XSLT Transformations


XSLT is a language that is used to transform XML documents so that they can be presented visually. You have performed a similar task before. When working with XML serialization, you rewrote the FilmOrder class. This class was used to serialize a movie order object to XML using nodes that contained English-language names. The rewritten version of this class, ElokuvaTilaus, serialized XML nodes containing Finnish names. Source Code Style attributes were used in conjunction with the XmlSerializer class to accomplish this transformation. Two words in this paragraph send chills down the spine of any experienced developer: rewrote and rewritten. The point of an XSL transform is to use an alternate language (XSLT) to transform the XML rather than rewriting the source code, SQL commands, or some other mechanism used to generate XML.

Conceptually, XSLT is straightforward. A file with an .xslt extension describes the changes (transformations) that will be applied to a particular XML file. Once this is completed, an XSLT processor is provided with the source XML file and the XSLT file, and performs the transformation. The System.Xml .Xsl.XslTransform class is such an XSLT processor. A new processor in .NET 2.0 is the XsltCommand object found at SystemXml.Query.XsltCommand. This section looks at using both of these processors.

The XSLT file is itself an XML document, although certain elements within this document are XSLT-specific commands. Dozens of XSLT commands can be used in writing an XSLT file. The first example explores the following XSLT elements (commands):

  • stylesheet - This element indicates the start of the style sheet (XSL) in the XSLT file.

  • template - This element denotes a reusable template for producing specific output. This output is generated using a specific node type within the source document under a specific context. For example, the text <xsl: template match=”/“> selects all root notes (“/“) for the specific transform template.

  • for-each - This element applies the same template to each node in the specified set. Recall the example class (FilmOrder_Multiple) that could be serialized. This class contained an array of movie orders. Given the XML document generated when a FilmOrder_Multiple is serialized, each movie order serialized could be processed using <xsl:for-each select = “FilmOrder_Multiple/multiFilmOrders/FilmOrder”>.

  • value-of - This element retrieves the value of the specified node and inserts it into the document in text form. For example, <xsl:value-of select=”name” /> would take the value of the XML element <name> and insert it into the transformed document.

When serialized, the FilmOrder_Multiple class generates XML such as the following (where indicates where additional <FilmOrder> elements may reside):

 <?xml version="1.0" encoding="you-ascii" ?> <FilmOrder_Multiple>     <multiFilmOrders>         <FilmOrder>             <name>Grease</name>             <filmId>101</filmId>             <quantity>10</quantity>         </FilmOrder>         ...     </multiFilmOrders> </FilmOrder_Multiple>

The preceding XML document is used to generate a report that is viewed by the manager of the movie supplier. This report is in HTML form, so that it can be viewed via the Web. The XSLT elements you previously reviewed (stylesheet, template, and for-each) are the only XSLT elements required to transform the XML document (in which data is stored) into an HTML file (data that can be displayed). An XSLT file DisplayThatPuppy.xslt contains the following text, which is used to transform a serialized version, FilmOrder_Multiple:

  <?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  <xsl:template match="/">       <HTML>       <TITLE>What people are ordering</TITLE>       <BODY>           <TABLE BORDER="1">             <TR>               <TD><B>Film Name</B></TD>               <TD><B>Film ID</B></TD>               <TD><B>Quantity</B></TD>             </TR>             <xsl:for-each select=              "FilmOrder_Multiple/multiFilmOrders/FilmOrder">             <TR>                <TD><xsl:value-of select="name" /></TD>                <TD><xsl:value-of select="filmId" /></TD>                <TD><xsl:value-of select="quantity" /></TD>             </TR>             </xsl:for-each>         </TABLE>       </BODY>     </HTML>   </xsl:template> </xsl:stylesheet> 

In the preceding XSLT file, the XSLT elements are marked in bold. These elements perform operations on the source XML file containing a serialized FilmOrder_Multiple object and generate the appropriate HTML file. Your file contains a table (marked by the table tag, <TABLE>) that contains a set of rows (each row marked by a table row tag, <TR>). The columns of the table are contained in table data tags, <TD>. The XSLT file contains the header row for the table:

 <TR>     <TD><B>Film Name</B></TD>     <TD><B>Film ID</B></TD>     <TD><B>Quantity</B></TD> </TR>

Each row containing data (an individual movie order from the serialized object, FilmOrder_Multiple) is generated using the XSLT element, for-each, to traverse each <FilmOrder> element within the source XML document:

 <xsl:for-each select=     "FilmOrder_Multiple/multiFilmOrders/FilmOrder">

