As you learned in Chapter 7, a variable can hold a special XSLT type called a result tree fragment. Such a fragment can hold XML nodes, but it isn't natively treated as a node-set. Nonetheless, with Xalan's node-set( ) function or Saxon's nodeset( ), you can cast a result tree fragment as a node-set and manipulate it as such. The following example will apply node-set( ) from Xalan (note, however, that many processors now provide the EXSLT version of this function for portability). Consider the document escapes.xml, which lists most of the string escapes offered by Python Version 2.3: <?xml version="1.0"?> <python version="2.3"> <escape purpose="bell">\a</escape> <escape purpose="backspace">\b</escape> <escape purpose="formfeed">\f</escape> <escape purpose="newline">\n</escape> <escape purpose="carriage return">\r</escape> <escape purpose="horizontal tab">\t</escape> <escape purpose="vertical tab">\v</escape> </python> There are a few escapes missing from this list. The stylesheet node-set.xsl supplies the missing nodes in a result tree fragment, as shown in Example 15-4. Example 15-4. Using the Xalan nodeset function to convert result tree fragments into node-sets<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xalan" exclude-result-prefixes="xalan"> <xsl:output method="xml" indent="yes"/> <xsl:variable name="frag"> <python> <description>Python 2.3 String Escapes</description> <escape purpose="ignore EOL">\</escape> <escape purpose="backslash">\\</escape> <escape purpose="octal value">\ddd</escape> <escape purpose="hexadecimal">\xXX</escape> <escape purpose="other">\other</escape> <escape purpose="single quote">\'</escape> <escape purpose="double quote">\"</escape> </python> </xsl:variable> <xsl:template match="python"> <xsl:copy> <xsl:copy-of select="xalan:nodeset($frag)/python/*"/> <xsl:apply-templates select="escape"/> </xsl:copy> </xsl:template> <xsl:template match="escape"> <xsl:copy-of select="."/> </xsl:template> </xsl:stylesheet> The Xalan namespace and prefix are set up for use on the stylesheet element. Following that is a variable definition that contains a result tree fragment. It contains the Python string escapes missing from escapes.xml. In the template matching python, the python element is copied into the result tree from the source tree, then copy-of uses xalan:node-set( ) in an expression to copy the result tree fragment with the node-set. Yes, copy-of could copy a result tree fragment into the result tree, but xalan:node-set( ) allows you to manipulate the fragment as a node-set. That's why it's possible to follow the function call with the XPath location steps /python/*, which grabs all the escape children in the fragment.
The second template copies all the escape nodes in the source tree into the result tree, joining them with nodes cast from frag. The following command: xalan -i 2 escapes.xml node-set.xsl gives you this combined output: <?xml version="1.0" encoding="UTF-8"?> <python> <description>Python 2.3 String Escapes</description> <escape purpose="ignore EOL">\</escape> <escape purpose="backslash">\\</escape> <escape purpose="octal value">\ddd</escape> <escape purpose="hexadecimal">\xXX</escape> <escape purpose="other">\other</escape> <escape purpose="single quote">\'</escape> <escape purpose="double quote">\"</escape> <escape purpose="bell">\a</escape> <escape purpose="backspace">\b</escape> <escape purpose="formfeed">\f</escape> <escape purpose="newline">\n</escape> <escape purpose="carriage return">\r</escape> <escape purpose="horizontal tab">\t</escape> <escape purpose="vertical tab">\v</escape> </python> That's an example of a Xalan function; now, I'll demonstrate an EXSLT function. |