XSL Transformations using ASP.NET

XSL Transformation is a technology introduced by the W3C to simplify the tasks of presenting and formatting XML data. In this article, Harish Kamath demonstrates the capabilities of the .NET platform to transform XML documents using XSLT style sheets.

Transformation time

Right from its initial days, XML grabbed the imagination of the programming community. If at first, everyone struggled with the concept of custom tags (or elements as purists like to call them), soon the issue of rendering the information present in these custom XML files took center stage. This is where the World Wide Web Consortium (W3C) stepped in and introduced the concept of XSL Transformations – a technology that aimed to simplify the tasks of presenting and formatting XML data.

While you can learn more about XSL Transformations on the official website of the W3C – http://www.w3c.org  – and the myriad of tutorials on the Internet on this topic, this article will concentrate the capabilities of the .NET platform to transform XML documents using XSLT style sheets.

I promise that I am going to keep it simple and straightforward. The XML data used in the examples are pretty easy to understand. I will assume that you are familiar with the basic concepts of XSL Transformations. I will also assume that you know the basic rules of ASP.NET scripting.

Let’s get the show on the road, shall we?

{mospagebreak title=Start it up}

Consider the following XML document (say articles.xml) that lists the details of an article (on a web site such ASPFree.com):

<?xml version=”1.0″?>
<article id=”110″>
    <title>Implementing XSL Transformations with ASP.NET</title>
    <author>Harish R. Kamath</author>
    <category>ASP.NET</category>
    <abstract>Leverage on the built-in functionality available in ASP.NET to transform your XML documents using XSL Transformations!</abstract>
</article>

While this looks fine and dandy to an XML-aware client, ordinary mortals (such as you and me) prefer an HTML version that looks more like this:

XSLT Transformations using ASP NET

This is possible if I use the following XSLT style sheet (say articles.xsl) to transform the above XML file:

<xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform“>
<xsl:template match=”/”>
<H3>Article Title: <xsl:value-of select=”article/title” /></H3>
 <H4>Author: <xsl:value-of select=”article/author” /></H4>
<H4>Category: <xsl:value-of select=”article/category” /></H4>
<H5>Abstract:</H5>
<xsl:value-of select=”article/abstract” />
</xsl:template>
</xsl:stylesheet>

I have the XML content and I have the XSLT style sheet. Now, I need the glue to ensure that the two of them interact with each other and return the desired HTML output. This is where ASP.NET steps in – I can leverage on the .NET Framework, which is equipped with a wide array of .NET assemblies specifically defined for this purpose.
 
Take a peek at the following ASP.NET script (say articles.aspx) that uses the server-side .NET “Xml” control.

<%@ Page Language=”C#” %>
<HTML>
<HEAD>
    <TITLE>ASPFree.com</TITLE>
    <BASEFONT face=”Arial” size=”2″>
</HEAD>
<BODY>
    <asp:Xml id=”output” runat=”server” DocumentSource=”articles.xml” TransformSource=”articles.xslt” />
</BODY>
</HTML>

Load the example in your browser in order to see the desired HTML output (as shown above).

After a quick review of the code listing, I can safely conclude that the task of transforming an XML document using an XSLT style sheet is pretty simple in ASP.NET. All that I need to do is to create an instance of the .NET “Xml” server control using the <asp:Xml> element. This “Xml” server control is associated with several useful attributes – I have used the following:

  • DocumentSource: allows me to specify the name of the XML file that I wish to transform
  • TransformSource: allows me to specify the name of the XSLT file that is used to transform the XML file specified in the “DocumentSource” property

Next, I have assigned the names of the XML and XSLT style sheet files to the corresponding attributes (listed above) of the <asp:Xml> element and the end result is the transformation of the XML data into the desired HTML output.

{mospagebreak title=Dynamic transformation}