The individual columns of data are generated using the value-of XSLT element, in order to query the elements contained within each <FilmOrder> element (<name>, <filmId>, and <quantity>):

 <TR>     <TD><xsl:value-of select="name" /></TD>     <TD><xsl:value-of select="filmId" /></TD>     <TD><xsl:value-of select="quantity" /></TD> </TR>

The code to create a displayable XML file using the XslTransform object is as follows:

  Dim myXslTransform As XslTransform = New XslTransform Dim destFileName As String = "..\ShowIt.html" myXslTransform.Load("..\DisplayThatPuppy.xslt") myXslTransform.Transform("..\FilmOrders.xml", destFileName) System.Diagnostics.Process.Start(destFileName) 

This consists of only seven lines of code, with the bulk of the coding taking place in the XSLT file. The previous code snippet created an instance of a System.Xml.Xsl.XslTransform object named myXslTransform. The Load() method of this class is used to load the XSLT file you previously reviewed, DisplayThatPuppy.xslt. The Transform() method takes a source XML file as the first parameter, which in this case was a file containing a serialized FilmOrder_Multiple object. The second parameter is the destination file created by the transform (ShowIt.html). The Start() method of the Process class is used to display the HTML file. This method launches a process that is most suitable for displaying the file provided. Basically, the extension of the file dictates which application will be used to display the file. On a typical Windows machine, the program used to display this file is Internet Explorer, as shown in Figure 11-4.

image from book
Figure 11-4

Tip 

Don’t confuse displaying this HTML file with ASP.NET. Displaying an HTML file in this manner takes place on a single machine without the involvement of a Web server. Using ASP.NET is more complex than displaying an HTML page in the default browser.

As demonstrated, the backbone of the System.Xml.Xsl namespace is the XslTransform class. This class uses XSLT files to transform XML documents. XslTransform exposes the following methods and properties:

  • XmlResolver - This get/set property is used to specify a class (abstract base class, XmlResolver) that is used to handle external references (import and include elements within the style sheet). These external references are encountered when a document is transformed (the method, Transform(), is executed). The System.Xml namespace contains a class, XmlUrlResolver, which is derived from XmlResolver. The XmlUrlResolver class resolves the external resource based on a URI.

  • Load - This overloaded method loads an XSLT style sheet to be used in transforming XML documents. It is permissible to specify the XSLT style sheet as a parameter of type XPathNavigator, filename of XSLT file (specified as parameter type String), XmlReader, or IXPathNavigable. For each of type of XSLT supported, an overloaded member is provided that allows an XmlResolver to also be specified. For example, it is possible to call Load(String, XmlResolver) where String corresponds to a filename and XmlResolver is an object that handles references in the style sheet of type xsl:import and xsl:include. It would also be permissible to pass in a value of Nothing for the second parameter of the Load() method (so that no XmlResolver would be specified). Note that considerable changes have been made to the parameters that the Load() method takes between versions 1.0 and 1.1 of the .NET Framework. Look at the SDK documentation for details on any late-breaking changes that you might encounter when working with the XslTransform class.

  • Transform - This overloaded method transforms a specified XML document using the previously specified XSLT style sheet and an XmlResolver. The location where the transformed XML is to be output is specified as a parameter to this method. The first parameter of each overloaded method is the XML document to be transformed. This parameter can be represented as an IXPathNavigable, XML filename (specified as parameter type String), or XPathNavigator. Considerable changes have been made to the parameters that the Transform() method takes between versions 1.0 and 1.1 of the .NET Framework. Check the SDK documentation for details on any changes that you might encounter when working with the XslTransform class.

The most straightforward variant of the Transform() method is Transform(String, String, XmlResolver). In this case, a file containing an XML document is specified as the first parameter, a filename that receives the transformed XML document is specified as the second parameter, and the XmlResolver is used as the third parameter. This is exactly how the first XSLT example utilized the Transform method:

 myXslTransform.Transform("..\FilmOrders.xml", destFileName)

The first parameter to the Transform method can also be specified as IXPathNavigable or XPath - Navigator. Either of these parameter types allows the XML output to be sent to an object of type Stream, TextWriter, or XmlWriter. When these two flavors of input are specified, a parameter containing an object of type XsltArgumentList can be specified. An XsltArgumentList object contains a list of arguments that are used as input to the transform.

When working with a .NET 2.0 project, it is preferable to use the XslCompiledTransform object instead of the XslTransform object, because the XslTransform object is considered obsolete. When using the new XslCompiledTransform object, you construct the file using the following code:

  Dim myXslCompiledTransform As XslCompiledTransform = New XslCompiledTransform Dim destFileName As String = "..\ShowIt.html" myXslCompiledTransform.Load("..\DisplayThatPuppy.xslt") myXslCompiledTransform.Transform("..\FilmOrders.xml", destFileName) System.Diagnostics.Process.Start(destFileName) 

