Click here to Skip to main content
Licence Apache
First Posted 22 Dec 2011
Views 18,487
Downloads 611
Bookmarked 33 times

XSLT 2.0 in .NET

By | 9 Feb 2012 | Article
The .NET Framework provides XslCompiledTransform which is an XSLT processor 1.0. However this doesn't mean that we can’t work with XSLT 2.0 in .NET. This article is for folks who want to use XSLT 2.0 in .NET.

Introduction

The .NET Framework provides XslCompiledTransform which is an XSLT processor 1.0. However this doesn't mean that we can’t work with XSLT 2.0 in .NET. This article is for folks who want to use XSLT 2.0 in .NET.

XSLT 2.0 is richer than XSLT 1.0. Indeed, below some features of XSLT 2.0.

  • regular expressions
  • current date time and multiple functions on dates
  • grouping
  • xsl:function for camelcasing a string
  • string comparison
  • tokenize() and matches()
  • for … in … return
  • next-match
  • as attribute on basic processors

All the functions and the specifications are described on W3C. You can also find all the functions on w3schools.

Saxon is an XSLT and XQuery processor created by Michael Kay. There are open-source and also closed-source commercial versions. Versions exist for Java and .NET. In this tutorial we will use Saxon .NET API to illustrate how the XSLT processing is performed.

Using the code

Input

The XML file below contains a list of some cities, their country and the population count.

<?xml version="1.0" encoding="utf-8"?>

<cities>
  <city name="Milano" country="Italia" pop="1307495" />
  <city name="Paris" country="France" pop="2220140" />
  <city name="Bordeaux" country="France" pop="719489" />
  <city name="München" country="Deutschland" pop="1260391" />
  <city name="Lyon" country="France" pop="474946" />
  <city name="Venezia" country="Italia" pop="270801" />
  <city name="Delft" country="Holland" pop="94512" />
  <city name="Rotterdam" country="Holland" pop="607460" />
</cities>

Desired output

Generated at 22.12.2011 23:42:27

Position Country City List Population
1 France Paris, Bordeaux, Lyon 3.414575E6
2 Italia Milano, Venezia 1.578296E6
3 Deutschland München 1.260391E6
4 Holland Delft, Rotterdam 701972

XSLT Processing

We will make an XSLT to transform this XML file into an HTML report containing the list of countries ordered by population count and for each country the list of its cities grouped.

In the XSLT below, I used xsl:for-each-group statement in order to group the cities by country.

It is possible to set up the grouping in XSLT 1.0 by using xsl:key but It would be more complex.

Also, you will notice that I used current-dateTime() function in order to retrieve the current date time and format-dateTime() function in order to format the current date time.

<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" encoding="iso-8859-1" />

  <xsl:template match="/">
    <html>
      <head>
        <title>Cities</title>
      </head>
      <body>
        Generated at
        <xsl:value-of select="format-dateTime(current-dateTime(), '[D].[M].[Y] [H]:[m]:[s]' )" />
        <br />
        <table style="border : 1px solid #000;">
          <thead>
            <tr>
              <th>Position</th>
              <th>Country</th>
              <th>City List</th>
              <th>Population</th>
            </tr>
          </thead>
          <tbody>
            <xsl:for-each-group select="cities/city" group-by="@country">
              <xsl:sort select="sum(current-group()/@pop)" data-type="number" order="descending" />
              <tr>
                <td>
                  <xsl:value-of select="position()" />
                </td>
                <td>
                  <xsl:value-of select="@country" />
                </td>
                <td>
                  <xsl:value-of select="current-group()/@name" separator=", " />
                </td>
                <td>
                  <xsl:value-of select="sum(current-group()/@pop)" />
                </td>
              </tr>
            </xsl:for-each-group>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

The code below performs the main XSLT processing by using the SAXON .NET API.

namespace Saxon
{
    internal class Program
    {
        private static void Main()
        {
            const string xmlFile = @"..\..\cities.xml";
            const string xsltFile = @"..\..\cities.xslt";
            const string outFile = @"..\..\cities_grouped.html";

            try
            {
                using (XmlReader xml = XmlReader.Create(xmlFile))
                using (XmlReader xslt = XmlReader.Create(xsltFile))
                {
                    // Create a Processor instance
                    var processor = new Processor();

                    // Load the source document
                    XdmNode input = processor.NewDocumentBuilder().
                        Build(xml);

                    // Create a transformer for the stylesheet
                    XsltTransformer transformer = processor.NewXsltCompiler().
                        Compile(xslt).Load();

                    // Set the root node of the source document to be the initial context node
                    transformer.InitialContextNode = input;

                    // Create a serializer
                    var serializer = new Serializer();
                    serializer.SetOutputStream(new FileStream(outFile, FileMode.Create, FileAccess.Write));

                    // Transform the source XML
                    transformer.Run(serializer);

                    Console.WriteLine("Output written to " + outFile + Environment.NewLine);
                }
            }
            catch (Exception e)
            {
                ConsoleColor currentConsoleColor = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("oops : " + e.Message);
                Console.ForegroundColor = currentConsoleColor;
            }

            Console.Write("Press any key to exit ...");
            Console.ReadKey();
        }
    }
} 

Other options

There is XQSharp, an XSLT, XPath 2.0 and XQuery 1.0 implementation for the .NET platform. And there is AltovaXML, an XSLT 2.0 and XQuery 1.0 COM based software package for Windows that can be used with .NET too (via COM Interop).

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0

About the Author

Akram El Assas

Architect
Mediatvcom
France France

Member

Follow on Twitter Follow on Twitter


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionMessage Automatically Removed Pinmemberram vilas pawar2:32 27 Feb '12  
AnswerRe: hello PinmvpDave Kreskowiak14:39 27 Feb '12  
GeneralRe: hello PinmvpSAKryukov19:11 27 Feb '12  
GeneralRe: hello PinmvpDave Kreskowiak1:44 28 Feb '12  
QuestionClient-Side XLST RSS to HTML5 PinmemberclintonG7:14 13 Feb '12  
AnswerRe: Client-Side XLST RSS to HTML5 PinmemberAkram El Assas8:12 13 Feb '12  
GeneralRe: Client-Side XLST RSS to HTML5 PinmemberclintonG13:11 13 Feb '12  
GeneralRe: Client-Side XLST RSS to HTML5 PinmemberAkram El Assas12:02 14 Feb '12  
GeneralRe: Client-Side XLST RSS to HTML5 PinmemberclintonG17:54 14 Feb '12  
QuestionTry http://qizx.codeplex.com/ Pinmembermail_main2:37 12 Jan '12  
GeneralMy vote of 5 PinmemberAl Moje21:44 11 Jan '12  
GeneralRe: My vote of 5 PinmemberAkram El Assas0:19 12 Jan '12  
QuestionXSLT for validating only xml data ? Pinmembersartar18:44 11 Jan '12  
AnswerRe: XSLT for validating only xml data ? Pinmembersebgod1:58 18 Jan '12  
Questionerror... PinmemberHoyaSaxa9310:13 23 Dec '11  
AnswerRe: error... PinmemberAkram El Assas10:51 23 Dec '11  
GeneralRe: error... PinmemberHoyaSaxa9317:37 23 Dec '11  
QuestionWhy? Pinmemberring_018:08 22 Dec '11  
AnswerRe: Why? [modified] PinmemberAkram El Assas6:59 23 Dec '11  

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.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 9 Feb 2012
Article Copyright 2011 by Akram El Assas
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid