Cory Foy

Wednesday, August 24, 2005

XSL Transformer

Today I was looking for a simple way to apply an XSL stylesheet to an XML document. I didn't want resolvers, files, or anything like that. I wanted to take an XSL string and an XML string, and apply it to get the output.

I started to play around with the System.Xml stuff, and then remembered that one of the tools I use pretty much every day is a frickin XSL Transformer I wrote! What better place to look then somewhere I had already solved it.

The core of the code is around a Transformer class that can take in either two XmlDocuments or two strings and applies the Xsl to the Xml, returning both the XmlDocument and the Xml string:


    1 using System;


    2 using System.IO;


    3 using System.Xml;


    4 using System.Xml.Xsl;


    5 


    6 namespace MobileHWY.DAL.MSSQLCommandMapper


    7 {


    8     /// <summary>


    9     /// Helper class to wrap XSL transformations and provide


   10     /// utilities for preparing documents


   11     /// </summary>


   12     public class Transformer


   13     {


   14 


   15         #region Declarations


   16         private XmlDocument xmlDoc;


   17         private XmlDocument xslDoc;


   18         private XmlDocument transformedDoc;


   19         private String transformedString;


   20         #endregion


   21 


   22         #region Constructors


   23 


   24         public Transformer()


   25         {


   26 


   27         }


   28 


   29         public Transformer(XmlDocument xmlDoc, XmlDocument xslDoc)


   30         {


   31             this.xmlDoc = xmlDoc;


   32             this.xslDoc = xslDoc;


   33         }


   34 


   35         public Transformer(String xmlDoc, String xslDoc)


   36         {


   37             try


   38             {


   39                 this.xmlDoc = ConvertStringToDocument(xmlDoc);


   40             }


   41             catch(Exception ex)


   42             {


   43                 throw new ApplicationException("An error occurred transforming the XML Document", ex);


   44             }


   45 


   46             try


   47             {


   48                 this.xslDoc = ConvertStringToDocument(xslDoc);


   49             }


   50             catch(Exception ex)


   51             {


   52                 throw new ApplicationException("An error occurred transforming the XSL Document", ex);


   53             }


   54         }


   55 


   56         #endregion


   57 


   58         #region Properties


   59         public XmlDocument XmlDocument


   60         {


   61             get


   62             {


   63                 return xmlDoc;


   64             }


   65 


   66             set


   67             {


   68                 xmlDoc = value;


   69             }


   70         }


   71 


   72         public XmlDocument XslDocument


   73         {


   74 


   75             get


   76             {


   77                 return xslDoc;


   78             }


   79             set


   80             {


   81                 xslDoc = value;


   82             }


   83         }


   84 


   85         public XmlDocument TransformedDocument


   86         {


   87             get


   88             {


   89                 return transformedDoc;


   90             }


   91         }


   92 


   93         public String TransformedString


   94         {


   95 


   96             get


   97             {


   98                 return transformedString;


   99             }


  100         }


  101         #endregion


  102 


  103         #region Methods


  104         public void Transform()


  105         {


  106             if(!ValidateInput())


  107             {


  108                 return;


  109             }


  110 


  111             //Set up the XSL transformer


  112             XslTransform transformer = new XslTransform();


  113 


  114             //Create a memory stream so we can transform the document into memory


  115             //instead of to a file and wrap it with an XmlTextWriter.


  116             MemoryStream memStream = new MemoryStream();


  117             XmlTextWriter memWriter = new XmlTextWriter(memStream, null);


  118 


  119             //Load the XSL Document into the transformer


  120             transformer.Load(xslDoc, null, null);


  121 


  122             //Transform the XML document using the loaded XSL and place the


  123             //output in the memory stream


  124             transformer.Transform(xmlDoc, null, memWriter, null);


  125 


  126             //reset the byte position in the memory stream so we can read


  127             //from the beginning


  128             memStream.Position = 0;


  129 


  130             //Create a reader to get the document back out of the memory stream


  131             XmlTextReader outReader = new XmlTextReader(memStream);


  132 


  133             //Create a writer to place it in. We will also be creating a seperate


  134             //XmlTextWriter so we can control the formatting of the output.


  135             StringWriter sw = new StringWriter();


  136             XmlTextWriter outWriter = new XmlTextWriter(sw);


  137 


  138             //Set up the output formatting instructions


  139             outWriter.Formatting = Formatting.Indented;


  140             outWriter.Indentation = 4;


  141 


  142             //actually write our the document


  143             outWriter.WriteNode(outReader, true);


  144 


  145             //clean up after ourselves


  146             outReader.Close();


  147             outWriter.Close();


  148 


  149             //place the results in the appropriate variables


  150             transformedString = sw.ToString();


  151             transformedDoc = ConvertStringToDocument(transformedString);


  152 


  153         }


  154 


  155         private XmlDocument ConvertStringToDocument(String doc)


  156         {


  157             XmlDocument mpDoc  = new XmlDocument();


  158             mpDoc.LoadXml(doc);


  159             return mpDoc;


  160         }


  161 


  162         private Boolean ValidateInput()


  163         {


  164             if(xmlDoc == null)


  165             {


  166                 throw new Exception("The XML Document must be loaded before calling Transform");


  167             }


  168             if(xslDoc == null)


  169             {


  170                 throw new Exception("The XSL Document must be loaded before calling Transform");


  171             }


  172             return true;


  173         }


  174         #endregion


  175 


  176     }


  177 }





Here's an example NUnit test showing how to use it:


public void TestTransformXmlDocument()


{


    string xsl = "<?xml version=\"1.0\"?>"


        + "<xsl:stylesheet version=\"1.0\" "


        + "  xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"


        + " <xsl:template match=\"/\">"


        + "   <output>1</output>"


        + " </xsl:template>"


        + "</xsl:stylesheet>";


    string xml = "<?xml version=\"1.0\"?><test><val>1</val></test>";


    string expectedOutXml = "<output>1</output>";


    XmlDocument xmlDoc = new XmlDocument();


    xmlDoc.LoadXml(xml);


    XmlDocument xslDoc = new XmlDocument();


    xslDoc.LoadXml(xsl);


 


    Transformer transformer = new Transformer(xmlDoc, xslDoc);


    transformer.Transform();


 


    Assert.AreEqual(expectedOutXml, transformer.TransformedString);


 


}


1 Comments:

  • "Here's an example NUnit test showing how to use it:"

    As someone just getting test infected, I find that statement, even completely out of context, quite profound.

    By Anonymous Anonymous, at 2:00 PM  

Post a Comment

Links to this post:

Create a Link

<< Home