Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

XSLT 2.0 Programming Basics

4.87/5 (11 votes)
17 Sep 2012CPOL6 min read 70.8K   1.7K  
This article describes XSLT programming for beginners.

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setting up the environment
  4. XSLT basics
    1. Displaying the XML data
    2. Using the XSL templates
    3. XSL variables and parameters
    4. Sorting and filtering (the xsl:key element and generate-id() function)
    5. Grouping the data
    6. Pagination
    7. XSLT 2.0 functions
  5. Practice
  6. Points of interest
  7. 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 returns the parsed XML value into string in HTML format. We can display the obtained HTML output in a Literal control.

C#
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.

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.

XML
<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
C#
string sourceUri = Server.MapPath("books.xml");
string xsltUri = Server.MapPath("code1.xslt");
string text = SaxonDemo.transformXml(sourceUri, xsltUri);
Literal1.Text = text;
Code Snippet 3
  1. Create a new empty web project using Visual Studio.
  2. Add the XML file to the project which is available for download with this article.
  3. Add a class file and copy code snippet 1 to the class file and add the required reference libraries.
  4. Add a new XSLT file to your project and copy the following code:
  5. For the time being, exclude the parameters in code snippet 1.
  6. Add a new web (.aspx) page to the project and drag a Literal control to the page.
  7. Add the following code to the Page_Load function:

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:

XML
<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>
XML
<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
  1. Create a template named results.
  2. Call the above template using the xsl:calltemplate element.

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:

XML
<xsl:variable name ="totalRecords">
      <xsl:for-each select ="/">
        <xsl:value-of select ="count(books/book)"/>
      </xsl:for-each>
</xsl:variable>
XML
<tr>
        <td colspan="5">
     <b>Total No of Record(s):<xsl:value-of select ="$totalRecords"/>
        </b>
        </td>
</tr>
Code Snippet 5
  1. Declare a variable.
  2. Access the variable.

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).

XML
<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>
XML
<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
  1. Define a template with a parameter using the xsl:param element.
  2. Call the template using the xsl:call template and xsl:with param elements.

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

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

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

XML
<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.

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 binds these values to the dropdown list.

XML
<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>
JavaScript
JavaScript
function getvalue(va){
 var txtval = document.getElementById('txtid');
 txtval.value = va;
 form1.submit();
}
C#
C#
string category = string.Empty;
category = txtid.Text;
txtid.Text = string.Empty;
string text = SaxonDemo.transformXml(sourceUri, xsltUri,currentPage, category);
Literal1.Text = text;
XML
<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
  1. Get distinct values using XSLT:
  2. Passing the filter values from JavaScript and C#:
  3. Get record(s) based on filter values:

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.

XML
<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.

XML
<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" />
XML
<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>
XML
<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>
XML
<td colspan ="3" align ="center">
<h3>
  Page <xsl:value-of select ="$currentPage"/> of <xsl:value-of select ="$pageCount"/>
</h3>
</td>
XML
<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>
  1. Initially, the following variables and parameters are defined
  2. 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
  3. Similarly for the previous button, the following code is used
  4. The page number and total number of records are displayed as follows
  5. And finally the results are displayed by checking the following condition

The following code is used to pass parameters using C# code:

C#
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.

A basic example of using an in-built funtion(s) is as shown below:

XML
<xsl:value-of select ="substring('saichandras','4')"/>
<br/>
<xsl:value-of select ="string-join(('20','04','1989'),'-')"/>

More examples are available here.

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.

 

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

XML
<xsl:call-template name ="factorial">
      <xsl:with-param name ="n" select="5">
      </xsl:with-param>
</xsl:call-template>

This link provides lot more practice examples for XSLT programming: .

Points of Interest

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:

C#
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 provides some of the links for further reading:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)