15.5 Fallback Behavior

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.

fallback works only with extension elements. You can test for the availability of extension elements with the XSLT function element-available( ). To test for extension functions, use function-available( ). These functions are demonstrated in Section 15.6, later in this chapter.


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&#10;&#10;</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>&#09;</xsl:text>  </xsl:when>  <xsl:otherwise>   <xsl:text>&#10;</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:

  1. saxon:output has a required attribute, href, whose value names the filename for the additional result tree. XSLT's output has no such attribute.

  2. saxon:output can contain a template, as you can see in output.xsl. XSLT's output is an empty element.

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 (&#09;) or a linefeed (&#10;), 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).

This functionality is provided in XSLT 2.0 in a rather different form using the new result-document instruction element. You'll learn about XSLT 2.0 and result-document in the next chapter.


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 Behavior

Immediately 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).



Learning XSLT
Learning XSLT
ISBN: 0596003277
EAN: 2147483647
Year: 2003
Pages: 164

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