I need to iterate over the elements of an XML file in sorted order of their language field many times. What I try is to get an iterable list of the languages as follows:
<xsl:variable name="languages">
<xsl:for-each select="elem/FIELD[@NAME='language']">
<xsl:sort select="."/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
While I can verify with a
<xsl:value-of select="$languages"/>
that the sorting works, I cannot iterate like
<xsl:for-each select="$langauges">...</xsl:for-each>
because the XSL processor complains that select expression does not evaluate to a node set.
Edit: Not sure whether this is important, but I have
<xsl:output encoding="UTF-8"
method="xml"
media-type="text/xml"
indent="yes" />
What do I have to insert in the loop to make the result into a node set? Is this at all possible?
Given you say that
I assume you're using XSLT 1.0 rather than 2.0. In XSLT 1.0 when you declare a variable with content rather than a
select
attribute, the resulting variable contains something called a "result tree fragment" rather than a node set. You can applyvalue-of
andcopy-of
to a RTF to send it to the output but you can't navigate into it using XPath expressions.Most XSLT processors provide some sort of extension function to convert a RTF into a real node set - msxsl for the Microsoft processor or exslt for most others.
In XSLT 2.0 there is no distinction between result tree fragments and node sets - they're both treated as sequences - so you don't need the extension function in that version.
You need to convert the result tree fragment in your variable into a node-set, using the EXSLT node-set() function.
XSLT 1.0 allows you to process a node-set in sorted order, but it doesn't allow you to save a sorted sequence in a variable (the data model only has sets, not sequences). The only way you can save sorted data in 1.0 is to construct a new tree containing copies of the original elements in a different order, and then use the node-set() extension to make this tree processable.
This changes in XSLT 2.0, which has a data model based on sequences. In 2.0 you can save a sorted sequence of nodes in a variable without copying the nodes into a new tree.
Try the following:
To declare variable:
And to loop: