XSLT Reference
xsl:sort
Specifies a sort key for xsl:apply-templates or xsl:for-each, controlling the order in which nodes are processed.
<xsl:sort select="expression" order="ascending|descending" data-type="text|number"/>Description
xsl:sort is placed as an immediate child of xsl:apply-templates or xsl:for-each to define the sort order for node processing. It does not alter the source document; it only changes the sequence in which the processor visits the selected nodes.
Multiple xsl:sort elements can be nested to define compound sort keys: the first xsl:sort is the primary key, the second is the secondary key (used when the primary values are equal), and so on.
The select attribute is an XPath expression evaluated against each candidate node to produce its sort key. Omitting select defaults to the string value of the context node (equivalent to select="."). The data-type attribute controls whether comparison is lexicographic (text, the default) or numeric (number). When sorting numerically, the key is converted to a number; non-numeric strings sort as NaN, which typically appears first in ascending order.
Attributes
| Attribute | Type | Required | Description |
|---|---|---|---|
select | XPath expression | No | Sort key expression. Defaults to . (string value of context node). |
order | ascending / descending | No | Sort direction. Default is ascending. |
data-type | text / number / QName | No | Comparison type. Default is text. |
case-order | upper-first / lower-first | No | Case ordering for text comparisons. Processor-defined default. |
lang | language code | No | Language for locale-sensitive collation. |
Examples
Sort by numeric attribute
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product price="24.99">Gadget</product>
<product price="9.99">Widget</product>
<product price="49.99">Device</product>
<product price="4.49">Bolt</product>
</products>
Stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/products">
<sorted>
<xsl:apply-templates select="product">
<xsl:sort select="@price" data-type="number" order="ascending"/>
</xsl:apply-templates>
</sorted>
</xsl:template>
<xsl:template match="product">
<item price="{@price}"><xsl:value-of select="."/></item>
</xsl:template>
</xsl:stylesheet>
Output:
<sorted>
<item price="4.49">Bolt</item>
<item price="9.99">Widget</item>
<item price="24.99">Gadget</item>
<item price="49.99">Device</item>
</sorted>
Multi-key sort: last name then first name
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<people>
<person first="Alice" last="Smith"/>
<person first="Bob" last="Jones"/>
<person first="Anna" last="Smith"/>
<person first="Carol" last="Jones"/>
</people>
Stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/people">
<sorted>
<xsl:for-each select="person">
<xsl:sort select="@last"/>
<xsl:sort select="@first"/>
<person><xsl:value-of select="concat(@first, ' ', @last)"/></person>
</xsl:for-each>
</sorted>
</xsl:template>
</xsl:stylesheet>
Output:
<sorted>
<person>Bob Jones</person>
<person>Carol Jones</person>
<person>Alice Smith</person>
<person>Anna Smith</person>
</sorted>
Notes
xsl:sortelements must appear before any other content insidexsl:for-eachorxsl:apply-templates. Placing them after output instructions is a schema error.- When
data-type="number", the sort key is converted to a floating-point number. Values that cannot be converted becomeNaN; in ascending order,NaNvalues typically sort before any numeric value, but this is implementation-defined. - Text sorting is locale-sensitive in theory, but XSLT 1.0 has limited collation support. Use the
langattribute or processor-specific collation URIs for reliable locale-aware sorting. - The
position()function inside a sortedxsl:for-eachreflects the sorted position, not the original document position.