Jesper Tverskov, September 1, 2008

Transform XML with XSLT 1.0 .NET processor

XSLT 2.0 has many improvements over XSLT 1.0 but Microsoft has not made its own XSLT 2.0 processor yet. In ASP.NET we can use Saxon's XSLT 2.0 processor or we can use the build in XSLT 1.0 processor often referred to as ".NET 2.0" in .NET 2.0 or higher. In this tutorial we use this XSLT 1.0 processor.

XSLT is a declarative programming language dedicated to transform XML to some other XML, to XHTML (also XML), HTML and text formats. When transforming to XSL-FO (also XML), it is easy to convert to PDF. XSLT is a W3C standard (Recommendation).

XSLT is a big subject. In the following we will only show two basic examples of transforming to screen and to file and we will transform to XHTML as in all the other ASP.NET examples to make it easy to compare the different XML APIs.

1. Transform products.xml

I use the following XML document, products.xml, in many of my XML tutorials. How could it be transformed into an XHTML table using XSLT 1.0? To make the example more interesting, we use CSS for formatting and we generate date, time and a form element for sorting.

2. Transform to screen

2.1 transform-xml-xslt10.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="transform-xml-xslt10.aspx.cs" Inherits="transform_xml_xslt10" %>

Test the ASP.NET files and XSLT 1.0.

2.2 transform-xml-xslt10.aspx.cs

using System;
using System.IO; // if File.Create is used
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;

public partial class transform_xml_xslt10 : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    string dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    string sortOrder = "ascending";

    if (Request.Form["sort"] != null)
    {
      sortOrder = Request.Form["sort"].ToString();
    }

    string xsltFile = Server.MapPath("products2table.xsl");
    string xmlFile = Server.MapPath("products.xml");

    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load(xsltFile);    XsltArgumentList arg = new XsltArgumentList();
    arg.AddParam("dateTime", "", dateTime);
    arg.AddParam("sortOrder", "", sortOrder);

    XPathDocument doc = new XPathDocument(xmlFile);

    // if we want to transform to screen
    xslt.Transform(doc, arg, Response.Output);
    // if we want to transform to file
    // xslt.Transform(doc, arg, File.Create(Server.MapPath("table.html")));
  }
}

2.3 products2table.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output method="xml" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes"/>

  <xsl:param name="dateTime"/>
  <xsl:param name="sortOrder"/>

  <xsl:template match="/">
    <html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>XML to XHTML with XSLT 1.0</title>
        <style type="text/css">
          html{background-color:ivory}
          body{font-family:Verdana, Arial, Helvetica, san-serif; background-color:ivory}
          table, td, th{border:1px solid silver; border-collapse:collapse}
          tr{background-color:mistyrose}
          tr.alt1{background-color: whitesmoke}
          tr.alt0{background-color: azure}
        </style>
      </head>
      <body>
        <h1>Transform XML to XHTML with XSLT 1.0</h1>
        <p><small><xsl:value-of select="$dateTime"/></small></p>

        <form id="Form1" method="post" action="transform-xml-xslt10.aspx">
          <p>Stock sorted:&#160;
            <select name="sort">
              <option value="ascending">
                <xsl:if test="$sortOrder = 'ascending'">
                  <xsl:attribute name="selected">selected</xsl:attribute>
                </xsl:if>ascending
              </option>
              <option value="descending">
                <xsl:if test="$sortOrder = 'descending'">
                  <xsl:attribute name="selected">selected</xsl:attribute>
                </xsl:if>descending
              </option>
            </select>
            &#160;<input type="submit" value=" ok "/>
          </p>
        </form>

        <table cellspacing="0" cellpadding="5">
          <tr>
            <th>id</th>
            <th>name</th>
            <th>price</th>
            <th>stock</th>
            <th>country</th>
          </tr>

          <xsl:for-each select="products/product">
            <xsl:sort select="stock" order="{$sortOrder}" data-type="number"/>
            <tr class="alt{position() mod 2}">
              <td><xsl:value-of select="@id"/></td>
              <td><xsl:value-of select="name"/></td>
              <td><xsl:value-of select="price"/></td>
              <td><xsl:value-of select="stock"/></td>
              <td><xsl:value-of select="country"/></td>
            </tr>
          <xsl:/for-each>
        </table>
      </body>
    </html>  
  </xsl:template>
</xsl:stylesheet>

3. Transform to file

Let us say we want to transform the XML document to a file instead of to the screen. Let us call the file , "table.html". The stylesheet is as before. The ASP.NET codebehind file we change to:

// if we want to transform to screen
// xslt.Transform(doc, arg, Response.Output);

// if we want to transform to file
xslt.Transform(doc, arg, File.Create(Server.MapPath("table.html")));

4. Transform XML in a namespace

In the XSLT stylesheet we must declare the namespaces and use the proper prefixes to get to the XML. Special attention is needed if the XML is in a default namesace. See: Transform XHTML to XHTML with XSLT for how to transform XML in a default namespace. My article uses XHTML as an XML application as example, but the technique used applies to any XML in a default namespace. The name of the article could just as well have been: "Transform XML in a default namespace to XML".

Updated 2008-09-02