page 133
Chapter 8. Extending XSLT
To this point, weve spent a lot of time learning how to use the built-in features of XSLT and XPath to get things done. Weve also talked about the somewhat unusual processing model
that makes life challenging for programmers from the world of procedural languages a.k.a. Earth. But what do you do if you still cant do everything with XSLT and XPath?
In this section, well discuss the XSLT extension mechanism that allows you to add new functions and elements to the language. Unfortunately, Version 1.0 of the XSLT standard
doesnt define all of the details about how these things should work, so there are some inconsistencies between processors. The good news is that if you write an extension function
or element that works with your favorite processor, another vendor cant do something sinister to prevent your functions or elements from working. On the other hand, if you decide
to change XSLT processors, youll probably have to change your code.
Most examples in this chapter are written for the Xalan processor. Well discuss how to write stylesheets that can work with multiple processors, and well briefly look at the differences
between the various APIs supported by those processors. In addition, Xalan comes with extensions written in Java, but you can use other languages, as well. Well look at extensions
written in Jython formerly JPython, JavaScript, and Jacl.
8.1 Extension Elements, Extension Functions, and Fallback Processing
Section 14 of the XSLT standard defines two kinds of extensions: extension elements and extension functions. Section 15 of the specification defines fallback processing, a way for
stylesheets to respond gracefully when extension elements and functions arent available. Well talk about these items briefly, then well move on to some examples that illustrate the
full range of extensions.
8.1.1 Extension Elements
An extension element is an element that should be processed by a piece of code external to the XSLT processor. In the case of the Java version of Xalan, our stylesheet defines the Java
class that should be loaded and invoked to process the extension element. Although the implementation details vary from one XSLT processor to the next, well discuss how an
extension element can access the XPath representation of our source document, how it can generate output, and how it can move through the XPath tree to manipulate the source
document.
8.1.1.1 Example: Generating multiple output files
The whole point of extensions is to allow you to add new capabilities to the XSLT processor. One of the most common needs is the ability to generate multiple output documents. As we
saw earlier, the
document
function allows you to have multiple input documents—but XSLT doesnt give us any way to create multiple output documents. Xalan, Saxon, and XT all
ship with extensions that allow you to create such documents. Heres an XML document that well use for several of our examples in this chapter:
?xml version=1.0? book
titleXSLTtitle chapter
titleGetting Startedtitle paraIf this chapter had any text, it would appear here.para
page 134 chapter
chapter titleThe Hello World Exampletitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleXPathtitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleStylesheet Basicstitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleBranching and Control Elementstitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleFunctionstitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleCreating Links and Cross-Referencestitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleSorting and Grouping Elementstitle
paraIf this chapter had any text, it would appear here.para chapter
chapter titleCombining XML Documentstitle
paraIf this chapter had any text, it would appear here.para chapter
book
For our first example, we want to create a stylesheet that converts the document to HTML, writing the contents of each
chapter
element to a separate HTML file. Heres what that stylesheet looks like:
?xml version=1.0? xsl:stylesheet version=1.0 xmlns:xsl=http:www.w3.org1999XSLTransform
xmlns:redirect=org.apache.xalan.xslt.extensions.Redirect extension-element-prefixes=redirect
xsl:output method=html xsl:template match=
xsl:choose xsl:when test=element-availableredirect:write
xsl:for-each select=bookchapter redirect:write select=concatchapter, position, .html
html head
titlexsl:value-of select=titletitle head
body h1xsl:value-of select=titleh1
xsl:apply-templates select=para xsl:if test=notposition=1
pa href=chapter{position-1}.htmlPreviousap xsl:if
xsl:if test=notposition=last pa href=chapter{position+1}.htmlNextap
xsl:if body
html redirect:write
xsl:for-each xsl:when