Introduction
XML Stylesheet Transformations (XSLT) is defined as a language for transforming source XML documents into another document formats using XML Path Language (XPath) as a query language. This is particularly useful when incoming or outgoing XML documents do not match the document type expected by the target system.
In an XSL transformation, an XSLT processor reads both an XML document and an XSLT style sheet. Based on the instructions the processor finds in the XSLT style sheet, it outputs a new XML document or fragment. There’s also special support for outputting HTML. With some effort, most XSLT processors can also be made to output essentially random text, though XSLT is designed primarily for XML-to-XML and XML-to-HTML transformations.
Discussion
XSLT operates by transforming one XML tree into another XML tree. More precisely, an XSLT processor accepts as input a tree represented as an XML document and produces as output a new tree, also represented as an XML document. Hence, XSLT assumes that three documents are in use: the source document, the XSLT stylesheet document and the result document. The source document is simply a well-formed XML document that provides the input for the transformation. The stylesheet document is an XML document that uses the XSLT vocabulary for expressing transformation rules. The result document is a text document that is produced by running the source document through the transformations found in XSLT stylesheet.
The XSLT transformation can be handled in the .NET platform, which is demonstrated by the code below:
using System; using System.IO; using System.Xml; using System.Xml.Xsl; using System.Xml.XPath; public class TransformXML { //This will transform xml document using xslt and produce result xml document //and display it public static void Main(string[] args) { try { XPathDocument myXPathDocument = new XPathDocument(sourceDoc); XslTransform myXslTransform = new XslTransform(); XmlTextWriter writer = new XmlTextWriter(resultDoc, null); myXslTransform.Load(xsltDoc); myXslTransform.Transform(myXPathDocument, null, writer); writer.Close(); StreamReader stream = new StreamReader (resultDoc); Console.Write("**This is result document**\n\n"); Console.Write(stream.ReadToEnd()); } catch (Exception e) { Console.WriteLine ("Exception: {0}", e.ToString()); } } } |
Note: this code will run in Console application
This sample relies on an XPathDocument
class named myXPathDocument
that loads the XML document that will be transformed, and an XslTransform
class named myXslTransform
that performs the transformation from the source document into another document, which is a result document. The XslTransform
class, found in the System.Xml.Xsl
namespace, is the XSLT processor that implements the XSLT version 1.0 recommendation.
The code above is handling the XSLT output with the XmlTextWriter
class, which functionality inherited from the XmlWriter
abstract class, is useful for writing out the character streams. In this sample, the XmlTextWriter
takes 2 parameters which are the filename as a String and the Encoding which in this case is defined as null
. Once an XmlTextWriter
object is created, it writes the transformed file to the disk. The file that is created named resultDoc
, which is the first parameter passed to the XmlTextWriter
constructor.
In order to perform a transformation using XslTransform
, first create an XslTransform
object and load it with the desired XSLT document (by calling Load
). The Load
method of XslTransform
class loads the XSL Stylesheet from disk called xsltDoc
. Finally, the transform is executed by calling Transform
method of the XslTransform
class object. Transform
method takes the XML document object and the XmlTextWriter
objects as parameters. The second parameter of the Transform
method is used to pass additional runtime arguments, it is left to null
. After the transform is complete, XmlTextWriter
object is closed to complete the writing of the new XML document file to the disk.
Reading the file back in is done by creating a stream for reading and using the StreamReader
to interpret the contents of the file. Finally, it will display the contents of the result document on the screen by calling the method Write
from Console
class.
There is an alternative way of handling the transformation. Instead of having to create and load the input source document and writing to a file stream, user can simply use the Transform
method of XslTransform
to load a document and write to file directly by loading an XML document from file, applying the XSLT file, and writing the result to the file as shown in the code below:
XslTransform myXslTransform = new XslTransform(); myXslTransform.Load(xsltDoc); myXslTransform.Transform(sourceDoc, resultDoc); |
Conclusion
XSLT, the extensible stylesheet language for transformations, is a language that provides the mechanism to transform and manipulate XML data. It is used to transform XML documents into another documents, for example other XML document, HTML document or text document. XSLT processors parse the input XML document, as well as the XSLT stylesheet and then process the instructions found in the XSLT stylesheet, using the elements from input XML document. During the processing of the XSLT instructions, a structured XML output is created.
In .NET framework, this transformation is handled using the Load
and Transform
method from the XslTransform
class. Initially, an XslTransform
object is instantiated, which is the engine to perform XSLT transformations on XML documents in the .NET framework. The Load
method of the XslTransform
class is called to load the XSL stylesheet from disk. Finally, the Transform
method is executed, takes the XPathDocument
and XmlTextWriter
object as parameters. On the other hand, user can call the Transform
method to initiate the transformation and passing in the source XML document and the transformed XML document name. Essentially, the XSLT processor processes the input document, applies the stylesheet and produces the result document.
Downloads
There are two sets of files associated with this article. The first is a Windows forms application and includes much of the code listed here. There is also a smaller command-line version that you may find easier to understand.
Appendix I : C# Source Code Listing
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.IO; using System.Xml; using System.Xml.Xsl; using System.Xml.XPath; namespace Transformer { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.TextBox txtSource; private System.Windows.Forms.TextBox txtXslt; private System.Windows.Forms.Label lblSource; private System.Windows.Forms.Label lblXslt; private System.Windows.Forms.Button btnGenerate; private String sourceDoc = ""; private String xsltDoc = ""; private String resultDoc = "result.xml"; private System.Windows.Forms.TextBox txtResult; private System.Windows.Forms.Button btnReset; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.txtSource = new System.Windows.Forms.TextBox(); this.txtXslt = new System.Windows.Forms.TextBox(); this.lblSource = new System.Windows.Forms.Label(); this.lblXslt = new System.Windows.Forms.Label(); this.btnGenerate = new System.Windows.Forms.Button(); this.txtResult = new System.Windows.Forms.TextBox(); this.btnReset = new System.Windows.Forms.Button(); this.SuspendLayout(); // // txtSource // this.txtSource.Location = new System.Drawing.Point(136, 16); this.txtSource.Name = "txtSource"; this.txtSource.Size = new System.Drawing.Size(136, 22); this.txtSource.TabIndex = 0; this.txtSource.Text = ""; // // txtXslt // this.txtXslt.Location = new System.Drawing.Point(136, 48); this.txtXslt.Name = "txtXslt"; this.txtXslt.Size = new System.Drawing.Size(136, 22); this.txtXslt.TabIndex = 1; this.txtXslt.Text = ""; // // lblSource // this.lblSource.Location = new System.Drawing.Point(16, 16); this.lblSource.Name = "lblSource"; this.lblSource.TabIndex = 2; this.lblSource.Text = "Source XML"; // // lblXslt // this.lblXslt.Location = new System.Drawing.Point(16, 48); this.lblXslt.Name = "lblXslt"; this.lblXslt.TabIndex = 3; this.lblXslt.Text = "XSLT"; // // btnGenerate // this.btnGenerate.Location = new System.Drawing.Point(40, 88); this.btnGenerate.Name = "btnGenerate"; this.btnGenerate.TabIndex = 4; this.btnGenerate.Text = "Generate"; this.btnGenerate.Click += new System.EventHandler(this.btnGenerate_Click); // // txtResult // this.txtResult.Location = new System.Drawing.Point(16, 120); this.txtResult.Multiline = true; this.txtResult.Name = "txtResult"; this.txtResult.ReadOnly = true; this.txtResult.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtResult.Size = new System.Drawing.Size(264, 152); this.txtResult.TabIndex = 5; this.txtResult.Text = ""; // // btnReset // this.btnReset.Location = new System.Drawing.Point(160, 88); this.btnReset.Name = "btnReset"; this.btnReset.TabIndex = 6; this.btnReset.Text = "Reset"; this.btnReset.Click += new System.EventHandler(this.btnReset_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(6, 15); this.ClientSize = new System.Drawing.Size(292, 288); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.btnReset, this.txtResult, this.btnGenerate, this.lblXslt, this.lblSource, this.txtXslt, this.txtSource}); this.Name = "Form1"; this.Text = "XML Transformer"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } private void Form1_Load(object sender, System.EventArgs e) { } private void btnGenerate_Click(object sender, System.EventArgs e) { if ((txtSource.Text.Trim() == "") || (txtXslt.Text.Trim() == "")) { MessageBox.Show("Enter the filename!", "File Name Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); } try { XPathDocument myXPathDocument = new XPathDocument (sourceDoc); XslTransform myXslTransform = new XslTransform(); XmlTextWriter writer = new XmlTextWriter(resultDoc, null); myXslTransform.Load(xsltDoc); myXslTransform.Transform(myXPathDocument, null, writer); writer.Close(); StreamReader stream = new StreamReader (resultDoc); txtResult.Text = stream.ReadToEnd(); } catch (FileNotFoundException filexc) { MessageBox.Show("File Not Found!", "File Not Found Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (Exception exc) { Console.WriteLine ("Exception: {0}", exc.ToString()); } } private void btnReset_Click(object sender, System.EventArgs e) { txtSource.Text = ""; txtXslt.Text = ""; txtResult.Text = ""; } } } |
Appendix II: XML Source Code Listing
<?xml version='1.0'?> <!-- This file represents a fragment of a book store inventory database --> <bookstore> <book genre="autobiography" publicationdate="1981" ISBN="1-861003-11-0"> <title>The Autobiography of Benjamin Franklin</title> <author> <first-name>Benjamin</first-name> <last-name>Franklin</last-name> </author> <price>8.99</price> </book> <book genre="novel" publicationdate="1967" ISBN="0-201-63361-2"> <title>The Confidence Man</title> <author> <first-name>Herman</first-name> <last-name>Melville</last-name> </author> <price>11.99</price> </book> <book genre="philosophy" publicationdate="1991" ISBN="1-861001-57-6"> <title>The Gorgias</title> <author> <name>Plato</name> </author> <price>9.99</price> </book> </bookstore> |
Appendix III: XSL Source Code Listing
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <root> <xsl:apply-templates/> </root> </xsl:template> <xsl:template match="bookstore"> <!-- Prices and books --> <bookstore> <xsl:apply-templates select="book"/> </bookstore> </xsl:template> <xsl:template match="book"> <book> <xsl:attribute name="ISBN"> <xsl:value-of select="@ISBN"/> </xsl:attribute> <price><xsl:value-of select="price"/></price><xsl:text> </xsl:text> </book> </xsl:template> </xsl:stylesheet> |
Appendix IV: Test Strategy
Instructions:
- Type in the XML file name (without extension)
- Type in the XSL file name (without extension)
- Click Generate button
Test Scenario Objective:
Test if the XML file given is transformed to new XML document by applying the XSL file
Test Cases
1. Type in valid XML filename and valid XSL filename
Expected Result: The file is created and the contents of the file are displayed in the Result Text Box
Actual Result: The file is created and the contents of the file are displayed in the Result Text Box
2. Type in invalid XML filename or invalid XSL filename
Expected Result: Pop up message box, telling user that File Not Found
Actual Result: Pop up message box, telling user that File Not Found
References
– Box, D., Skonnard, A., Lam, J. (2000), ‘XSL Transformations: XSLT Alleviates XML Schema Incompatibility Headaches’, MSDN Magazine August 2000
– Gardner, J.R. (2002), XSLT & XPATH: A Guide to XML Transformations, Prentice Hall, New Jersey, USA
– Harold, E.R. (2001), XML Bible 2nd Edition, Hungry Minds, USA
– Ryan, B. (2002), Read Less-Learn More C#, Hungry Minds, USA
– Skonnard, A. (2001), ‘XML in .NET: .NET Framework XML Classes and C# Offer Simple, Scalable Data Manipulation’, MSDN Magazine January 2001
– Turtschi, A., et.al (2002), C# .NET Web Developer Guide, Syngress Publishing Inc., Rockland, MA, USA
– Wahlin, D. (2002), ‘4 XSLT Output Tips’, XML & Web Services Magazine April/May 2002
– MSDN Home website, http://msdn.microsoft.com/default.asp
– Programmers Heaven website, http://www.programmersheaven.com/
– Perfect XML website, http://www.perfectxml.com/
– C# Corner website, http://www.c-sharpcorner.com/