The XslCompiledTransform object uses the same Load() and Transform() methods as the XslTransform object from .NET 1.0/1.1. The new Transform() method provides the following signatures:

 XslCompiledTransform.Transform(IXPathNavigable, XmlWriter) XslCompiledTransform.Transform(IXPathNavigable, XsltArguementList, XmlWriter) XslCompiledTransform.Transform(IXPathNavigable, XsltArguementList, TextWriter) XslCompiledTransform.Transform(IXPathNavigable, XsltArguementList, Stream) XslCompiledTransform.Transform(XmlReader, XmlWriter) XslCompiledTransform.Transform(XmlReader, XsltArguementList, XmlWriter) XslCompiledTransform.Transform(XmlReader, XsltArguementList, TextWriter) XslCompiledTransform.Transform(XmlReader, XsltArguementList, Stream) XslCompiledTransform.Transform(XmlReader, XsltArguementList, XmlWriter,    XmlResolver) XslCompiledTransform.Transform(String, String) XslCompiledTransform.Transform(String, XmlWriter) XslCompiledTransform.Transform(String, XsltArguementList, XmlWriter) XslCompiledTransform.Transform(String, XsltArguementList, TextWriter) XslCompiledTransform.Transform(String, XsltArguementList, Stream)

In this case, String is a representation of the .xslt file that should be used in the transformation. Here, String represents the location of specific files (whether it is source files or output files). Some of the signatures also allow for output to XmlWriter objects, streams, and TextWriter objects. These can be used by also providing additional arguments using the XsltArgumentList object.

The preceding example used the second signature XslCompiledTransform.Transform(String, String), which asked for the source file and the destination file (both string representations of the location of said files):

 myXslCompiledTransform.Transform("..\FilmOrders.xml", destFileName)

XSLT Transforming between XML Standards

The first example used four XSLT elements to transform an XML file into an HTML file. Such an example has merit, but it doesn’t demonstrate an important use of XSLT: transforming XML from one standard into another standard. This may involve renaming elements/attributes, excluding elements/attributes, changing datatypes, altering the node hierarchy, and representing elements as attributes, and vice versa.

A case of differing XML standards could easily happen to your software that automates movie orders coming into a supplier. Imagine that the software, including its XML representation of a movie order, is so successful that you sell 100,000 copies. However, just as you’re celebrating, a consortium of the largest movie supplier chains announces that they are no longer accepting faxed orders and that they are introducing their own standard for the exchange of movie orders between movie sellers and buyers.

Rather than panic, you simply ship an upgrade that includes an XSLT file. This upgrade (a bit of extra code plus the XSLT file) transforms your XML representation of a movie order into the XML representation dictated by the consortium of movie suppliers. Using an XSLT file enables you to ship the upgrade immediately. If the consortium of movie suppliers revises their XML representation, you are not obliged to change your source code. Instead, you can simply ship the upgraded XSLT file that ensures that each movie order document is compliant.

The specific source code that executes the transform is as follows:

  Dim myXslCompiledTransform As XslCompiledTransform = New XslCompiledTransform myXslCompiledTransform.Load("..\ConvertLegacyToNewStandard.xslt") myXslCompiledTransform.Transform("..\MovieOrdersOriginal.xml",    "..\MovieOrdersModified.xml") 

The three lines of code accomplish the following:

  1. Create an XslCompiledTransform object

  2. Use the Load method to load an XSLT file (ConvertLegacyToNewStandard.xslt)

  3. Use the Transform method to transform a source XML file (MovieOrdersOriginal.xml) into a destination XML file (MovieOrdersModified.xml)

Recall that the input XML document (MovieOrdersOriginal.xml) does not match the format required by your consortium of movie supplier chains. The content of this source XML file is as follows:

 <?xml version="1.0" encoding="utf-8" ?> <FilmOrder_Multiple>     <multiFilmOrders>         <FilmOrder>             <name>Grease</name>             <filmId>101</filmId>             <quantity>10</quantity>         </FilmOrder>         ...     </multiFilmOrders> </FilmOrder_Multiple>

The format exhibited in the preceding XML document does not match the format of the consortium of movie supplier chains. To be accepted by the collective of suppliers, you must transform the document as follows:

  • Remove element <FilmOrder_Multiple>.

  • Remove element <multiFilmOrders>.

  • Rename element <FilmOrder> to <DvdOrder>.

  • Remove element <name> (the film’s name is not to be contained in the document).

  • Rename element <quantity> to HowMuch and make HowMuch an attribute of <DvdOrder>.

  • Rename element <filmId> to FilmOrderNumber and make FilmOrderNumber an attribute of <DvdOrder>.

  • Display attribute HowMuch before attribute FilmOrderNumber.

