The .NET framework provides XslCompiledTransform which is an XSLT processor 1.0. However this does not mean that we can’t work with XSLT 2.0 in .NET. This tutorial is for people who want to use XSLT 2.0 in .NET. XSLT 2.0 is richer than XSLT 1.0. Indeed, bellow, some features of XSLT 2.0:

  • regular expressions
  • current date time and multiple functions on dates
  • grouping
  • xsl:function for camelcasing a string
  • anges, like “2 to 3″ and comparison
  • tokenize() and matches()
  • for … in …. return
  • next-match
  • the use of the ‘as’ attribute on basic processors

You can find all the features of XSLT 2.0 with examples on W3C.

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. The xml file bellow contains a list of some cities, their country and the population count.

Using the code


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

  <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" />

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

We will make an XSLT to transform this file to an HTML table containing the list of countries and for each country the list of cities grouped and the sum of the population count. In the XSLT bellow, we use the xsl:for-each-group statement to group the cities by country. It is possible to do this in XSLT 1.0 but It would be more difficult. Also, you will notice that we use current-dateTime() function in order to retrieve the current date time. I invite you to read the W3C recommendation to see all the functions of XSLT 2.0.

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

<xsl:stylesheet version="2.0" xmlns:xsl="">
  <xsl:output method="html" indent="yes" encoding="iso-8859-1" />

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

The code bellow performs the main XSLT processing by using the SAXON .NET API. I invite you to read the documentation of the API and see the code samples.

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";

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

                    // Create a transformer for the stylesheet
                    XsltTransformer transformer = processor.NewXsltCompiler().

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

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

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

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架