Microsoft XML SDK 2.6 - XSLT Developer's Guide

Sorting XML

Sorting is specified by adding <xsl:sort> elements as children to an <xsl:apply-templates> or an <xsl:for-each> element. The first <xsl:sort> child specifies the primary sort key, the second <xsl:sort> child specifies the secondary sort key, and so on. When an <xsl:apply-templates> or <xsl:for-each> element has one or more <xsl:sort> children, instead of processing the selected nodes in document order, it sorts the nodes according to the specified sort keys and then processes them in sorted order. When used in <xsl:for-each>, <xsl:sort> elements must occur first. When a template is instantiated by <xsl:apply-templates> and <xsl:for-each>, the current node list consists of the complete list of nodes being processed in sorted order.

<xsl:sort> has a select attribute whose value is an Expression. For each node to be processed, the expression is evaluated with that node as the current node and with the complete list of nodes being processed in unsorted order as the current node list. The resulting object is converted to a string; this string is used as the sort key for that node. The default value of the select attribute is ".", which will cause the string-value of the current node to be used as the sort key.

This string serves as a sort key for the node. The following optional attributes on <xsl:sort> control how the list of sort keys are sorted:

The sort must be stable: In the sorted list of nodes, any sub list that has sort keys that all compare equal must be in document order.

For example, suppose an employee database has the following form:

<employees>
  <employee>
    <name>
      <given>James</given>
      <family>Clark</family>
    </name>
    ...
  </employee>
</employees>

Then a list of employees sorted by name could be generated using:

<xsl:template match="employees">
  <ul>
    <xsl:apply-templates select="employee">
      <xsl:sort select="name/family"/>
      <xsl:sort select="name/given"/>
    </xsl:apply-templates>
  </ul>
</xsl:template>

<xsl:template match="employee">
  <li>
    <xsl:value-of select="name/given"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="name/family"/>
  </li>
</xsl:template>