In Chapter 2, XPath core functions were introduced. In addition, XSLT has some functions of its own. While the core XPath functions are available to XSLT, the XSLT defined functions are not available to XPath when it is used beyond the confines of XSLT. The functions that we take a closer look at now are actually core XPath functions, but exist in the XSLT namespace.
The names of these functions usually give away what they do. Those we will cover here are:
- position()
- last()
- name()
- count()
We will also look at accessing nodes in a node-set by index.
position() and last()
In many cases, we will want to select nodes based on their position in a node-set. This is what we did in ListCharacters.xsl when we made the list of characters in Hamlet, to ensure that the last character did not have a comma after his name:
<xsl:if test="position()!=last()">, </xsl:if>
As well as checking against last(), we can check against any index into the node-set. It is this that means we do not need a first() function to match the last() function. Instead, we just look for a position() of 1. To apply a template only if there is only one matching elem node, we would use:
<xsl:template match="elem[position()='1' and position()=last()]">
Note that the first matching node has an index of 1, and not 0.
As well as using the position within a test, we can use the value of the position() function to number our nodes. Earlier, we looked at <xsl:number>, which provides us with a number relating to a node's position in the source tree. In contrast, position() provides a number relating to the position in a node-set, which might be after a sort operation. It can therefore be used to provide a number relating to a node's position in the result tree.
We can very easily demonstrate this difference by using both methods to number the books in our catalog. We will produce a table of book titles with the results of numbering using <xsl:number>
and position().
This is our stylesheet, position.xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">
<xsl:template match="/">
<TABLE BORDER="1">
<TR>
<TD>Title</TD>
<TD>position()</TD>
<TD>xsl:number</TD>
</TR>
<xsl:apply-templates select="Catalog/Book"/>
</TABLE>
</xsl:template>
<xsl:template match="Book">
<TR>
<TD><xsl:value-of select="Title"/></TD>
<TD align="center"><xsl:value-of select="position()"/></TD>
<TD align="center"><xsl:number/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
This is extremely simple. The template for the document root creates the table and applies the template for the <Book> elements. Each time the <Book> template executes, it adds a row to the table and puts in the book title with the result of applying <xsl:number> and position() to the current <Book> element.
The result of applying this stylesheet to catalog.xml looks like this:

Continued...