Processing Nodes by Position
Problem
You want to process nodes in a sequence that is a function of their position in a document or node set.
Solution
Use xsl:sort
with the select set to the
position( )
or last( )
functions. The most trivial application of this example processes
nodes in reverse document order:
<xsl:apply-templates>
<xsl:sort select="position( )" order="descending" data-type="number"/>
</xsl:apply-templates>or:
<xsl:for-each select="*">
<xsl:sort select="position( )" order="descending" data-type="number"/>
<!-- ... -->
</xsl:for-each>Another common version of this example traverses a node set as if it were a matrix of a specified number of columns. Here, you process all nodes in the first column, then the second, and then the third:
<xsl:for-each select="*">
<xsl:sort select="(position( ) - 1) mod 3" />
<!-- ... -->
</xsl:for-each>Or, perhaps more cleanly with:
<xsl:for-each select="*[position( ) mod 3 = 1]">
<xsl:apply-templates
select=". | following-sibling::*[position( ) < 3]" />
</xsl:for-each>Sometimes you need to use position( ) to separate
the first node in a node set from the remaining nodes. Doing so lets
you perform complex aggregation operations on a document using
recursion. I call this example
recursive-aggregation.
The
abstract form of this example follows:
<xsl:template name="aggregation"> <xsl:param name="node-set"/> <xsl:choose> <xsl:when test="$node-set"> <!--We compute some function of the first element that produces a value that we want to aggregate. ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access