After learning the basics of XSLT one often wonders how to filter the XML data to returns data that contains a search string or has a value greater then or less than another value. To do this in XSL Stylesheets you can use take advantage of XPath in your xsl:foreach elements. Lets assume we have the following xml data as I used in my previous XSLT sorting article modified so that the year and publisher values are now attributes and not sub elements.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="sorted_books.xsl"?>
<books>
   <book year="2007" publisher="DAW">  
	<author>Patrick Rothfuss</author>
	<title>The Name of the Wind</title>
   </book>
   <book year="2004" publisher="EOS">  
	<author>Trudi Canavan</author>
	<title>The Magicain's Guild</title>
   </book>
   <book year="2009" publisher="Orbit">  
	<author>Trudi Canavan</author>
	<title>The Magicain's Apprentice</title>
   </book>
   <book year="2009" publisher="ACE">  
	<author>Jim Butcher</author>
	<title>First Lord's Fury</title>
   </book>
   <book year="2010" publisher="ROC">  
	<author>Jim Butcher</author>
	<title>Changes</title>
   </book>
   <book year="2009" publisher="TOR">  
	<author>Brandon Sanderson</author>
	<title>Warbreaker</title>
   </book>
</books>

Next we’ll create a basic XSL Stylesheet that will simply display our data in a table.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:template match="/">
<html>
<head><title>My Books</title>
</head>
<body>
<table width="100%" border="1">
  <THEAD>
   <TR>
       <TD width="50%"><B>Title</B></TD>
       <TD width="50%"><B>Author</B></TD>
       <TD width="50%"><B>Publisher</B></TD>
       <TD width="50%"><B>Year</B></TD>
   </TR>
  </THEAD> 
  <TBODY>
   <xsl:for-each select="books/book">
    <xsl:sort select="author" />
    <xsl:sort select="title" />
    <TR>	  
       <TD width="25%"><xsl:value-of select="title" /></TD>
       <TD width="25%"><xsl:value-of select="author" /></TD>
       <TD width="25%"><xsl:value-of select="@publisher" /></TD>
       <TD width="25%"><xsl:value-of select="@year" /></TD>
    </TR>
   </xsl:for-each>
  </TBODY>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

This stylesheet will give us the following output:

Title Author Publisher Year
Warbreaker Brandon Sanderson TOR 2009
Changes Jim Butcher ROC 2010
First Lord’s Fury Jim Butcher ACE 2009
The Name of the Wind Patrick Rothfuss DAW 2007
The Magicain’s Apprentice Trudi Canavan Orbit 2009
The Magicain’s Guild Trudi Canavan EOS 2004

Now for applying our filters, you will notice that in the xsl:for-each we use the select attribute to define the XML nodes to iterate over. This value books/book is an XPath value saying all elements of path books > book. To filter we simply modify the XPath. For example lets say we want all books published after 2008. To do this we would use the following XPath books/book[(number(@year) > 2008)]. This string says select all book elements that have an attribute of year greater then 2008. The xsl:for-each statement would look like the following.

<xsl:for-each select="books/book[(number(@year) > 2007)]">
    <xsl:sort select="author" />
    <xsl:sort select="title" />
    <TR>	  
       <TD width="25%"><xsl:value-of select="title" /></TD>
       <TD width="25%"><xsl:value-of select="author" /></TD>
       <TD width="25%"><xsl:value-of select="@publisher" /></TD>
       <TD width="25%"><xsl:value-of select="@year" /></TD>
    </TR>
</xsl:for-each>

This would render the following output:

Title Author Publisher Year
Warbreaker Brandon Sanderson TOR 2009
Changes Jim Butcher ROC 2010
First Lord’s Fury Jim Butcher ACE 2009
The Magicain’s Apprentice Trudi Canavan Orbit 2009

If we wanted our filter to be even more complicated we could use multiple attributes or child elements in are select statement for example we could only want books published after 2008 and only display authors that contain the letter i. Doing this we would make use of the XSL function contains to compare strings as well as the and keyword to join are statements. The finished XPath would be books/book[(number(@year) > 2007) and contains(author, 'i')] with the output being the following XHTML.

Title Author Publisher Year
Changes Jim Butcher ROC 2010
First Lord’s Fury Jim Butcher ACE 2009
The Magicain’s Apprentice Trudi Canavan Orbit 2009

That is pretty much all there is to it. There are many functions available to utilize in your XPath query strings and can be referenced here. For further details also visit the w3schools website’s XPath tutorial

, , , , ,