Articles   Dev Forums   Personalize   Favorites   Member Login        Active Users:  54
DevASP - ASP and XML Articles, Samples, Toturials, Sample Chapters and resources for Developers Thursday, November 20, 2008
Home
Articles & Samples
Dev Search
Dev Forum
Add a Listing
Sample Chapters
Directory Feed
Link to US
Contact

Search Directory
Applications
Articles & Samples
Components
Community
Database
Developer Sites
Downloads
Hosting Services
Introduction
Knowledge Base
Sample Chapters
WebCasts

Trusted by over 7 million customers!
ASP Directory
Applications
Articles & Samples
Components
Developer Sites
Knowledge Base
Sample Chapters
WebCasts
XML Directory
Applications
Articles & Samples
Developer Sites
Error, Bugs & Fixes
Downloads
Introduction
Knowledge Base
Sample Chapters
WebCasts

XSLT Functions


After that little aside to understand a couple of important areas of XSLT, we can get back to what
XSLT can do for us. Now that we have covered the most important elements, we can cover the
most important functions.

 

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:

 

q        position()

q        last()

q        name()

q        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:

 


In this case, the results are the same since the node-set produced by the select attribute in the <xsl:apply-templates> element will be in document order. However, we can sort the catalog alphabetically by changing the template for the document root (number.xsl):

 

<xsl:template match="/">

<TABLE BORDER="1">

<TR>

<TD>Title</TD>

<TD>position()</TD>

<TD>xsl:number</TD>

</TR>

<xsl:apply-templates select="Catalog/Book">

<xsl:sort select="Title"/>

</xsl:apply-templates>

</TABLE>

</xsl:template>

 

Now the results will be somewhat different:

 

 

The position() function has produced numbering in the order of the node-set provided to the <Book> template (which is also the order in the result tree), while the <xsl:number> element has kept the numbering as it was in the source tree (so each title is numbered as it was in the previous example).


name()

The name() function merely returns the name of the node. If applied to a node-set rather than a node, the optional node parameter can identify the node required. Where there is more than one match, the function returns the first.

 

There are often occasions when you want to display a node name. For example, I often use XSLT stylesheets to document XML Schemas. In one of these, I want to display the facets of an element. Don't worry if you are not familiar with XML Schema, the important thing is that each facet is defined by its element name and the value of its value attribute. An extract of the stylesheet I use is:

 

<table>

<xsl:for-each select="*">

<tr>

<td><xsl:value-of select="name()"/>:</td>

<td><xsl:value-of select="@value"/></td>

</tr>

</xsl:for-each>

</table>

 

We therefore list each facet name and value attribute value in two columns in a table.

count()

The final function we will consider here is the count() function, which returns the number of nodes in a node-set.

 

In the book catalog, catalog.xml, we could provide a template to list the titles of all the books with more than one author:

 

<xsl:template match="Book[count(//Authors)>1]">

<xsl:value-of select="Title"/>

</xsl:template>

 

Or, we might want to sort the books by the number of authors (CountAuthors.xsl):

 

<xsl:stylesheet

version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

<xsl:template match="/">

<xsl:apply-templates select="Catalog"/>

</xsl:template>

 

<xsl:template match="Catalog">

<xsl:for-each select="Book">

<xsl:sort select="count(Authors/Author)" data-type="number"/>

<P>

<xsl:value-of select="Title"/> has

<xsl:value-of select="count(Authors/Author)"/> author(s)

</P>

</xsl:for-each>

</xsl:template>

 

</xsl:stylesheet>

 

The result will be a list of books sorted in increasing number of authors order, and saying how many authors there are in each.


Summary

In this chapter, we have learnt the basics of XSLT through discussion and examples. In particular, we have seen:

 

q        How XSLT is a declarative language with procedural elements, matching XPath expressions to apply templates to nodes in the source tree, while including control flow elements to provide the procedural aspects.

q        The push and pull models, and where each is most suitable. We have also seen that most stylesheets will use some combination of these.

q        A number of the elements used in XSLT, and how we can write useful stylesheets with just this subset of the language.

q        A few of the functions built into the language, and how we can use these to give more control over our processing.

q        How the built-in template rules ensure that all nodes are processed (unless we over ride them) and how XSLT knows which rule to apply when there is a conflict.

 

Before we move on to more advanced XSLT processing, why not try a few stylesheets of your own, perhaps gathering more statistics about Hamlet or displaying the book catalog in different ways?






DevASP - Privacy - Disclaimer
Copyright © 2008 DevASP.com