RE: [xsl] Reverse axis, reverse document order, xsl:for-each

Subject: RE: [xsl] Reverse axis, reverse document order, xsl:for-each
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 28 Feb 2008 10:22:29 -0000
XSLT 1.0 models the result of any path expression as a set of nodes in no
particular order. The semantics of xsl:for-each are that it processes this
set in the order determined by its xsl:sort specification; the default for
this is "document order".

You can reverse this using <xsl:sort select="position()" order="descending"
data-type="number"/>

The way the semantics are modelled changes significantly in XSLT 2.0, though
of course backwards compatiblity has been retained.

> Why is this so?

Depends who you ask. Committees move in mysterious ways. It can be hard to
work out why a decision was made even if you were present at all the
meetings - which in this case, I wasn't.

> And, last question, is there a way to have a pointer 
> (xsl:variable) to nodes in RDO without resorting to copying 
> or reconstructing? 

Not in 1.0: the type system only allows sets of nodes, not sequences. 2.0
changes that.

Michael Kay
http://www.saxonica.com/ 


> -----Original Message-----
> From: Michael Ludwig [mailto:mlu@xxxxxxxxxxxxx] 
> Sent: 28 February 2008 09:28
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Reverse axis, reverse document order, xsl:for-each
> 
> I want to process nodes collected on a reverse axis in 
> reverse document order (RDO). Using xsl:for-each, it doesn't 
> work. Why is this so? Why does xsl:for-each obliterate the 
> direction offered by the axis? Why does it revert reversion?
> 
> What precise situation does RDO apply to? Is it only for node 
> test immediately attached to the axis step?
> 
> And, last question, is there a way to have a pointer 
> (xsl:variable) to nodes in RDO without resorting to copying 
> or reconstructing? (See example two in the stylesheet below.)
> 
> I'm using XSL language version 1.0 with libxslt.
> 
> mludwig@forelle:~/xpg/Werkstatt/xsl-rdo > expand -t1 rdo.xml <Urmel>
>   <elm>eins</elm>
>   <elm>zwei</elm>
>   <elm>drei</elm>
> </Urmel>
> 
> mludwig@forelle:~/xpg/Werkstatt/xsl-rdo > expand -t1 rdo.xsl 
> <?xml version="1.0"?> <xsl:stylesheet version="1.0"
>   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>   <xsl:output method="text"/>
>   <xsl:template match="/">
>    <xsl:variable name="my-node" select=".//elm[ . = 'drei' ]"/>
>    <!-- one -->
>    <xsl:for-each select="$my-node/preceding-sibling::elm">
>     <xsl:value-of select="concat(. , '&#10;')"/>
>    </xsl:for-each>
>    <!-- two, same thing using a variable -->
>    <xsl:variable name="prec" 
> select="$my-node/preceding-sibling::elm"/>
>    <xsl:for-each select="$prec">
>     <xsl:value-of select="concat(. , '&#10;')"/>
>    </xsl:for-each>
>   </xsl:template>
> </xsl:stylesheet>
> 
> mludwig@forelle:~/xpg/Werkstatt/xsl-rdo > xsltproc rdo.xsl 
> rdo.xml eins zwei eins zwei
> 
> The output I want and expect is the reverse:
> zwei
> eins
> zwei
> eins
> 
> Michael

Current Thread