472,133 Members | 1,453 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,133 software developers and data experts.

XSL sort/if confusion

6
Hi all,

This is a small issue to make things prettier, but we all know how important that can be!

I had an xsl:if to check if a node was the last one in a collection of nodes and if it was a horizontal divider would not be displayed underneath it. This worked a treat but now I'm trying to sort my data using xsl:sort. The if statement technically still works but now the node identified by last() could be anywhere in the output order. I only want to remove the horizontal divider at the end.

Does anyone have any suggestions on how I can alter my if statement to reflect this? I imagine it is going to have to check that it is the latest year/month/day against every other sibling but I can't figure out how to do this properly.

My sort:
Expand|Select|Wrap|Line Numbers
  1. <xsl:apply-templates select="primarycontent" mode="_1">
  2.   <!-- Break down into components and sort ascending as a number -->
  3.   <xsl:sort data-type="number" select="substring(detaildate,7,4)"/>
  4.   <!-- year  -->
  5.   <xsl:sort data-type="number" select="substring(detaildate,4,2)"/>
  6.   <!-- month -->
  7.   <xsl:sort data-type="number" select="substring(detaildate,1,2)"/>
  8.   <!-- day   -->
  9. </xsl:apply-templates>
My xsl:if that worked before:
Expand|Select|Wrap|Line Numbers
  1. <xsl:if test=".!=/page/primarycontent[last()]">
  2.   <div class="divider2"></div>
  3. </xsl:if>
Any suggestions?
Nov 6 '08 #1
7 4910
Dormilich
8,658 Expert Mod 8TB
idea – you could store the node set in a variable and test the variable's last element.... like <xsl:if test="$var[last()]"> (something like that)

regards
Nov 6 '08 #2
otis
6
That sounds interesting Dormilich... how would I store the sorted node set in a variable? I have to be honest, this is my first major foray into manually writing XSLT!
Nov 6 '08 #3
Dormilich
8,658 Expert Mod 8TB
without any testing I'd say
Expand|Select|Wrap|Line Numbers
  1. <xsl:template match="..." mode="_1">
  2.   <xsl:variable name="var" select="."/> // change name as desired
  3. // further code here
  4. </xsl:template>
at least that looks sensible to me (the element passed over to the template should be already sorted (that's what I assume after your apply-templates call)).

regards

PS you may have to declare the variable globally
Nov 6 '08 #4
jkmyoung
2,057 Expert 2GB
A couple ideas:
Use a for-each to sort, and then use apply-templates. You could pass in a parameter to see if it's the last one.
eg:

Expand|Select|Wrap|Line Numbers
  1. <xsl:for-each select="primarycontent"> 
  2.   <!-- Break down into components and sort ascending as a number --> 
  3.   <xsl:sort data-type="number" select="substring(detaildate,7,4)"/> 
  4.   <!-- year  --> 
  5.   <xsl:sort data-type="number" select="substring(detaildate,4,2)"/> 
  6.   <!-- month --> 
  7.   <xsl:sort data-type="number" select="substring(detaildate,1,2)"/> 
  8.   <!-- day   --> 
  9.   <xsl:apply-templates select="." mode="_1">
  10.     <xsl:with-param name="last" select=".=last()"/>
  11.   </xsl:apply-templates> 
  12. </xsl:for-each>
  13. ...
  14. ...
  15. <xsl:template match="primarycontent" mode="_1">
  16.   <xsl:param name="last">
  17.  
Nov 6 '08 #5
otis
6
idea – you could store the node set in a variable and test the variable's last element.... like <xsl:if test="$var[last()]"> (something like that)

regards
Unfortunately, my attempt at this meant every single one thought that it was $var[last()] because I had to put the variable declaration inside the xsl:template for the repeating group that has been sorted... so "." is a single node rather that the sorted group. I also tried "./..".

With the way it is sorted and that fact that xsl:variable is not valid within xsl:apply-templates I don't see another place to put the xsl:variable where it would be effective. Am I being really useless on this one?

jkmyoung, I don't understand your suggestion but I'll give it a try!
Nov 6 '08 #6
jkmyoung
2,057 Expert 2GB
Rechecked the concept. You don't even need a parameter.
Expand|Select|Wrap|Line Numbers
  1. <xsl:for-each select="your nodes...">
  2.   <xsl:sort select="..."/>
  3.   <xsl:sort select="..."/>
  4.   <xsl:sort select="..."/>
  5.   <xsl:apply-templates select="."/>
  6. </xsl:for-each>
  7.  
  8. <xsl:template match="nodes">
  9. ...
  10.   <xsl:if test="position() != last()">
  11.      display your horizontal divider
  12.   </xsl:if>
  13.  
  14.  
The for-each automatically reorders the nodes with the sorting. Then you can just check if the node is the last one the same way that you used to.
Nov 6 '08 #7
otis
6
Unfortunately when I try that position() and last() are always equal to 1 because you're only passing a single node to the apply-templates request.

However, I moved the if statement into the for-each as shown below and it worked a treat!

Thanks for your help guys.

Expand|Select|Wrap|Line Numbers
  1. <xsl:for-each select="primarycontent">
  2.   <!-- Break date down into components and sort ascending as a number -->
  3.   <xsl:sort data-type="number" select="substring(detaildate,7,4)"/>
  4.   <!-- year  -->
  5.   <xsl:sort data-type="number" select="substring(detaildate,4,2)"/>
  6.   <!-- month -->
  7.   <xsl:sort data-type="number" select="substring(detaildate,1,2)"/>
  8.   <!-- day   -->
  9.   <xsl:apply-templates select="." mode="_1" />
  10.   <!-- Add a conditional test to hide the divider for the last entry -->
  11.   <xsl:if test="position() != last()">
  12.     <div class="divider2"></div>
  13.   </xsl:if>
  14. </xsl:for-each>
Nov 7 '08 #8

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

6 posts views Thread by alexhong2001 | last post: by
7 posts views Thread by Steve Crawford | last post: by
2 posts views Thread by siromega | last post: by
2 posts views Thread by Randy | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.