8. Sorting

The letters in the file collection.xml are not sorted in any particular way. Sometimes, however, you may need to sort data alphabetically or chronologically. This can be achieved by making use of the <xsl:sort> element. This element can only be used as a direct child of <xsl:for-each> and <xsl:apply-templates> (the latter element will be discussed later on in this tutorial). <xsl:sort> requires a select attribute which indicates the element that needs to be used as a basis for the sorting operation.

<xsl:sort> can sort data both alphabetically and numerically. By default, data are sorted alphabetically. If you want to make this explicit, you can use the data-type attribute with the value "text". To sort nodes numerically, use the data-type attribute with the value "number".

In addition, the elements can be sorted in a descending and an ascending order. This can be specified with the order attribute, which can take either the value "ascending" or "descending". The ascending order is the default value.

Note that the select attribute can only refer to elements in current context. Otherwise, you need to supply a path. If <sort> is included as a direct child of <xsl:for-each>, the path that you mention in the <sort> element must depart from the element that is mentioned in <xsl:for-each>.

The following stylesheet will sort the letters chronologically. Note that the elements <place>, <year> and <callnumber> are selected only if they are actually present. This is achieved with <xsl:if>.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="collection">

      <html>

      <head/>

      <body><p>
      <ul>

      <xsl:for-each select="body/letter">
          
      <xsl:sort select="year"/>
    

    <li> <b>From
      <xsl:value-of select="author"/>
      to <xsl:value-of
      select="recipient"/>

      </b> <br/>

      <xsl:if test="place">
        <xsl:value-of select="place"/> <br/>
      </xsl:if>

      <xsl:if test="year">
        <xsl:value-of select="year"/><br/>
      </xsl:if>

      <xsl:if test="callnumber">
        <xsl:value-of select="callnumber"/>
      </xsl:if>
      </li>

       </xsl:for-each>
      </ul>

  </p>
      </body>
      </html>

      </xsl:template>

</xsl:stylesheet>