Table of contents
- Introduction
- Prerequisites
- Setting up the environment
- XSLT basics
- Displaying the XML data
- Using the XSL templates
- XSL variables and parameters
- Sorting and filtering (the xsl:key element and
generate-id() function)
- Grouping the data
- Pagination
- XSLT 2.0 functions
- Practice
- Points of interest
- Conclusion
Introduction
XSLT stands for XSL Transformations. XSL is well known as Extensible Stylesheet Language which is used for
XML documents. XSLT is a language used to describe a transformation that can be applied to a set of
XML documents to generate a new set of transformed HTML documents.
The following figure shows the flow of the XSLT processor.

From the above figure it is clear that the XSLT processor takes the XML file as input,
and processes it based on the XSLT instructions into the HTML document.
In this article we go through some code snippets to understand the latest version of
XSLT programming using Saxon API for .NET.
Prerequisites
In order to execute the code, we need to have the following:
- .NET Framework
- Visual Studio
- Saxon.dll for .NET
Setting up the environment
In order to compile the XSLT 2.0 code we’re supposed to use the Saxon .NET library
which is available here.
Once the Saxon .NET library is available we can include it in our project by adding it as
a reference to the project.
The following method takes the XML, XSLT file path names and the xsl-param values as parameters and return the parsed
XML value into string in HTML format.
We can display the obtained HTML output in a Literal control.
public static string transformXml(string sourceUri, string xsltUri, double CurrentPage,string category)
{
Processor processor = new Processor();
XdmNode input = processor.NewDocumentBuilder().Build(new Uri(sourceUri));
XsltTransformer transformer = processor.NewXsltCompiler().Compile(new Uri(xsltUri)).Load();
transformer.InitialContextNode = input;
transformer.SetParameter(new QName("", "", "currentPage"), new XdmAtomicValue(CurrentPage));
transformer.SetParameter(new QName("", "", "category"), new XdmAtomicValue(category));
transformer.BaseOutputUri = new Uri(xsltUri);
Serializer serializer = new Serializer();
StringWriter sw = new StringWriter();
serializer.SetOutputWriter(sw);
transformer.Run(serializer);
return sw.ToString();
}
Code snippet 1.
XSLT the basics
XSLT contains the following elements:
xsl:template | xsl:param |
xsl:calltemplate | xsl:sort |
xsl:choose | xsl:attribute |
xsl:for-each-group | xsl:valueof |
The complete list of XSL elements reference is available here: http://www.saxonica.com/documentation/xsl-elements/intro.xml.
As we have seen the list of some of the commonly used XSLT elements, now we’ll try to perform some of the most frequently used operations.
Displaying XML data
The xsl:foreach element helps to loop all the elements of the
XML file and display them. In the below example we’ll use the xsl:foreach element to display data in tabular format.
- Create a new empty web project using Visual Studio.
- Add the XML file to the project which is available for download with this article.
- Add a class file and copy code snippet 1 to the class file and add the required reference libraries.
- Add a new XSLT file to your project and copy the following code:
- For the time being exclude the parameters in code snippet 1.
<xsl:template match ="books">
<table>
<tr>
<th align ="left">S.No</th>
<th align ="left">Title</th>
<th align ="left">Author</th>
<th align ="left">Price</th>
<th align ="left">Category</th>
</tr>
<xsl:for-each select ="book">
<tr>
<td>
<xsl:number/>
</td>
<td>
<xsl:value-of select ="title"/>
</td>
<td>
<xsl:value-of select ="author"/>
</td>
<td>
<xsl:value-of select ="price"/>
</td>
<td>
<xsl:value-of select ="@category"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
Code Snippet 2.
- Add a new web (.aspx) page to the project and drag a
Literal control to the page.
- Add the following code to the
Page_Load function:
string sourceUri = Server.MapPath("books.xml");
string xsltUri = Server.MapPath("code1.xslt");
string text = SaxonDemo.transformXml(sourceUri, xsltUri);
Literal1.Text = text;
Code Snippet 3.
Repeat the above steps for all other examples described below.
Using the XSL templates
XSL templates are similar to function/method(s) in general programming languages.
XSL templates are used to define code which can
be used repeatedly throughout. XSL templates use xsl:variable elements to declare and store variables just like in traditional programming.
The xsl:param element is used in xsl:template to pass parameters to templates.
In order to understand how xsl:template can be used to define a piece of code we’ll just make small modifications in code snippet 2.
We’ll declare the xsl:foreach element code separately in a template named “results” and then we’ll call the template using
the xsl:call template element as shown below:
- Create a template named
results.
<xsl:template name ="results">
<xsl:for-each select ="book">
<tr>
<td>
<xsl:number/>
</td>
<td>
<xsl:value-of select ="title"/>
</td>
<td>
<xsl:value-of select ="author"/>
</td>
<td>
<xsl:value-of select ="price"/>
</td>
<td>
<xsl:value-of select ="@category"/>
</td>
</tr>
</xsl:for-each>
</xsl:template>
- Call the above template using the
xsl:calltemplate element.
<xsl:template match ="books">
<table>
<tr>
<th align ="left">S.No</th>
<th align ="left">Title</th>
<th align ="left">Author</th>
<th align ="left">Price</th>
<th align ="left">Category</th>
</tr>
<xsl:call-template name ="results"></xsl:call-template>
</table>
</xsl:template>
Code Snippet 4.
XSL variables and parameters
The xsl:variable element is used to store data which can be used in the program.
The ‘$’ symbol is used to access the declared variable. The following code shows the usage of
the variable.
- Declare a variable.
<xsl:variable name ="totalRecords">
<xsl:for-each select ="/">
<xsl:value-of select ="count(books/book)"/>
</xsl:for-each>
</xsl:variable>
- Access the variable.
<tr>
<td colspan="5">
<b>Total No of Record(s):<xsl:value-of select ="$totalRecords"/>
</b>
</td>
</tr>
Code Snippet 5.
xsl:parameter element(s) are used to pass parameters to xsl:template.
The xsl:call template element is used to call xls:template with parameters.
In order to demonstrate the xsl:parameter element we’ll use an alternate way to display the total number of record(s) using
XSL parameter(s).
- Define a template with a parameter using the
xsl:param element.
<xsl:template name ="results">
<xsl:param name ="ttlrds"/>
!!-------- previously used foreach loop code goes here-------------!!
<tr>
<td colspan="5">
<b>
Total No of Record(s):<xsl:value-of select ="$ttlrds"/>
</b>
</td>
</tr>
</xsl:template>
- Call the template using the
xsl:call template and xsl:with param elements.
<xsl:template match ="books">
<xsl:variable name ="totalRecords">
<xsl:for-each select ="/">
<xsl:value-of select ="count(books/book)"/>
</xsl:for-each>
</xsl:variable>
<table>
!!...Table heading code from the above code snippet goes here……!!
<xsl:call-template name ="results">
<xsl:with-param name ="ttlrds" select ="$totalRecords">
</xsl:with-param>
</xsl:call-template>
</table>
</xsl:template>
Code Snippet 6.
Conditional (If and When) Elements
We can apply conditions for the elements in an XML file by using xsl:if or
xsl:when. The following code shows an example of both, respectively.
xsl:if example:
<xsl:variable name ="a" select ="24" />
<xsl:if test ="$a<5">
!!! The value of a (<xsl:value-of select ="$a"/>) is less than 5.
</xsl:if>
xsl:choose example
<xsl:choose>
<xsl:when test ="$a>5">
The value of a (<xsl:value-of select ="$a"/>) is greater than 5.
</xsl:when>
<xsl:otherwise>
== The value of a (<xsl:value-of select ="$a"/>) is less than 5.
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Code Snippet 7.
Sorting and filtering (The xsl:key element and generate-id() function)
The xsl:sort element is used to sort values. The following syntax shows the usage of sorting in
XSL.
<xsl:sort order ="ascending" select="author"/>
In order to understand how we can use filtering in XSL programming, we’ll go through the following demonstration, where first we’ll add all the distinct values
to the dropdown and then we’ll make use of these values to filter records.
- Get distinct values using XSLT:
By using the xsl:key element and generate-id() function we can get the distinct values as shown below. The below code snippet extracts the distinct author
values from the XML file and bind these values to the dropdown list.
<xsl:key name="athr" match="/books/book/author/text()" use="." />
<select onchange ="getvalue(this.value)">
<option>==select==</option>
<xsl:for-each select="/books/book/author/text()[generate-id()=generate-id(key('athr',.)[1])]">
<option>
<xsl:value-of select="."/>
</option>
</xsl:for-each>
</select>
- Passing the filter values from JavaScript and C#:
JavaScript
function getvalue(va){
var txtval = document.getElementById('txtid');
txtval.value = va;
form1.submit();
}
C#:
string category = string.Empty;
category = txtid.Text;
txtid.Text = string.Empty;
string text = SaxonDemo.transformXml(sourceUri, xsltUri,currentPage, category);
Literal1.Text = text;
- Get record(s) based on filter values:
<xsl:param name="category" />
<xsl:for-each select ="books/book[@category=$category]">
<xsl:call-template name ="results"></xsl:call-template>
</xsl:for-each>
Code Snippet 8.
Grouping the data
XSLT 2.0 introduces the xsl:for-each-group element which is used
to group record(s) based on a given column.
<xsl:for-each-group select="book" group-by="@category">
<h2>
<xsl:text>Category:</xsl:text>:<xsl:value-of select="current-grouping-key()"/>
</h2>
<xsl:for-each-group select="current-group()" group-by="@Genre">
<h2>
<xsl:text>Genre:</xsl:text>:<xsl:value-of select="current-grouping-key()"/>
</h2>
<xsl:for-each select="current-group()">
<table>
<xsl:call-template name ="results"></xsl:call-template>
</table>
</xsl:for-each>
</xsl:for-each-group>
</xsl:for-each-group>
Code Snippet 9.
The above code can be repeated to group multiple levels of columns.
Pagination
As we do paging in ASP.NET GridView, similar results can be
obtained for record(s) displayed here in XSL.
- Initially, the following variables and parameters are defined:
<xsl:variable name ="totalRecords">
<xsl:for-each select ="/">
<xsl:value-of select ="count(books/book)"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name ="recordsPerPage">
<xsl:value-of select ="8"/>
</xsl:variable>
<xsl:param name ="pageCount" select ="round($totalRecords div $recordsPerPage)" />
<xsl:param name="currentPage"/>
<xsl:param name="category" />
- Conditions are checked for the next set of record(s) to be displayed and code is defined for the next button by adding the
href attribute to the anchor tag of HTML as follows:
<xsl:if test ="$currentPage>=1 and $currentPage < $pageCount">
<td>
<a>
<xsl:attribute name="href">
Default.aspx?page=<xsl:value-of select="number($currentPage)+1"/>
</xsl:attribute>
Next>
- Similarly for the previous button, the following code is used:
<xsl:if test ="$currentPage>1 and $currentPage <= $pageCount">
<td>
<a>
<xsl:attribute name="href">
Default.aspx?page=<xsl:value-of select="number($currentPage)-1"/>
</xsl:attribute>
Previous<<
</a>
</td>
</xsl:if>
- The page number and total number of records are displayed as follows:
<td colspan ="3" align ="center">
<h3>
Page <xsl:value-of select ="$currentPage"/> of <xsl:value-of select ="$pageCount"/>
</h3>
</td>
- And finally the results are displayed by checking the following condition.
<xsl:template name ="results">
<xsl:for-each select ="book">
<xsl:if test ="position() > number(($currentPage*$recordsPerPage)-$recordsPerPage)
and position() <= number($currentPage*$recordsPerPage)">
!!!!!!------ Display the record(s) --------- !!!!!
</xsl:if>
</xsl:for-each>
</xsl:template>
The following code is used to pass parameters using C# code:
string text = SaxonDemo.transformXml(sourceUri, xsltUri, currentPage, category);
Literal1.Text = text;
Code Snippet 10.
XSLT 2.0 functions
XSLT 2.0 comes with a huge number of in-built functions related to different aspects like host names, dates, string……. and so on. We can find the complete list of functions
referenced here: http://www.saxonica.com/documentation/functions/intro.xml.
A basic example of using an in-built funtion(s) is as shown below:
<xsl:value-of select ="substring('saichandras','4')"/>
<br/>
<xsl:value-of select ="string-join(('20','04','1989'),'-')"/>
More examples are available here: http://www.w3schools.com/xpath/xpath_functions.asp.
Practice
Exercise 1
An XSLT program to find the factorial of a given number. The following
XSLT template is used to find the factorial of a given number.
<xsl:template name="factorial">
<xsl:param name="n" select="1"/>
<xsl:variable name="sum">
<xsl:if test="$n = 1"> 1 </xsl:if>
<xsl:if test="$n != 1">
<xsl:call-template name="factorial">
<xsl:with-param name="n" select="$n - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:variable>
<xsl:value-of select="$sum * $n"/>
</xsl:template>
Call this template:
<xsl:call-template name ="factorial">
<xsl:with-param name ="n" select="5">
</xsl:with-param>
</xsl:call-template>
The following link provides lot more practice examples for XSLT programming:
http://incrementaldevelopment.com/xsltrick.
Points of tnterest
In this tutorial we have directly used raw XML files as input, however most of the time, if we ever need to get data from database tables,
we can get the XML from the DataSet class of .NET. The following code describes this:
string xsltUri = Server.MapPath("code1.xslt");
string query = "select * from books";
SqlConnection con = new SqlConnection("data source =.; intial catalog=books; integrated security=true;");
DataSet ds = new DataSet("books");
SqlDataAdapter da = new SqlDataAdapter(query, con);
da.Fill(ds);
MemoryStream ms = new MemoryStream();
ds.WriteXml(ms);
string text = SaxonDemo.transformXml(ms, xsltUri);
Literal1.Text = text;
Conclusion
In this article, I have tried to put some of the basic examples of how to use
XSLT elements for programming. There are a lot more articles available that explain about
XSLT in a more detailed manner. The following List provide some of the links for further reading.