The first example is about as simple as it gets when it comes to using ASP.NET for XSL Transformations. Next, I will attempt to make things dynamic – take a look at the next two examples that re-use the ASP.NET “Xml” server control; each introducing its own new, little twist.

<%@ Page Language=”C#” %>
<SCRIPT runat=”server”>

void Page_Load() {

output.DocumentSource = “articles.xml”;
output.TransformSource = “articles.xsl”;
}

</SCRIPT>
<HTML>
<HEAD>
    <TITLE>ASPFree.com</TITLE>
    <BASEFONT face=”Arial” size=”2″>
</HEAD>
<BODY>
    <asp:Xml id=”output” runat=”server” />
</BODY>
</HTML>

If you have been using ASP.NET server controls for some time, you will already know that it is possible to ssign values to the attributes of a server control by invoking them as properties of the same .NET object at run time.

Confused? Let me review quickly.

Behind the scenes in the .NET environment, I can safely state that “everything is an object.” Consider the ASP.NET “Xml” server control used in all my examples so far. Under the hood, this control is an instance of the “System.Web.UI.WebControls.Xml” class, equipped with its own set of properties and methods. This means that you can specify values for the attributes of the server control by simply assigning those values to the corresponding properties of the underlying class.

This is exactly what I have done in the second example – I have assigned values to the “DocumentSource” and “TransformSource” properties of the local instance of the “System.Web.UI.WebControls.Xml” class at run time. This modification allows me to drop the definitions of the “DocumentSource” and “TransformSource” attributes from within the <asp:Xml> element and thereby make the process of XSL Transformation more dynamic.

The next example demonstrates another manner in which this <asp:Xml> element can be used:

<%@ Page Language=”C#” %>
<HTML>
<HEAD>
    <TITLE>ASPFree.com</TITLE>
    <BASEFONT face=”Arial” size=”2″>
</HEAD>
<BODY>
<asp:Xml id=”output” runat=”server” TransformSource=”articles.xsl” >
<article id=”110″>
            <title>Implementing XSL Transformations with ASP.NET</title>
            <author>Harish R. Kamath</author>
            <category>ASP.NET</category>
            <abstract>Leverage on the built-in functionality available in ASP.NET to transform your XML documents using XSL Transformations!</abstract>
</article>
</asp:Xml>
</BODY>
</HTML>

While the output (for the third example) remains the same as that for the first two, the noteworthy difference is the manner in which the XML content has been provided to the “Xml” server control. Instead of the customary use of the “DocumentSource” attribute (or property), you will notice that I have chosen to enclose the XML text within the <asp:Xml> element.

This ability to enclose the raw XML between start and end elements of the <asp:Xml> element allows me to change the source of XML data with great ease. This technique is useful if I do not have the XML data in a flat file, but I have to generate it dynamically – say, from a database, or by combining multiple XML documents into a single file at run time. In case of the former, I can easily connect to a database, build the entire XML structure in memory and spit it out between the <asp:Xml> elements. Then, the .NET compiler takes over – it loads the associated XSLT style sheet, applies it to the raw XML data between the <asp:Xml> tags, thereby generating the desired HTML output. 

And there’s more – you can learn about the ASP.NET “Xml” server control at the following URL: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemWebUIWebControlsXmlClassTopic.asp

{mospagebreak title=Jumping higher}

So far, the examples that I have demonstrated used the ASP.NET “Xml” server control. While such ready-to-use ASP.NET server controls make the job at hand a breeze to implement, the real power of the .NET platform lies in the vast number of assemblies that it comes equipped with to handle XML and related technologies, and this includes XSL Transformations.

The XML data in the previous examples can be at best considered to belong to the novice category. When you’re working on a real-world project, you are bound to come across something more complicated. Now it is time to approach the task of XSL Transformation in a different – and more complex – manner.

For starters, let me update the XML file so that it contains information about a list of articles rather than a single article – this is more likely in a real-world project:

