Advanced XSL Transformations With ASP.NET - Code in Your Style Sheets
(Page 4 of 7 )
Microsoft, being Microsoft, is known to add its own little tweaks (they call them enhancements) to the official specifications, and it is no different when it comes to XSL Transformations.
Why, you may ask?
Take a quick look at all style sheets listed so far and you will notice they consist of elements and more elements. This elements-only policy of the W3C for XML-related technologies has been implemented so strictly that even core programming constructs such as loops and conditional statements are implemented using XSL-specific elements such as <xsl:for-each> and <xsl:choose>.
While this makes life easy for folks with a non-technical background, it can get on the nerves of hardcore programmers who swear by their "if" statements and "for" loops. This is where the custom <msxsl:script> element, introduced by Microsoft for use in XSLT style sheets, comes in handy.
Consider the following example that adds and subtracts two numbers by invoking custom C# functions defined in the XSLT style sheet (say "calculator.xsl") using the <msxsl:script> element.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:calculator="urn:the-calculator">
<msxsl:script language="C#" implements-prefix="calculator">
<![CDATA[
public double sum(double dblNumber1, double dblNumber2){
return dblNumber1 + dblNumber2;
}
public double difference(double dblNumber1, double dblNumber2){
return dblNumber1 - dblNumber2;
}
]]>
</msxsl:script>
<xsl:template match="input">
<xsl:variable name="number1" select="number1" />
<xsl:variable name="number2" select="number2" />
<xsl:element name="output">
<xsl:copy-of select="number1" />
<xsl:copy-of select="number2" />
<xsl:element name="sum">
<xsl:value-of select="calculator:sum($number1, $number2)" />
</xsl:element>
<xsl:element name="difference">
<xsl:value-of select="calculator:difference($number1, $number2)" />
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Before we get into the nitty gritty on how this new <msxsl:script> element works, let us review the associated XML file (say "input.xml").
<?xml version='1.0'?>
<input>
<number1>5</number1>
<number2>2</number2>
</input>
Let's also review the ASP.NET script (say "calculator.aspx").
<%@ Page Language="C#" Debug="true" %>
<%@ import Namespace="System.IO" %>
<%@ import Namespace="System.Xml" %>
<%@ import Namespace="System.Xml.Xsl" %>
<%@ import Namespace="System.Xml.XPath" %>
<script runat="server">
void Page_Load()
{
// define some variables
string strXsltFile = Server.MapPath("calculator.xsl");
string strInputXmlFile = Server.MapPath("input.xml");
string strOutputXmlFile = Server.MapPath("output.xml");
// create instance of XslTransform object
XslTransform objXslTransform = new XslTransform();
// load the XSLT style sheet
objXslTransform.Load(strXsltFile);
// transform the input XML file
// and store result in output XML file
objXslTransform.Transform(strInputXmlFile, strOutputXmlFile);
// output message
output.Text = strOutputXmlFile + " file created successfully.";
// clean up memory
objXslTransform = null;
}
</SCRIPT>
<HTML>
<HEAD>
<TITLE>Mathematics using XSLT style sheets</TITLE>
<BASEFONT face="Arial" />
</HEAD>
<BODY>
<asp:Label id="output" runat="server"></asp:Label>
</BODY>
</HTML>
The XML file lists two numbers that we wish to add and subtract while the ASP.NET script contains routine code to publish the transformed output.
For the sake of completeness, this is output that you will view in the browser, when you load the script:

Take a quick peek at the newly created output XML file:

Now, let us shift our focus to the XSL style sheet that makes all this possible:
For starters, we have added some new namespace definitions to the root <xsl:stylesheet> element:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:calculator="urn:the-calculator">
// snip
</xsl:stylesheet>
You should be familiar with the first namespace definition, as it is the default namespace for all XSL style sheets. The second namespace, i.e. "xmlns:msxsl="urn:schemas-microsoft-com:xslt" represents the Microsoft-defined namespace for the "msxsl" prefix, and the third -- xmlns:calculator="urn:the-calculator" -- is the definition of our custom "calculator" namespace prefix. This third namespace definition is required to invoke the C# functions, defined later in the style sheet. More on this later.
Next, we have the definitions of the custom C# functions:
<%
// snip
<msxsl:script language="C#" implements-prefix="calculator">
<![CDATA[
public double sum(double dblNumber1, double dblNumber2){
return dblNumber1 + dblNumber2;
}
public double difference(double dblNumber1, double dblNumber2){
return dblNumber1 - dblNumber2;
}
]]>
</msxsl:script>
// snip
%>
Within the <msxsl:script> element, we need to define a value for the "implements-prefix" attribute. This stores the name of the namespace prefix defined in the root <xsl:stylesheet> element. We also must specify the name of the .NET language used within the <msxsl:script> block using the "language" attribute.
Next, we have the definitions of our custom "sum" and "difference" functions within a CDATA section. This ensures that the XML parser does not balk when it encounters this section of the style sheet. After all, the XSLT style sheet needs to be a valid XML document, in keeping with W3C guidelines.
Finally, the XSLT code that invokes our custom function is in the following code snippet:
<%
// snip
<xsl:template match="input">
<xsl:variable name="number1" select="number1" />
<xsl:variable name="number2" select="number2" />
<xsl:element name="output">
<xsl:copy-of select="number1" />
<xsl:copy-of select="number2" />
<xsl:element name="sum">
<xsl:value-of select="calculator:sum($number1, $number2)" />
</xsl:element>
<xsl:element name="difference">
<xsl:value-of select="calculator:difference($number1, $number2)" />
</xsl:element>
</xsl:element>
</xsl:template>
// snip
%>
Once we match the <input> element from the XML file, we define two XSLT variables -- number1 and number2 -- to store the two numbers. Next, we create a new "output" element and create copies of the two <input> elements using the <xsl:copy-of> element. Then we invoke the "sum" and "difference" functions and enclose the results within two new custom elements, <sum> and <difference>, respectively.
Note the use of the "calculate" namespace prefix to ensure that we invoke the correct C# function.
The "calculator.aspx" script contains routine code and you'll agree with us -- after all, you are a pro -- that it deserves no further explanation.
Now that we have demonstrated the <msxsl:script> element, we safely conclude that hardcore programmers will be satisfied with its introduction, since it allows them to use .NET languages rather than XSL Transformation elements to perform complex calculations.
The next section uses one such situation, and shows how this <msxsl:script> element makes life easy for us!
Intrigued? Read on.
Next: The Magic of Compounding >>
More ASP.NET Articles
More By Harish Kamath