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>