65.9K
CodeProject is changing. Read more.
Home

A better MSXSL.EXE: Adding the ability to Transform XSL with Embedded Scripts

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (4 votes)

Nov 18, 2004

2 min read

viewsIcon

74082

downloadIcon

1310

This program creates a wrapper around the XSLT process that allows you to transform an XML file using the embedded MSXSL script.

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

<?xml version="1.0" encoding="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" version="1.0"
     xmlns:msxsl="urn:schemas-microsoft-com:xslt"
     xmlns:utils="urn:script-items">
<msxsl:script language="C#" implements-prefix="utils">
     <![CDATA[
     public string getDate(){
          return (DateTime.Today.ToLongDateString() + " at " + 
                  DateTime.Now.ToLongTimeString() );
     }
     ]]>
</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.