What happens if you use a stylesheet that has a Saxon extension element with another processor? It's hard to predict what might happen, except that it's likely you'll get an error stating that the extension element can't be found. You can prepare for this by specifying fallback behavior for extension elements in your stylesheet using the fallback and message elements together.
The output.xsl stylesheet shown in Example 15-8 uses the XSLT elements fallback and message to deal with the possibility of a processor other than Saxon encountering it. Example 15-8. A stylesheet using fallbacks<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon"> <xsl:output method="text" encoding="ISO-8859-1"/> <xsl:strip-space elements="*"/> <xsl:template match="python"> <!-- to result tree as text --> <xsl:text>Python 2.3 Keywords </xsl:text> <xsl:apply-templates select="keyword" mode="text"> <xsl:sort/> </xsl:apply-templates> <!-- save as HTML, too --> <saxon:output href="keywords.html" method="html" indent="yes" saxon:indent-spaces="1"> <xsl:fallback> <xsl:message terminate="yes">ERROR: saxon:output not available!</xsl:message> </xsl:fallback> <html> <body> <h3>Python 2.3 Keywords</h3> <ol> <xsl:apply-templates select="keyword" mode="html"> <xsl:sort/> </xsl:apply-templates> </ol> </body> </html> </saxon:output> </xsl:template> <xsl:template match="keyword" mode="html"> <li><xsl:value-of select="."/></li> </xsl:template> <xsl:template match="keyword" mode="text"> <xsl:value-of select="."/> <xsl:choose> <xsl:when test="not((position( ) mod 5)=0) and not(position( )=last( ))"> <xsl:text>	</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text> </xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Using the saxon:output element, this stylesheet produces two result trees: a normal result tree as text and an additional HTML result tree saved as a file in the current directory. The saxon:output element has many of the same attributes as XSLT's output element, such as method, indent, encoding, and so forth. Two important differences are:
In the initial template, the one that matches python, some title text is created for the result tree, then templates are applied for keyword elements in the text mode. In addition, the keyword elements are sorted. The template whose mode is text prints a keyword, followed by a tab (	) or a linefeed ( ), depending on the position of the word in the source tree. After that, the same template (the one matching python) uses saxon:output to write an HTML version of the result tree to the file keywords.html. It uses the saxon:indent-spaces attribute, and, yes, it is not allowed on saxon:output without a namespace prefix. It also employs ordinary HTML tags, sorts the keyword elements, and applies the mode html template to print list items (li).
The text result tree is printed on standard output, and the HTML result is written to a file. Perform the transformation by using: saxon keywords.xml output.xsl or using: java -jar saxon.jar keywords.xml output.xsl Here is the text output you will get: Python 2.3 Keywords and assert break class continue def del elif else except exec finally for from global if import in is lambda not or pass print raise return try while yield This is the HTML that is saved to keywords.html: <html> <body> <h3>Python 2.3 Keywords</h3> <ol> <li>and</li> <li>assert</li> <li>break</li> <li>class</li> <li>continue</li> <li>def</li> <li>del</li> <li>elif</li> <li>else</li> <li>except</li> <li>exec</li> <li>finally</li> <li>for</li> <li>from</li> <li>global</li> <li>if</li> <li>import</li> <li>in</li> <li>is</li> <li>lambda</li> <li>not</li> <li>or</li> <li>pass</li> <li>print</li> <li>raise</li> <li>return</li> <li>try</li> <li>while</li> <li>yield</li> </ol> </body> </html> 15.5.1 Invoking the Fallback BehaviorImmediately following saxon:output in output.xsl is the fallback element, followed by an instance of message. (This isn't the first time in this book that you've seen fallback and message working together.) A fallback element provides a fail-safe mechanism that will let you know when a processor can't accept an extension element. You must use fallback right after an extension element in order for it to work; it contains a template. A message element can be used in any template, not just in fallback. It generally prints a message to standard output, but not, however, to the result tree (this behavior where the message appears is undefined in the XSLT spec, however). It has a single required attribute, terminate, which lets you specify whether, once encountered, processing should stop. The value of terminate must be yes or no. You've run this stylesheet successfully with Saxon. Now you'll see what happens when you try it with another processor. Why not try MSXSL for a switch? msxsl keywords.xml output.xsl This command works only on Windows, by the way. MSXSL will give you this error report: Python 2.3 Keywords and assert break class continue def del elif else except exec finally for from global if import in is lambda not or pass print raise return try while yield Error occurred while executing stylesheet 'output.xsl'. Code: 0x80004005 ERROR: saxon:output not available! MSXSL performed the regular transformation, but when it encountered saxon:output, it hiccupped. If saxon:output were first in the top template, the MSXSL processor would just blurt out its error messages, including your custom message, then terminate. The error message that output.xsl produces, however, isn't all that different from the behavior you would get if you didn't include fallback. An interesting case would be to write an empty fallback element, which would silently ignore the error; then you just wouldn't get the second output file! You can try it by transforming keywords.xml with nofall.xsl in examples/ch15 (not shown here). |