getting next node in sorted node list

Here should go questions about transforming XML with XSLT and FOP.
Hamster
Posts: 1
Joined: Sat Oct 23, 2010 7:20 am

getting next node in sorted node list

Post 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.
adrian
Posts: 2879
Joined: Tue May 17, 2005 4:01 pm

Re: getting next node in sorted node list

Post 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
Adrian Buza
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
Post Reply