XSLT provide an <xsl:sort> statement to permit ordering of XML nodes on one or multiple elements. Its general format is shown below.
|
<xsl:sort select="node" order="ascending|descending" data-type="text|number" case-order="upper-first|lower-first" /> |
The select attribute names the node on which sorting takes place, order gives whether the sort is in ascending or descending order (ascending is the default), data-type specificies whether sorting should treat the element as text (the default) or numeric data, and case-order determines whether upper-case characters are sorted ahead of matching lower-case characters.
Sorting is applied to a node list that has been selected through an <xsl:apply-templates> or <xsl:for-each> element. The sort element is placed inside the associated node-list selection:
<xsl:apply-templates select="expression"> <xsl:sort select="node"/> ... </xsl:apply-templates> or <xsl:for-each select="expression"> <xsl:sort select="node"/> ... </xsl:for-each>
Multiple <xsl:sort/> statements can be stacked one after another to cause major and minor sorts. That is, the first statement gives the primary sort order, the second statement sorts elements within the primary sort order, the third statement sorts elements within the second sort order, and so forth.
The following button shows the results of arranging the Books.xml information in descending order by publication year, within which books are in descending order by price.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<style>
table {border-collapse:collapse}
tr#head {background-color:#E6E6E6}
td {padding:3px}
td#title {font-style:italic}
</style>
<h3>Books Ordered by Year and Price</h3>
<table border="1">
<tr id="head">
<th>ISBN</th>
<th>Title</th>
<th>Author</th>
<th>Publisher</th>
<th>Year</th>
<th>Price</th>
</tr>
<xsl:for-each select="books/book">
<xsl:sort select="year" data-type="number" order="descending"/>
<xsl:sort select="price" data-type="number" order="descending"/>
<tr>
<td><xsl:value-of select="isbn"/></td>
<td id="title"><xsl:value-of select="title"/></td>
<td>
<xsl:value-of select="author/lastname"/>, 
<xsl:value-of select="author/firstname"/>
</td>
<td><xsl:value-of select="publisher"/></td>
<td><xsl:value-of select="year"/></td>
<td><xsl:value-of select="format-number(price, '$ ##0.00')"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
For both the <year> and <price> nodes data-type is specified as "number" to override default treatment of the data as text characters. Also, order="descending" overrides default ascending sequence.