<?xml version=”1.0″?>
<articles>
    <article id=”110″>
        <title>XSL Transformations with ASP.NET</title>
        <author>Harish R. Kamath</author>
        <category>ASP.NET</category>
        <abstract>Leverage on the built-in functionality available in ASP.NET to transform your XML documents using XSL Transformations!</abstract>
    </article>
    <article id=”109″>
        <title>Input Validation in ASP.NET</title>
        <author>Harish R. Kamath</author>
        <category>ASP.NET</category>
        <abstract>Prevent corrupt data from entering into your database – use built-in ASP.NET validation controls in your scripts.</abstract>
    </article>
    <article id=”108″>
        <title>Master the ASP.NET DataGrid Server Control</title>
        <author>Harish R. Kamath</author>
        <category>ASP.NET</category>
        <abstract>Learn how to use the powerful ASP.NET DataGrid server control to list data from a database table.</abstract>
    </article>
</articles>

Next, I have listed the updated XSLT style sheet to transform the above XML data into browser-compatible HTML format.

<xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform“>

<xsl:template match=”/article”>
 <xsl:apply-templates select=”title”/>
 <xsl:apply-templates select=”author”/>
 <xsl:apply-templates select=”category”/>
 <xsl:apply-templates select=”abstract”/>
</xsl:template>

<xsl:template match=”title”>
    <H3>Article Title: <xsl:value-of select=”.” /></H3>
</xsl:template>

<xsl:template match=”author”>
    <H4>Author: <xsl:value-of select=”.” /></H4>
</xsl:template>

<xsl:template match=”category”>
    <H4>Category: <xsl:value-of select=”.” /></H4>
</xsl:template>

<xsl:template match=”abstract”>
    <H5>Abstract:</H5>
    <xsl:value-of select=”.” />
</xsl:template>

</xsl:stylesheet>

Finally, I have the re-vamped ASP.NET script that brings about the XSL Transformation.

<%@ Page Language=”C#” %>
<%@ import Namespace=”System.Xml.Xsl” %>
<%@ import Namespace=”System.Xml.XPath” %>
<%@ import Namespace=”System.IO” %>
<SCRIPT runat=”server”>

void Page_Load() {
   
// path to the XML and XSLT files
string strXMLFile = Server.MapPath(“articles.xml”);
string strXSLTFile = Server.MapPath(“articles.xsl”);
   
// create an instance of XPathDocument object
// to load the XML file
XPathDocument objXmlFile = new XPathDocument(strXMLFile);

// create instance of XstTransform object
XslTransform objXSLTransform = new XslTransform();
   
// load the XSLT style sheet
objXSLTransform.Load(strXSLTFile);
   
// create an instance of StringWriter object
// to store result of transform
StringWriter objSWriter = new StringWriter();
   
// transform the XML file using the XSLT file
// store the output in a StringWriter object
objXSLTransform.Transform(objXmlFile, null, objSWriter, null);
   
// display the output in the browser
output.Text = objSWriter.ToString();
   
// clean up memory
objXmlFile = null;
objXSLTransform = null;
   
}
</SCRIPT>
<HTML>
<HEAD>
<TITLE>ASPFree.com</TITLE>
<BASEFONT face=”Arial”>   
</HEAD>
<BODY>
<asp:Label id=”output” runat=”server” />
</BODY>
</HTML>

Load this ASP.NET script in your browser to view the following output:

XSLT Transformations using ASP NET

With the formalities behind me, let me start dissecting the above code listing line-by-line.

{mospagebreak title=Code dissection}

<%@ Page Language=”C#” %>
<%@ import Namespace=”System.Xml.Xsl” %>
<%@ import Namespace=”System.Xml.XPath” %>
<%@ import Namespace=”System.IO” %>
<%

// snip

%>

For starters, I have imported the “System.Xml.Xsl” and “System.Xml.XPath” assemblies in order to create instances of the required classes later in the script. Next, the “System.IO” assembly has to be imported in order to create an instance of the StringWriter() object, the purpose of which will be clear as I proceed with the explanations.

