following-sibling in a sorted for-each

Here should go questions about transforming XML with XSLT and FOP.
SchlauFuchs
Posts: 2
Joined: Wed Feb 15, 2006 2:57 pm

following-sibling in a sorted for-each

Post by SchlauFuchs » Wed Feb 15, 2006 3:10 pm

Hello,

I have an XML file which I transform to a tree-style document. I have to sort the xml nodes in a for-each loop. The display of a node is dependend on the nodes before and after it - see it like an expansion of a explorer folder structure - the last element of the tree has a leaf end.

Code: Select all


|- a node
| |- a subnode
| \- another sub node
\- last node
But I found that sorting doesn't affect the real order of an node, so even if the element is first() it can have a preceeding-sibling (in the unsorted order), as for last() there can be a follwing-sibling. But I now need to access the element before & after in the sorted order, to know what icon to display. How?

Kindly regards,
SF[/code]

george
Site Admin
Posts: 2101
Joined: Thu Jan 09, 2003 2:58 pm

Post by george » Wed Feb 15, 2006 4:07 pm

Hi,

You can place the nodes in the sorthed order in a variable and then loop over that, thus you will get the preceding and following sibling axes work as you expect. Below there is a full working sample (XML, XSLT and result) for XSLT 2.0, if you want that in XSLT 1.0 then you need to use the node-set funtion to get the variable result as a set of nodes instead of a result tree fragment.

Code: Select all


<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="sorted">
<xsl:apply-templates mode="copy" select="//node">
<xsl:sort select="@id"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:for-each select="$sorted/*"> [preceding sibling]<xsl:value-of
select="preceding-sibling::*[1]/@id"/> [current]<xsl:value-of select="@id"/> [following sibling]<xsl:value-of select="following-sibling::*[1]/@id"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template mode="copy" match="node">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

Code: Select all


<test>
<node id="3"/>
<node id="4"/>
<node id="2"/>
<node id="5"/>
<node id="1"/>
</test>

Code: Select all


 [preceding sibling] [current]1 [following sibling]2
[preceding sibling]1 [current]2 [following sibling]3
[preceding sibling]2 [current]3 [following sibling]4
[preceding sibling]3 [current]4 [following sibling]5
[preceding sibling]4 [current]5 [following sibling]
Best Regards,
George

SchlauFuchs
Posts: 2
Joined: Wed Feb 15, 2006 2:57 pm

Post by SchlauFuchs » Wed Feb 15, 2006 6:21 pm

Thank you, that helped! :)

Ciao!
SF

Post Reply