Click here to Skip to main content
Click here to Skip to main content

XSLT 2.0 programming basics

, 17 Sep 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
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 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:templatexsl:param
xsl:calltemplatexsl:sort
xsl:choosexsl:attribute
xsl:for-each-groupxsl: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.

  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. <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.
  7. Add a new web (.aspx) page to the project and drag a Literal control to the page.
  8. Add the following code to the Page_Load function:
  9. 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:

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

  1. Declare a variable.
  2. <xsl:variable name ="totalRecords">
          <xsl:for-each select ="/">
            <xsl:value-of select ="count(books/book)"/>
          </xsl:for-each>
    </xsl:variable>
  3. Access the variable.
  4. <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).

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

  1. Get distinct values using XSLT:
  2. 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>
  3. Passing the filter values from JavaScript and C#:
  4. 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;
  5. Get record(s) based on filter values:
  6. <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.

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

License

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

Share

About the Author

S V Saichandra
Software Developer GSS Infotech Ltd.
India India
S V Sai Chandra is a Software Engineer from Hyderabad Deccan. He started Embedded Programing in his college days and now he is a Web Developer by Profession. He Loves coding and his passion is always been towards Microsoft Technologies. Apart from coding his other hobbies include reading books, painting and hang out with friends is his most favorite past time hobby.
He blogs at
http://technowallet.blogspot.com
Technical Skills:
C#,Ado.Net,Asp.Net,Sql Server,JavaScript,XML,Web services.
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
QuestionSorting XML in custom order Pinmembertratak10-Feb-14 2:07 
QuestionXSLT Browser Support PinmemberclintonG18-Sep-12 13:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141030.1 | Last Updated 17 Sep 2012
Article Copyright 2012 by S V Saichandra
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid