XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

XSLT Extensions

XSLT Extensions

September 05, 2001

If the specialized elements of the XSLT namespace and the combined functions of XSLT and XPath aren't enough to perform the transformations you need, XSLT gives you ways to incorporate additional instruction elements and functions into your stylesheets. Most XSLT processors offer several extra extension elements and functions because it's a good way to distinguish themselves from the competition. This month we'll examine the use of extensions and some ways that a stylesheet can gracefully handle the possibility that the XSLT processor doesn't recognize an extension designed for use with another processor.

Extension Elements

There are three categories of elements that can be in an XSLT stylesheet:

  • Elements from the XSLT namespace that tell the processor how to transform the source tree into the result tree.

  • Literal result elements of any namespace you like that get added to the result tree just as they are shown in the stylesheet.

  • Extension elements: customized instruction elements that can be used along with the instructions from the XSLT namespace.

Warning Elements from the XSLT namespace fall into two categories: top-level elements, which are children of the xsl:stylesheet element with general instructions about handling the source document, and the children of the xsl:template elements known as instructions, which give specific instructions about nodes to add to the result tree. Extension elements cannot be top-level elements; they are always new instructions.

It's an important part of an XSLT processor's job to recognize all the elements in a stylesheet from the XSLT namespace and to carry out their instructions. If literal result elements can be from any namespace (see the earlier "Transforming XML" column Namespaces and XSLT Stylesheets for more on namespaces), letting you add elements from the HTML, XLink, or any other namespace to the result tree, how does a processor know which elements are extension elements? Because the stylesheet must explicitly list which namespaces are to be treated as extension element namespaces in the extension-element-prefixes attribute.

Related Reading

XSLT

XSLT
By Doug Tidwell

Let's look at an example. Some XSLT stylesheet authors are frustrated by XSLT's prohibition against changing the value of a variable during the execution of a stylesheet. Michael Kay added an assign extension element to his Saxon processor that lets you change a variable's value all you want. In the following stylesheet, the http://icl.com/saxon namespace (the one his processor expects to find for Saxon extension elements) is declared as a namespace with a prefix of "saxon", and this "saxon" namespace prefix is included in the value of the xsl:stylesheet element's extension-element-prefixes attribute. (The sample documents, stylesheets, and output shown in this column are available in this zip file.)

<!-- xq610.xsl: converts xq610.xsl into xq611.txt -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:saxon="http://icl.com/saxon"
     extension-element-prefixes="saxon"
     version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:variable name="color" 
       saxon:assignable="yes">red</xsl:variable>

  <xsl:template match="/">

    <saxon:assign name="color">blue</saxon:assign>

    The color variable has the following value:
    <xsl:value-of select="$color"/>
  </xsl:template>

</xsl:stylesheet>
Tip The extension-element-prefix attribute is usually included with the xsl:stylesheet element, but it can be added to any literal result element or extension element. If it's an attribute of an element other than the stylesheet's root xsl:stylesheet element, then it's only effective within the element where it's an attribute -- in other words, any extension elements from the specified namespace can only be used in that element or in one of its descendants. That's why it's more convenient to declare any extension namespaces in an extension-element-prefixes attribute of the xsl:stylesheet element; you can then use the extension elements anywhere you want in the document.

The preceding stylesheet, which you can run using any XML document as input, doesn't do much. First, it declares a variable named "color" and assigns it the value "red". Next, the single template rule in the stylesheet adds the phrase "The color variable has the following value:" to the result tree followed by the variable's value as put there by the xsl:value-of instruction. The special part comes inside that template rule just before this text gets added to the result tree: the saxon:assign extension element assigns the value "blue" to the "color" variable. (XSLT also allows extension attributes as well as extension elements, and the special Saxon attribute saxon:assignable is added to XSLT's xsl:variable element to let the saxon:assign element know that changing this variable's value is okay.) The output, when run with the Saxon processor, shows that the variable's value was successfully changed:


    The color variable has the following value:
    blue

When run with the Xalan Java processor, or any others besides Saxon, the saxon:assign element has no effect:


    The color variable has the following value:
    red

A lack of error messages might be considered a good thing, but in this case it's a bad thing: a stylesheet instruction failed to execute, so some sort of message about this failure would make for a more robust system. Fortunately, XSLT offers two ways to check whether an extension element will work or not: fallback and the element-available() function.

If an XSLT processor doesn't implement a particular extension element, it must look for an xsl:fallback child of that element and add its contents to the result tree. In the following revision of the stylesheet above, the xsl:fallback element has no contents to add to the result tree, but instead sends an xsl:message text string to wherever such strings go for the processor in question. (The xsl:message element sends a text message somewhere other than the result tree -- for example, to a command line window -- and is useful for debugging and status messages. Not all XSLT processors support it fully.)

<!-- xq617.xsl: converts xq617.xsl to xq637.txt  -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:saxon="http://icl.com/saxon"
     extension-element-prefixes="saxon"  
     version="1.0">
  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:variable name="color" 
       saxon:assignable="yes">red</xsl:variable>

  <xsl:template match="/">

    <saxon:assign name="color">blue<xsl:fallback>
        <xsl:message>This XSLT processor doesn't support saxon:assign.
        </xsl:message></xsl:fallback></saxon:assign>

    The color variable has the following value:
    <xsl:value-of select="$color"/>
  </xsl:template>

</xsl:stylesheet>

When run with the Saxon processor, this creates the same result as the earlier Saxon run. No xsl:message text appears at the command line because the saxon:assign element enclosing the xsl:fallback element executed successfully. When run with the Xalan Java parser, however, the stylesheet creates the same result as with the earlier Xalan run and sends the following message to the command line window:

This XSLT processor doesn't support saxon:assign. 
Comment on this article Do you use the extension functions of your preferred XSLT processor? Share your experience in our forum.
Post your comments

While the xsl:fallback element gives you a way to handle the failure of an extension element, the boolean element-available() function gives you a way to check whether the extension element is supported before even trying to execute it.

The following revision of the stylesheet above has an xsl:choose element that uses this function to test whether the saxon:assign element is supported. If so, the saxon:assign element inside the xsl:when element gets evaluated; if not, the message "This XSLT processor doesn't support saxon:assign" gets sent wherever that XSLT processor sends such messages.

<!-- xq619.xsl: converts xq619.xsl  -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:saxon="http://icl.com/saxon"
     extension-element-prefixes="saxon"  
     version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:variable name="color" 
       saxon:assignable="yes">red</xsl:variable>


  <xsl:template match="/">

    <xsl:choose>
      <xsl:when test="element-available('saxon:assign')">
        <saxon:assign name="color">blue</saxon:assign>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message>This XSLT processor doesn't support saxon:assign.
        </xsl:message>
      </xsl:otherwise>
    </xsl:choose>
    The color variable has the following value:
    <xsl:value-of select="$color"/>
  </xsl:template>

</xsl:stylesheet>

The results, when run with Saxon and then Xalan Java, are the same as with the previous version of the stylesheet: with Saxon, the result tells us that the color variable was successfully set to "blue", and no extra messages appear in the command prompt window; when run with Xalan Java, the result tells us that the color variable remains at the original setting of "red" and the xsl:message element sends the message about the lack of support for saxon:assign to the command prompt window.

Pages: 1, 2

Next Pagearrow