XSL Transformation is widly known tecnique for converting XML files to XHTML output. XSLT is designed for use as part of XSL, which is a stylesheet language for XML. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.

Here is sample XML document that will be used further.

<?xml version="1.0" encoding="UTF-8"?>
<sales>
    <division id="North">
        <revenue>10</revenue>
        <growth>9</growth>
        <bonus>7</bonus>
    </division>
    <division id="South">
        <revenue>4</revenue>
        <growth>3</growth>
        <bonus>4</bonus>
    </division>
    <division id="West">
        <revenue>6</revenue>
        <growth>-1.5</growth>
        <bonus>2</bonus>
    </division>
</sales>


Here is sample XSL Transformation

<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" lang="en">
    <head>
        <title>Sales Results By Division</title>
    </head>
    <body>
        <table border="1">
            <tr>
                <th>Division</th>
                <th>Revenue</th>
                <th>Growth</th>
                <th>Bonus</th>
            </tr>
            <xsl:for-each select="sales/division"> <!-- order the result by revenue -->
            <xsl:sort select="revenue" data-type="number" order="descending"/>
                <tr>
                    <td><em><xsl:value-of select="@id"/></em></td>
                    <td><xsl:value-of select="revenue"/></td>
                    <td> <!-- highlight negative growth in red -->
                        <xsl:if test="growth &lt; 0">
                            <xsl:attribute name="style">
                                <xsl:text>color:red</xsl:text>
                            </xsl:attribute>                
                        </xsl:if>
                        <xsl:value-of select="growth"/>
                    </td>
                    <td><xsl:value-of select="bonus"/></td>
                </tr>
            </xsl:for-each>
        </table>
    </body>
</html>


By using following sample c# code we can effectivly load xml document, and transform it's content into xhtml by using given xslt transformation:

XmlDocument xmldocument = new XmlDocument();
xmldocument.Load(@"..\..\data.xml");

XslCompiledTransform xsltransform = new XslCompiledTransform();
xsltransform.Load(@"..\..\style.xsl");

XmlTextWriter htmlwriter = new XmlTextWriter("output.html", null);

xsltransform.Transform(xmldocument, htmlwriter);


Now since we know how to transform xml data with xsl stylesheet and produce valid html code, we can continue with introducing XSL Extension Objects.
Extension objects are used to extend the functionality of style sheets. Extension objects are maintained by the XsltArgumentList class. The following are advantages to using an extension object rather than embedded script:

  • Provides better encapsulation and reuse of classes.
  • Allows style sheets to be smaller and more maintainable.

XSLT extension objects are added to the XsltArgumentList object using the AddExtensionObject method. A qualified name and namespace URI are associated with the extension object at that time. In this example we are using ResourceReader object

public class ResourceReader
{
    public string GetResourceString(string key)
    {
        //TODO: Read localized string representation for provided 'key' from resource file
        switch (key)
        {
            case "0001": return "Division";
            case "0002": return "Revenue";
            case "0003": return "Growth";
            case "0004": return "Bonus";
        }
        return string.Format("No resource value found for key='{0}'", key);
    }
}


Let's add this object to XsltArgumentList so we can use latter in xsl transformation for reading string values from resources

XmlDocument xmldocument = new XmlDocument();
xmldocument.Load(@"..\..\data.xml");

XslCompiledTransform xsltransform = new XslCompiledTransform();
xsltransform.Load(@"..\..\style.xsl");

XsltArgumentList arguments = new XsltArgumentList();
arguments.AddExtensionObject("urn:ResourceReader", new ResourceReader());

XmlTextWriter htmlwriter = new XmlTextWriter("output.html", null);
xsltransform.Transform(xmldocument, arguments, htmlwriter);


And modified xslt stylesheet will look like this

<html
        xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:ResourceReader="urn:ResourceReader"
        lang="en">
    <head>
        <title>Sales Results By Division</title>
    </head>
    <body>
        <table border="1">
            <tr>
                <th><xsl:value-of select="ResourceReader:GetResourceString('0001')" /></th>
                <th><xsl:value-of select="ResourceReader:GetResourceString('0002')" /></th>
                <th><xsl:value-of select="ResourceReader:GetResourceString('0003')" /></th>
                <th><xsl:value-of select="ResourceReader:GetResourceString('0004')" /></th>
            </tr>
            <xsl:for-each select="sales/division">
                <xsl:sort select="revenue" data-type="number" order="descending"/>
                <tr>
                    <td><em><xsl:value-of select="@id"/></em></td>
                    <td><xsl:value-of select="revenue"/></td>
                    <td>
                        <xsl:if test="growth &lt; 0">
                            <xsl:attribute name="style">
                                <xsl:text>color:red</xsl:text>
                            </xsl:attribute>
                        </xsl:if>
                        <xsl:value-of select="growth"/>
                    </td>
                    <td><xsl:value-of select="bonus"/></td>
                </tr>
            </xsl:for-each>
        </table>
    </body>
</html> tml>


And the rest is history. Cheers!