
XSLT Extensions
by Bob DuCharme
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
By DougTidwell
Table of Contents
Index
Sample Chapter
Author's Article
Read Online--Safari
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:convertsxq610.xslintoxq611.txt-->
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://icl.com/saxon"
extension-element-prefixes="saxon"
version="1.0">
<xsl:outputmethod="xml"omit-xml-declaration="yes"/>
<xsl:variablename="color"
saxon:assignable="yes">red</xsl:variable>
<xsl:templatematch="/">
<saxon:assignname="color">blue</saxon:assign>
Thecolorvariablehasthefollowingvalue:
<xsl:value-ofselect="$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:
Thecolorvariablehasthefollowingvalue:
blue
When run with the Xalan Java processor, or any others besides
Saxon, the saxon:assign element has no effect:
Thecolorvariablehasthefollowingvalue:
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:convertsxq617.xsltoxq637.txt-->
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://icl.com/saxon"
extension-element-prefixes="saxon"
version="1.0">
<xsl:outputmethod="xml"omit-xml-declaration="yes"/>
<xsl:variablename="color"
saxon:assignable="yes">red</xsl:variable>
<xsl:templatematch="/">
<saxon:assignname="color">blue<xsl:fallback>
<xsl:message>ThisXSLTprocessordoesn'tsupportsaxon:assign.
</xsl:message></xsl:fallback></saxon:assign>
Thecolorvariablehasthefollowingvalue:
<xsl:value-ofselect="$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:
ThisXSLTprocessordoesn'tsupportsaxon:assign.
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:convertsxq619.xsl-->
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://icl.com/saxon"
extension-element-prefixes="saxon"
version="1.0">
<xsl:outputmethod="xml"omit-xml-declaration="yes"/>
<xsl:variablename="color"
saxon:assignable="yes">red</xsl:variable>
<xsl:templatematch="/">
<xsl:choose>
<xsl:whentest="element-available('saxon:assign')">
<saxon:assignname="color">blue</saxon:assign>
</xsl:when>
<xsl:otherwise>
<xsl:message>ThisXSLTprocessordoesn'tsupportsaxon:assign.
</xsl:message>
</xsl:otherwise>
</xsl:choose>
Thecolorvariablehasthefollowingvalue:
<xsl:value-ofselect="$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.
[1] [2] Next