Introduction
I am using XSL transformation in a project. So far, I have been very pleased with XSL and its capabilities. However, sometimes I find myself spending a large amount of time trying to solve a problem using XSL's set based structure. Usually, you can solve these problems, but it often takes a lot of work. In some cases, especially with dates, I have found the XSL support to be very weak (or non-existant). This is where embedded scripts come in. If I cannot find a solution to a problem using XSL, I will usually turn to an embedded script coded in C# to help solve the problem. I have written another article that contains a basic example of how to do this. Originally, I was transforming the style sheets in my custom application. However, this was tedious and I did not want to keep waiting for the entire program to load just to check if there was an error in the XSL. So, I downloaded Microsoft's MSXSL.EXE program and tried to use this to transform the XSL. I found that MSXSL would not transform the files. I kept getting the error: Invalid class file. I am not 100% sure why this is happening but my thoughts on this are that MSXSL.EXE is a wrapper around the MSXML 4.0. I do not think MSXML 4.0 supports embedded scripts. Fortunately for us - .NET does! So, I wrote my own wrapper to let me transform the XSL. Below is the relevant code for the wrapper application:
static void Main(string[] args)
{
if( args.Length != 3 )
{
Console.WriteLine( "You have not entered the correct parameters" );
return;
}
string xmlfile = args[0];
string xslfile = args[1];
string outfile = args[2];
try
{
XPathDocument doc = new XPathDocument( xmlfile );
XslTransform transform = new XslTransform();
transform.Load( xslfile );
XmlTextWriter writer = new XmlTextWriter( outfile, null );
transform.Transform( doc, null, writer );
}
catch( Exception e )
{
Console.WriteLine( e.StackTrace );
}
}
It is fairly basic stuff - but very useful. Below is an example XML file, the XSL file, and the output file that I used as a test.
atest.xml
="1.0" ="UTF-8"
<root>
<dataitem>From the xml file: item 1</dataitem>
<dataitem>From the xml file: item 2</dataitem>
<dataitem>From the xml file: item 3</dataitem>
<dataitem>From the xml file: item 4</dataitem>
</root>
atest.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:utils="urn:script-items">
<msxsl:script language="C#" implements-prefix="utils">
<![CDATA[]]>
</msxsl:script>
<xsl:output method="html" encoding="utf-8" />
<xsl:template match="dataitem">
<xsl:value-of select="." /> displayed on <xsl:value-of select="utils:getDate()" />
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
You can transform this with:
myxsl atest.xml atest.xsl atest.htm
and you will get the result:
atest.htm
From the xml file: item 1 displayed on Thursday, November 18, 2004 at 2:38:26 PM
From the xml file: item 2 displayed on Thursday, November 18, 2004 at 2:38:26 PM
From the xml file: item 3 displayed on Thursday, November 18, 2004 at 2:38:26 PM
From the xml file: item 4 displayed on Thursday, November 18, 2004 at 2:38:26 PM
I have also included everything needed in the source and demo projects. I hope this helps someone.