LordAro
LordAro

Reputation: 1289

sorting by position with XSL

I'm trying to use xsl:sort to invert a list in XML/XSLT, but it doesn't appear to be doing anything.

example.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text" encoding="UTF-8"/>
  <xsl:template match="/">
   <xsl:for-each select="CONTAINER/PARAM">
    <xsl:sort data-type="number" order="descending" select="position()"/>
    Battleaxe = <xsl:value-of select="name()" /><xsl:number value="position()" format="1" />
   </xsl:for-each>
  </xsl:template>
 </xsl:stylesheet>

example.xml

<CONTAINER>
 <PARAM>foo</PARAM>
 <PARAM>bar</PARAM>
 <PARAM>baz</PARAM>
 <PARAM>quix</PARAM>
</CONTAINER>

Expected result:

Battleaxe = PARAM4
Battleaxe = PARAM3
Battleaxe = PARAM2
Battleaxe = PARAM1

Actual result:

Battleaxe = PARAM1
Battleaxe = PARAM2
Battleaxe = PARAM3
Battleaxe = PARAM4

If it helps, I'm using xsltproc, version:

Using libxml 20903, libxslt 10117 and libexslt 813
xsltproc was compiled against libxml 20626, libxslt 10117 and libexslt 813
libxslt 10117 was compiled against libxml 20626
libexslt 813 was compiled against libxml 20626

When running with xsltproc --verbose, I see no mention of sorting anywhere in the output

I've got to be missing something obvious here...

EDIT:

OK, looks like position() is always in ascending order, even if you previously reversed it. I guess that makes sense

This differs to How to do an XSL:for-each in reverse order in that I have no such id attribute and just want to use some positional based logic. Is there something like a length() function I can use to reverse it manually?

Upvotes: 0

Views: 1037

Answers (2)

Michael Kay
Michael Kay

Reputation: 163458

In the xsl:sort/@select expression, the context sequence is the unsorted sequence, so position() gives you the position of an item in its original unsorted order. Hence sorting with select="position()" order="descending" data-type="number" reverses the input order.

Within the body of the xsl:for-each, by contrast, position() gives you the position of the item in the sorted sequence.

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167696

If you want to have the sequence of numbers 4, 3, 2, 1 then instead of position() output/compute last() - position() + 1. But you don't have to sort for doing that.

Upvotes: 1

Related Questions