xsl-list
[Top] [All Lists]

Release Date vs. Highlight Until Date

2004-09-21 09:34:39
For testing I am using an extension function to get sysdate and a variable
instead of a parameter; hopefully I can fix that later.  I am not sure why
xsl:for-each is not recommended, but it seems like I should do this with
xsl:template, xsl:call-template, xsl:apply-templates and/or whatever else is
appropriate, I just don't know how, especially "breaking out of the loop"
(comments below)

There is some redundancy in the XPath statements (for instance, the variable
$remaining is populated with something very similar to the for-each below it)
- how do I avoid that?

Thanks again,

   -John

<xsl:variable name="sysdate" select="shcutil:Now()" />
<xsl:variable name="sysdatenum" select="concat( substring-before( $sysdate,
'T' ), substring-after( $sysdate, 'T' ))" />

<xsl:template match="*" mode="main">

<!-- after outputing the "highlighted" records, this number of non-highlighted
records should be output -->

  <xsl:variable name="remaining" select="5 - count( 
//item[(_at_)template='tmpnews'
and number( concat( substring-before( sc:fld( 'highlightuntil', . ), 'T' ),
substring-after( sc:fld( 'highlightuntil', . ), 'T' ))) &gt; $sysdatenum] )" />

<!-- this seems to work -->

  <xsl:for-each select="//item[(_at_)template='tmpnews' and number( concat(
substring-before( sc:fld( 'highlightuntil', . ), 'T' ), substring-after(
sc:fld( 'highlightuntil', . ), 'T' ))) &gt; $sysdatenum]">
   <xsl:sort order="descending" select="@highlight"/>
         <strong><xsl:value-of select="sc:fld( 'highlightuntil', . )" />
<xsl:value-of select="sc:path(.)" /></strong><br />
  </xsl:for-each>

<!-- I am not sure how to make this one break out of the loop when $remaining
is hit -->

  <xsl:for-each select="//item[(_at_)template='tmpnews' and number( concat(
substring-before( sc:fld( 'highlightuntil', . ), 'T' ), substring-after(
sc:fld( 'highlightuntil', . ), 'T' ))) &lt;= $sysdatenum]">
    <xsl:sort order="descending" select="@releasedate"/>
          <xsl:value-of select="sc:fld( 'releasedate', . )" /> <xsl:value-of
select="sc:path(.)" /><br />
  </xsl:for-each>
</xsl:template>



---------- Forwarded message ----------
From: Robert Koberg <rob(_at_)koberg(_dot_)com>
Date: Mon, 20 Sep 2004 17:56:01 -0700
Subject: Re: [xsl] Release Date vs. Highlight Until Date
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com

xsl-list wrote:

Thanks for your suggestions.  I am not sure the CMS vendor supports XSL 2.0.
After looking more at the system I think I'll implement an XSL extension to
retrieve sysdate instead of passing it everywhere I need it.  I've been
digging deeper and found that the dates are stored as yyyyMMddTHHmmss, which 
I
don't think is xs:datetime format but should be pretty easy to parse/sort, or
convert to another format for parsing/sorting.



It is the XML Schema date time or xs:dateTime datatype. You are 
lucky -- this is the easiest to sort, since it allows for simple 
string sorting. You would do something like:

<xsl:template match="items">
  <xsl:apply-template select="item">
    <xsl:sort select="@release-date"/>
  </xsl:apply-templates>
</xsl:template>

Therefore, since a single XML document contains both the IA and the content, 
I
think I can do something like (half code, half psuedo-code):

<xsl:variable name="sysdate" select="me:function" />



personally, I would avoid extension functions as much as humanly
possible (you don't need them -- I never use them in the CMS, but do
when offline for batch processing).

Is it possible to write a single XPath query that merges the equivalent of 
the
two XPath queries below (excuse my attempt at syntax) such that an
xsl:for-each with that as select will first process the elements matching the
first condition, then those matching the second condition?

//item[(_at_)highlight_date &lt; $sysdate]




this works, but stay away from xsl:for-each until you uinderstand 
what you are doing.

//item

Also, to ensure I don't get the same record twice, do I just reverse the 
first
condition in the second condition?  Something like:

//item[(_at_)highlight_date &lt; $sysdate]

//item[(_at_)highlight_date &gt;= $sysdate]


You would want to apply-templates like I have shown above then you 
can check the position of the node (continuing on my XSL above):

<xsl:template match="item">
  <xsl:if test="position() &lt; 6">
    <xsl:apply-templates/>
  </xsl:if>
</xsl:template>

<>
I think that for performance I wouldn't want this combined query to return
more than 5 records. It seems like this would have to do with
position(), but
that can only apply before the sort, and I want the 5 records after
sort. Any
suggestions? maybe a recursive function? anyway, I have to consider
alternatives for performance.

Then within the xsl:for-each I need to sort such that those records
matched by
the highlight_date query appear first - any suggestions there?
Now you can can all see how lost I am.

No, you are getting it, but heading in a wrong direction. Stay away from
xsl:for-each.

best,
-Rob