<%

// snip

<SCRIPT runat=”server”>

void Page_Load() {
   
// path to the XML and XSLT files
string strXMLFile = Server.MapPath(“articles.xml”);
string strXSLTFile = Server.MapPath(“articles.xsl”);

// create an instance of XPathDocument object
// to load the XML file
XPathDocument objXmlFile = new XPathDocument(strXMLFile);

// create instance of XstTransform object
XslTransform objXSLTransform = new XslTransform();
   
// snip
   
}
</SCRIPT>

// snip

%>

Next, I have the customary Page_Load() function – the function begins with the definitions of two variables i.e. strXMLFile and strXSLTFile, to store path to the XML and XSLT code files respectively. Next, I have created instances of the XPathDocument() and XslTransform() classes for use in my script.

Note that I could have opted for the more-familiar XmlDocument() object instead of the XPathDocument() object. However, if you are familiar with the Document Object Model (a.k.a. the DOM) and its .NET implementation i.e. the aforementioned XmlDocument() object, you will know that this is memory intensive, since the object is required to keep the entire tree structure of the XML data in memory at all times. In contrast, the XPathDocument() is a much more lightweight object that uses the relatively simpler and easy-to-understand XPath syntax to access the required nodes directly without needing to keep any information in memory.

<%

// snip

<SCRIPT runat=”server”>

void Page_Load() {
   
 // snip

// load the XSLT style sheet
objXSLTransform.Load(strXSLTFile);
   
// create an instance of StringWriter object
// to store result of transform
StringWriter objSWriter = new StringWriter();
   
// transform the XML file using the XSLT file
// store the output in a StringWriter object
objXSLTransform.Transform(objXmlFile, null, objSWriter, null);
   
// display the output in the browser
output.Text = objSWriter.ToString();

// clean up memory
objXmlFile = null;
objXSLTransform = null;
   
}
</SCRIPT>

// snip

%>

Next, I invoke the Load() method of the XslTransform() object to load the XSLT style sheet file – the location to the file stored in the variable “strXSLTFile” is passed as an input parameter. This is followed by the creation of an instance of the StringWriter() object that is passed as an output parameter to the Transform() method of the XslTransform() object.

As you might have guessed, the Transform() method does all the hard work of applying the XSLT rules (present in the style sheet file) to the XML data (loaded in the local instance XPathDocument() object). This method in turn returns the transformed HTML output as a StringWriter() object.

Finally, I have used the ToString() method of the StringWriter() object to assign the transformed output to the “Text” property of an ASP.Net “Label” server control for display in the browser.

{mospagebreak title=Publish or you will perish}

I have already shown you two different techniques to transform XML document using XSLT style sheets.

There is one common feature in all these examples – they transform the XML data using the style sheet in real-time. This mechanism works efficiently when I am working in a development environment and  – in all probability – I  am the only user accessing the resources of the Web server.

Cut to a real-world Web server, where thousands (if not millions) of users are constantly accessing a  website. As the above examples transform the XML files every time, the run-time memory utilized by the processors for transforming the XML will be enormous – not to mention the high loads that the server will be subjected to. In such a scenario, any means to reduce the memory utilization as well as the load is definitely welcome.

One simple mechanism: develop an ASP.NET script that transforms an  XML file using a XSLT style sheet and stores the output in a static HTML file. The Web server, then, will serve these static files to visitors of the website, thereby avoiding the need for run-time transformation for every visit. This, in turn, will definitely lead to drastic improvement in server memory utilization as well as reduction of load on the Web server, since requests will be served quickly.

Fortunately, this task is not very complex when it comes to ASP.NET. Take a look at the next example that saves the transformed XML data as a HTML file on the server.

First, the XSLT style sheet has to be updated in order to ensure that the HTML output is complete, i.e. it contains the required HTML elements such as <HTML>, <HEAD>, <BODY> etc.

<xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”>

<xsl:template match=”/articles”>
<HTML>
<HEAD>
    <TITLE>ASPFree.com</TITLE>
    <BASEFONT face=”Arial” />
</HEAD>
<BODY>
 <xsl:apply-templates select=”article”/>
</BODY> 
</HTML>
</xsl:template>

<xsl:template match=”article”>
 <xsl:apply-templates select=”title”/>
 <xsl:apply-templates select=”author”/>
 <xsl:apply-templates select=”category”/>
 <xsl:apply-templates select=”abstract”/>
</xsl:template>

<xsl:template match=”title”>
    <H3>Article Title: <xsl:value-of select=”.” /></H3>
</xsl:template>

<xsl:template match=”author”>
    <H4>Author: <xsl:value-of select=”.” /></H4>
</xsl:template>

<xsl:template match=”category”>
    <H4>Category: <xsl:value-of select=”.” /></H4>
</xsl:template>

<xsl:template match=”abstract”>
    <H5>Abstract:</H5>
    <xsl:value-of select=”.” />
</xsl:template>

</xsl:stylesheet>

Next, I have updated the ASP.NET script in order to publish an HTML file on the server instead of merely displaying the output in the browser.

<%@ Page Language=”C#” %>
<%@ import Namespace=”System.Xml.Xsl” %>
<script runat=”server”>

void Page_Load(){

// path to the XML and XSLT files
string strXSLTFile = Server.MapPath(“articles.xsl”);
         string strXMLFile = Server.MapPath(“articles.xml”);
         string strHTMLFile = Server.MapPath(“articles.htm”);

         // create instance of XstTransform object
         XslTransform objXSLTransform = new XslTransform();

         // load the XSLT style sheet
         objXSLTransform.Load(strXSLTFile);

         // transform the XML file using the XSLT file
// store the output in a HTML file
         objXSLTransform.Transform(strXMLFile, strHTMLFile);

         // output message
        output.Text = strHTMLFile + ” file published successfully.”;

         // clean up memory
         objXSLTransform = null;

}

</SCRIPT>
<HTML>
<HEAD>
    <TITLE>ASPFree.com</TITLE>
    <BASEFONT face=”Arial” />
</HEAD>
<BODY>
    <asp:Label id=”output” runat=”server”></asp:Label>
</BODY>
</HTML>

If you load the example in browser, you will notice the following output:

XSLT Transformations using ASP NET

Navigate to the location that appears in the output above and you will find that the script has created the required HTML file.

Now, let us focus on the ASP.NET script itself.

The first change you will notice that I have only imported one .NET assembly i.e. the “System.Xml.Xsl” assembly. The rest (imported earlier)  are not required for this example. This is followed by definition of the strings variables to store the path to the XML and XSLT style sheet files. This time around, I have defined one more variable called “strHTMLFile” – this is used to store the name of the HTML file that will be created on the server.

Next, I created a local instance of XslTransform() object and invoked the Load() method in order to load the required XSLT style sheet.

Then,  I passed the locations of the input XML file and output HTML file to Transform() method that – once again – bears the responsibility of loading the XML file from the specified location, applying the style sheet rules from XSLT file and storing the output as a HTML file at the specified location.

That was pretty simple, wasn’t it?

Just one caveat – ensure that the location on the server where the HTML file will be created has appropriate “write” permissions for the special ASP.NET user.

{mospagebreak title=To err is human}

To make errors is considered human; commit errors regularly, and you must be a programmer. Bitter as it may sound, programmers are prone to making errors, and trapping them in their scripts is a vital weapon in the armory of every ASP.NET programmer.

Take a look at the next example that I have cooked up.

<%@ Page Language=”c#” %>
<%@ import Namespace=”System.Xml.Xsl” %>
<script runat=”server”>

