Page 1 of 1

getting next node in sorted node list

Posted: Sat Oct 23, 2010 7:30 am
by Hamster
Hello,

Given a silly XML document:

Code: Select all


<alpha>
<letter>k</letter>
<letter>z</letter>
<letter>a</letter>
</alpha>
I have an xslt style sheet that iterates over each letter node in sorted order and prints out the letter:

Code: Select all


<xsl:for-each select="/alpha/letter">
<xsl:sort />
<xsl:value-of select="text()" />
</xsl:for-each>
That works fine, it just prints out a k z.

However, as the foreach is processing the letter k, I would also like it to print out the value of the next letter.

That's where I'm stuck. The following-sibling axis prints out document order, not node list order. I can use position() to get the index of the k node (in this case 2), but I have no idea how/where to use that to do (position() +1).

Can anyone help me work out how to get the next node in node list order, not document list order?

Many many thanks

H.

Re: getting next node in sorted node list

Posted: Tue Oct 26, 2010 11:45 am
by adrian
Hi,

In XSLT 2.0(needs a Saxon-HE/PE/EE transformer) it's a bit simpler. Sort it once and keep the result in a variable. Like this:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">

<xsl:variable name="sorted">
<xsl:for-each select="/alpha/letter">
<xsl:sort select="text()"/>
<xsl:element name="letter">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:for-each>
</xsl:variable>

<xsl:for-each select="$sorted/letter">
<xsl:text>(</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>) next[</xsl:text>
<xsl:value-of select="following-sibling::node()[1]"/>
<xsl:text>]</xsl:text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>
In XSLT 1.0 a solution is to sort it again at each step, like this:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:for-each select="/alpha/letter">
<xsl:sort select="text()"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>) next[</xsl:text>
<xsl:variable name="pos" select="position()"/>

<xsl:for-each select="/alpha/letter">
<xsl:sort select="text()"/>
<xsl:if test="position()=$pos+1">
<xsl:value-of select="text()"/>
</xsl:if>
</xsl:for-each>
<xsl:text>]</xsl:text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>
Regards,
Adrian