Using XSL


To transform a document using XSL, you need to create a style sheet that defines the transformation and then pass the style sheet to the XSL processor. The first important thing to note is that XSL style sheets are simply XML documents. They have all the familiar syntax and are written, structured, and processed in just the same way as any other XML document.

XSL transformations are handled using the XslTransform class from the
System::Xml::Xsl namespace. The class has only three members and is very simple to use. Here’s the typical sequence you follow to apply a transformation:

  1. Create an XslTransform object.

  2. Use its Load method to load the style sheet from a file, a URL, an XmlReader, or an XPathNavigator.

  3. Call the Transform method to perform the transformation. You can input and output data in a number of ways, as you’ll see in the following exercise.

The following short exercise will show you how to process XML using an XSL style sheet. Like XPath, XSL is too complex to introduce in any detail here, but if you haven’t met XSL before, you’ll find basic details in the following sidebar, “The Basics of XSL Style Sheets.”

start sidebar
The Basics of XSL Style Sheets

This brief explanation of how XSL style sheets work should help you understand the one used in the exercise. First, XSL style sheets are simply another type of XML document, so they have to obey all the usual rules. They start with an XML declaration, they contain a single root element, and all elements must nest and be closed correctly.

An XSL style sheet is defined by a stylesheet element, which has to define the XSL namespace and the version attribute. This namespace has to use the correct URL; otherwise, the element won’t be recognized as an XSL style sheet. It’s normal for the namespace prefix to be xsl, but this prefix isn’t essential.

XSL works by specifying templates that use XPath expressions to match sets of nodes in the document. The following example style sheet defines one template that matches the root element. When the style sheet is processed, the XSL engine looks at the body of the template and applies it to the node list. Any other XSL commands are processed, and anything it doesn’t recognize as an XSL command gets echoed to the output. In this example, the HTML isn’t recognized as XSL commands, so it’s echoed to the output.

Note that content—such as the HTML—is still processed by the XSL processor, so it has to be valid XML. All elements must be correctly nested and must have closing tags.

There are a number of XSL commands, two of which are used in the following exercise. The xsl:for-each command provides a looping construct that loops over all the nodes that match the current template. The xsl:value-of command typically retrieves the value of an element or attribute. You can see in the exercise how the two attributes of the height element are used to build the contents of the table cell.

end sidebar

Here’s the style sheet that I’ll use to transform the XML. It contains one template that matches the root element and then prints out some of the fields for each volcano element in a table.

<?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/geology"> <html> <head><title>Volcanoes</title></head> <body> <h1>Volcanoes</h1> <table width="75%" border="1"> <tr> <th>Name</th> <th>Location</th> <th>Height</th> <th>Type</th> </tr> <xsl:for-each select="volcano"> <tr> <td><xsl:value-of select="@name"/></td> <td><xsl:value-of select="location"/></td> <td><xsl:value-of select="height/@value"/> <xsl:value-of select="height/@unit"/></td> <td><xsl:value-of select="type"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>

Here’s how to use this style sheet to transform the XML.

  1. Create a new Visual C++ Console Application (.NET) project named CppXsl.

  2. Add the following four lines to the top of CppXsl.cpp:

    #using <System.xml.dll> using namespace System::Xml; using namespace System::Xml::XPath; using namespace System::Xml::Xsl;

    The code for the XML classes lives in System.xml.dll, so it needs to be included via a #using directive. It’s easier to use the classes if you include using directives for the three XML namespaces, as shown in the preceding code.

  3. You’re going to supply the names of the XML document to transform and the style sheet to use when you run the program from the command line, so change the declaration of the _tmain function to include the command-line argument parameters, like this:

    int _tmain(int argc, char* argv[])
  4. Add the following code to the start of the _tmain function to check the number of arguments and save the paths to the XML document and the XSL style sheet:

    // Check for required arguments if (argc < 3) { Console::WriteLine(S"Usage: CppXsl xml-file stylesheet"); return -1; } String* path = new String(argv[1]); String* xslpath = new String(argv[2]);
  5. Now that you’ve got the paths, create an XmlDocument to parse the file and load it into a DOM tree.

    try { // Create the XmlDocument to parse the file XmlDocument* doc = new XmlDocument(); // Load the file doc->Load(path); Console::WriteLine(S"Document loaded"); } catch(Exception* pe) { Console::WriteLine(pe->Message); }

    As before, it’s a good idea to be prepared to catch exceptions when using XmlDocument because it will throw exceptions if it encounters any problems with opening or parsing the file.

  6. Now create an XPathNavigator that uses the XmlDocument, and position it at the root. Add the following code, and any code presented further in this exercise, to the end of the try block:

    // Create the navigator and position it XPathNavigator* nav = doc->CreateNavigator(); nav->MoveToRoot();
  7. Create an XslTransform object, and load the style sheet, as shown here:

    // Create the XslTransform and load it XslTransform* xslt = new XslTransform(); xslt->Load(xslpath);

    The Load function loads the style sheet, parsing it just like any other XML document. Always put calls to Load inside a try block to catch file loading and parsing errors.

    Note

    Load can also take its input from an XmlReader or an XPathNavigator.

  8. The output from this transformation is going to be HTML, so it would be useful to output it properly formatted. As you saw in the previous chapter, XmlTextWriter is used to output formatted XML, so you can create an XmlTextWriter to write output to the Console by using the following code:

    // Create a writer for output XmlTextWriter* xtw = new XmlTextWriter(Console::Out); xtw->Formatting = Formatting::Indented;
  9. Now you can perform the transformation, like this:

    // Do the transformation xslt->Transform(nav, 0, xtw);

    The first argument to Transform is the source of the XML, which in this case is an XPathNavigator. The second argument, which we’re not using, lets you pass data into the transform using an XslArgumentList object. The third argument specifies the destination for the output, which is the Console via the XmlTextWriter.

  10. Build and run the program from the command line, specifying the names of the XML and XSL files. You should see HTML output such as this:

    <html> <head> <title>Volcanoes</title> </head> <body> <h1>Volcanoes</h1> <table width="75%" border="1"> <tr> <th>Name</th> <th>Location</th> <th>Height</th> <th>Type</th> </tr> <tr> <td>Erebus</td> <td>Ross Island, Antarctica</td> <td>3794m</td> <td>stratovolcano</td> </tr> <tr> <td>Hekla</td> <td>Iceland</td> <td>1491m</td> <td>stratovolcano</td> </tr> <tr> <td>Mauna Loa</td> <td>Hawaii</td> <td>13677ft</td> <td>shield</td> </tr> </table> </body> </html> 

    The data has been extracted from the XML file and merged with HTML to create the output. The following figure shows how the output looks in a browser.

    click to expand




Microsoft Visual C++  .NET(c) Step by Step
Microsoft Visual C++ .NET(c) Step by Step
ISBN: 735615675
EAN: N/A
Year: 2003
Pages: 208

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