void Page_Load() {

    // Start the “try” block
    try {

        // path to the XML and XSLT files
        string strXSLTFile = Server.MapPath(“articles.xsl”);
        string strXMLFile = Server.MapPath(“articles.xml”);
        string strHTMLFile = Server.MapPath(“articles.htm”);

        // create instance of XstTransform object
        XslTransform objXSLTransform = new XslTransform();

        // load the XSLT style sheet
        objXSLTransform.Load(strXSLTFile);

        // transfor the XML file using the XSLT file
        // store the output in a StringWriter object
        objXSLTransform.Transform(strXMLFile, strHTMLFile);

        // output message
        output.Text = strHTMLFile + ” file published successfully.”;

    } catch (XsltException e) {

        output.Text = “An XSLT Exception occured: ” + e.Message;

    } catch (Exception e) {

        output.Text = “A General Exception occured: ” + e.Message;

    } finally {

        // clean up memory
        if(objXSLTransform != null) {
            objXSLTransform = null;
        }
    }
}
</SCRIPT>
<HTML>
<HEAD>
    <TITLE>ASPFree.com</TITLE>
    <BASEFONT face=”Arial” />
</HEAD>
<BODY>
    <asp:Label id=”output” runat=”server”></asp:Label>
</BODY>
</HTML>

The output of this example – if all goes well – is the same as the last one, i.e. a HTML file is generated on the server at the specified location. But Murphy’s Law states “if things can go wrong, they will.”

Consider a situation where the “articles.xml” XML file has been accidentally deleted from the server. Now, load the above example in your browser. The updated ASP.NET script ensures that the .NET compiler takes a quiet detour into the “catch” block of the “try-catch-finally” mechanism and displays the following error message:

XSLT Transformations using ASP NET

What would happen if there is no error handling present in the above example – take a look:

XSLT Transformations using ASP NET

Now, that is definitely a sight for sore eyes!

That is not the end of the story. Let me assume that, in a hurry to get my work done and over with, I replace the “match” attribute of the <xsl:template> element in the XSLT style sheet with the word “matches.” Not likely to happen, but then nobody’s perfect.

Should I worry? Not really. The error handling mechanism in my ASP.NET is quite adept at handling such unfortunate mishaps. Why? It takes the honorable route of displaying a polite error message as shown in the output below:

XSLT Transformations using ASP NET

As usual, it is up to the resourceful “try-catch-finally” block to make amends for all my mistakes.

The general norm is to  place all the code that can potentially throw errors within the try block – for the above example, this includes loading the XSLT style sheet using the Load() method and pulling off the XSL transformation by calling the Transform() method.

Next, I have the “catch” block. Since the “System.Xml.Xsl” assembly is equipped with it very own XsltException(), the catch block tries to trap any error in XSLT style sheet using this exception handler.

However, if things get worse, I have also provided for general Exception() handler – this can catch any mistake that XsltException() object is unable to handle.

Last but not least, I have the “finally” block. As you might be aware, this block contains code that will always execute at the end of the execution of the “try” block even if the script encounters an exception. I use this feature to carry out a clean-up job that includes closing any active XslTransform() object that might have been created during the execution of the script.

Round Up

That’s about it for this article. If you’re interested in learning more about XSLT on the .NET platform, take a look at the following links:

XSLT and XSL at the W3C: http://www.w3.org/Style/XSL/

XSL Transformations with the XslTransform Class on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconxslttransformationswithxsltransformclass.asp

The ASP.NET “Xml” server control on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemWebUIWebControlsXmlClassTopic.asp

The .NET XslTransform() class on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemxmlxslxsltransformclasstopic.asp

The .NET XPathDocument() class on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemXmlXPathXPathDocumentClassTopic.asp

Note: All examples in this article have been tested on Windows 2000 Server with ASP.NET version 1.1 . Examples are illustrative only, and are not meant for a production environment. YMMV!

One thought on “XSL Transformations using ASP.NET

[gp-comments width="770" linklove="off" ]