Trying to explain how XSLT works is often very complicated because those used to traditional programming languages (C++, Java, or Visual Basic) find that XSLT executes oddly. I think the best way to explain XSLT is to have you debug a simple Hello World example. Instead of trying to figure out some weird matching node process, you see XSLT in action.
In a nutshell, XSLT is the process of combining an XML document with an XSLT (Extensible Stylesheet Language Transformation) document to produce a new document. The XSLT document is a specially coded XML document that transforms XML content into other XML or text-based content. Listing 6-1 shows you the XSLT process in action.
Listing 6-1: Original XML Document
<?xml version="1.0" encoding="UTF-8"?> <data> <elements>Hello</elements> <elements>World</elements> </data>
On the CD You can find all example files referenced in this chapter on the CD-ROM that accompanies this book at C:\Program Files\Altova\XMLSPY\ Examples\xmlspyhandbook\Ch6-7.
This XML document includes two elements: Hello and World. The contents Hello and World form the basis of the generated output of the Hello World example. The following listing shows the XSLT code used to process the XML:
<?xml version=”1.0” encoding=”UTF-8”?> <xsl:stylesheet version=”1.0” xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” xmlns:fo=”http://www.w3.org/1999/XSL/Format”> </xsl:stylesheet>
The preceding XSLT example contains no actions, just the base XML tag stylesheet. Notice, however, that the namespaces xsl and fo are defined. The xsl namespace references the XSLT specification created in 1999. The fo namespace references the XSL formatting objects specification. XSL formatting objects make it possible to lay out output exactly, similar to the PDF format from Adobe. XSL formatting objects, however, are beyond the scope of this book.
XMLSPY 5 includes a debugger. But before you begin the debugging process, here is something you need to understand. If you edited the preceding two documents in the order in which they are presented here, the last document that has the focus within the XMLSPY IDE is the XSL sheet. In this situation, if you start the debugger by choosing XSL → Start Debugger/Go, a dialog box asks for the sample XML file that you want to debug. If, from within the XMLSPY IDE, you edited the XML document last and then started the XMLSPY debugger, a dialog box asks for the sample XSL file that you want to debug. In either case, you can select the other document and click the OK button to begin debugging.
If you used XMLSPY to edit the documents shown in the preceding examples, you most likely have both documents loaded. In that case, you can click the Window button in the Please Choose Sample dialog box to select one of the already loaded documents.
After the selected document has been loaded, XMLSPY switches into debug mode and reassembles to look like Figure 6-1.
Figure 6-1: XMLSPY IDE layout after the XSLT debugger has been started.
Depending on the speed of your computer, you will likely see a few flashes and window activity. Your application has just been debugged and content generated. The output has been sent to the XSL Output.html window shown in Figure 6-1. Notice that in the window containing the output, the Hello World text is generated without any spaces between the words Hello and World.
What is interesting about this example is that output has been generated even though no action was specified in the XSLT stylesheet. The output is a default action from a default template that is invoked with every XSLT processor. In other XSLT processors and XSLT debuggers, the default template is not shown, just assumed. In XMLSPY, however, you can show the default template by stepping through the XSLT debugging process.
To invoke the XSLT debugging process, choose XSL → Step-Into. The XMLSPY IDE changes to resemble Figure 6-2.
When repeatedly debugging or stepping into the XSLT sheet, you can skip the process of associating the XML or XSL document because the Find dialog box remembers the last debugging session. Consequently, you only have to click OK in the Find dialog box.
As you go through the debugging process, you should notice a window activation flicker and then see a new window, Built In Templates, in the center of the XMLSPY window. The file Built In Templates is an optional default XSLT file that handles any situation not handled in your XSLT document. In your live session, the XML xsl:template tag is highlighted, and the debugger is starting to debug the first node of the XML document. That first node is the highlighted node, and it has matched the specific XML node within the Built In Templates XML document. If you press F11 continuously, the highlighted sections change windows and skip between the XML nodes shown in the XML and XSL documents.
Please note that the term XML node and XML tag are used interchangeably at times. The difference is that an XML node can be any type of XML structure, whereas an XML tag is a type of XML node.
When an XSLT document executes on an XML document and the XSLT does not select a specific node in the document, a default handler in the XSLT default template takes over. In the preceding debugging example, this was the file Built In Templates. The rules within the default template handler are just other XSLT statements. The default template within the XMLSPY IDE is shown in the following listing:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="*|/" mode="?"> <xsl:apply-templates mode="?"/> </xsl:template> <xsl:template match="text()|@*" mode="?"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="processing-instruction()|comment()"/> <xsl:template match="processing-instruction()|comment()" mode="?"/> </xsl:stylesheet>
When the debugger started, the first element selected was the xsl:template match=”*|/” XML node. This node is selected first because of the match attribute. The match attribute is a regular expression that specifies the rule to select the current XML node within the XML document.
The best way to understand the XSLT logic is to consider the XSLT processor as a running rule engine that, in a serial manner, selects each node in the XML document and attempts to match that node to an XSLT node.
In the original XML document shown in Listing 6-1, the first XML node selected is the data XML tag, which is kept as a selected reference in the XSLT processor. Going through the originally created XSLT document, there will be no match. But in the default template there is the match as defined in the regular expression of the backward slash, which is the root node match. After the XSLT processor has found a match in the XSLT document, the XSLT processor executes the contained XML nodes. In the case of the default template, this is the xsl:apply-templates XML node. The effect of xsl:apply-templates is that the XSL processor will process all the immediate children of the selected XML node in the XML document. What makes this selection special is the mode attribute. For the moment, you can ignore this. Notice that the selected XSLT node executes no specific subaction on its own.
As the XSLT processor iterates through the various XML nodes in the XML document, it attempts to match the XML node to the XSLT document. The text Hello and World are XML text nodes, and the XSLT XML node that is the associated match is xsl:template match=”text()|@*”. The result of the matched XSLT node is to output the value of the XML text node using the xsl:value-of XML node.