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

, , , , ,

XSLT  (EXtensible Sytlesheet Language Transformations) is a tool that can be used to transform XML documents into other formats most commonly of which is XHTML. XSLT is a stylesheet that defines how to display or output the data from the XML. Using XSLT you can sort, filter, and manipulate the data as needed iterating of data elements and their child elements. Below is a short example of how to sort an XML data file based on 2 elements.

To start things off we need an xml data file. In our example we are going to use books. You will notice that in addition to the xml data we specify the xml-stylesheet to utilize which we will create next.

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

Next we will create an XSL Stylesheet that will be used to transform the XML Data into a XHTML page that displays the information in a table sorted by author followed by the title.

<?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>

In the above example we define the style sheet to iterate over each book element in the xml using the xsl:for-each tag. Then we immediately tell it to sort on the author field and secondly by the title field by use of the xsl:sort tag.

<xsl:sort select="author" />
<xsl:sort select="title" />

The end result is an html table as shown below:

Title Author Publisher Year
Warbreaker Brandon Sanderson TOR 2009
Changes Jim Butcher ROC 2010
First Lord’s Fury Jim Butcher ACE 2090
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

You can sort on as many elements as you want simply adding addtional xsl:sort tags. Full information on the available properties like order can be found at w3schools

, , , , ,