A great many of the steps performed by the transform could have been achieved using an alternative technology. For example, you could have used Source Code Style attributes with your serialization to generate the correct XML attribute and XML element name. If you had known in advance that a consortium of suppliers was going to develop a standard, you could have written your classes to be serialized based on the standard. The point was that you didn’t know and now one standard (your legacy standard) has to be converted into a newly adopted standard of the movie suppliers’ consortium. The worst thing you could do would be to change your working code and then force all users working with the application to upgrade. It is vastly simpler to add an extra transformation step to address the new standard.

The XSLT file that facilitates the transform is named ConvertLegacyToNewStandard.xslt. A portion of this file is implemented as follows:

  <?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   <xsl:template match="FilmOrder">     <! rename <FilmOrder> to <DvdOrder> >     <xsl:element name="DvdOrder">       <! Make element 'quantity' attribute HowMuch             Notice attribute HowMuch comes before attribute FilmOrderNumber >       <xsl:attribute name="HowMuch">         <xsl:value-of select="quantity"></xsl:value-of>       </xsl:attribute>       <! Make element filmId attribute FilmOrderNumber >       <xsl:attribute name="FilmOrderNumber">         <xsl:value-of select="filmId"></xsl:value-of>       </xsl:attribute>     </xsl:element>     <! end of DvdOrder element >   </xsl:template> </xsl:stylesheet> 

In the previous snippet of XSLT, the following XSLT elements are used to facilitate the transformation:

  • <xsl:template match=“FilmOrder”> - All operations in this template XSLT element take place on the original document’s FilmOrder node.

  • <xsl:element name=“DvdOrder”> - The element corresponding to the source document’s FilmOrder element will be called DvdOrder in the destination document.

  • <xsl:attribute name=“HowMuch”> - An attribute named HowMuch will be contained in the previously specified element. The previously specified element is <DvdOrder>. This attribute XSLT element for HowMuch comes before the attribute XSLT element for FilmOrderNumber. This order was specified as part of your transform to adhere to the new standard.

  • <xsl:value-of select='quantity’> - Retrieve the value of the source document’s <quantity> element and place it in the destination document. This instance of XSLT element value-of provides the value associated with attribute HowMuch.

Two new XSLT elements have crept into your vocabulary: element and attribute. Both of these XSLT elements live up to their names. Specifying the XSLT element named element places an element in the destination XML document. Specifying the XSLT element named attribute places an attribute in the destination XML document. The XSLT transform found in ConvertLegacyToNewStandard.xslt is too long to review here. When reading this file in its entirety, remember that this XSLT file contains inline documentation to specify precisely what aspect of the transformation is being performed at which location in the XSLT document. For example, the following XML code comments indicate what the XSLT element attribute is about to do:

 <!-- Make element 'quantity' attribute HowMuch       Notice attribute HowMuch comes before attribute FilmOrderNumber > <xsl:attribute name="HowMuch">      <xsl:value-of select='quantity'></xsl:value-of> </xsl:attribute>

The preceding example spanned several pages but contained just three lines of code. This demonstrates that there is more to XML than learning how to use it in Visual Basic and the .NET Framework. Among other things, you also need a good understanding of XSLT, XPath, and XQuery.

Other Classes and Interfaces in System.Xml.Xsl

We just took a good look at XSLT and the System.Xml.Xsl namespace, but there is a lot more to it than that. Other classes and interfaces exposed by System.Xml.Xsl namespace include the following:

  • IXsltContextFunction - This interface accesses at runtime a given function defined in the XSLT style sheet.

  • IXsltContextVariable - This interface accesses at runtime a given variable defined in the XSLT style sheet.

  • XsltArgumentList - This class contains a list of arguments. These arguments are XSLT parameters or XSLT extension objects. The XsltArgumentList object is used in conjunction with the Transform method of XslTransform.

  • XsltContext - This class contains the state of the XSLT processor. This context information allows XPath expressions to have their various components resolved (functions, parameters, and namespaces).

  • XsltException, XsltCompileException - These classes contain the information pertaining to an exception raised while transforming data. XsltCompileException is derived from XsltException.




Professional VB 2005 with. NET 3. 0
Professional VB 2005 with .NET 3.0 (Programmer to Programmer)
ISBN: 0470124709
EAN: 2147483647
Year: 2004
Pages: 267

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net