My personal preference when moving forward to a new software version or language version is to take the pain of the conversion all at once, and try to make the program or stylesheet look as if it had been written for the new version from the word go. Most of the changes listed above are to reflect the fact that XSLT 2.0 and XPath 2.0 no longer use the “first node” rule when a sequence is supplied in a context where a singleton is needed. You can always get the effect of selecting the first item in the sequence, by using the predicate
[1]
. For example, if an XSLT 1.0 stylesheet contains the instruction:
then it should be changed to:
But doing the conversion all at once is a luxury that you can't always afford. Backward-compatibility mode is there to allow you to spread the cost of making the changes by doing it gradually.
Extensibility
Bitten by years of experience with proprietary vendor extensions to HTML, the W3 C committee responsible for XSLT took great care to allow vendor extensions in a tightly controlled way.
The extensibility mechanisms in XSLT are governed by several unstated design principles:
- Namespaces are used to ensure that vendor extensions cannot clash with facilities in the standard (including facilities introduced in future versions), or with extensions defined by a different vendor.
- It is possible for an XSLT processor to recognize where extensions have been used, including extensions defined by a different vendor, and to fail cleanly if it cannot implement those extensions.
- It is possible for the writer of a stylesheet to test whether particular extensions are available, and to define fallback behavior if they are not. For example, the stylesheet might be able to achieve the same effect in a different way, or it might make do without some special effect in the output.
The principal extension mechanisms are extension functions and extension instructions. However, it is also possible for vendors to define other kinds of extensions, or to provide mechanisms for users or third parties to do so. These include the following:
- XSLT-defined elements can have additional vendor-defined attributes, provided they use a non-null namespace URI, and that they do not introduce nonconformant behavior for standard elements and attributes. For example, a vendor could add an attribute such as
acme:debug
to the
element, whose effect is to pause execution when the template is evaluated. But adding an attribute
acme:repeat = “2”
whose effect is to execute the template twice would be against the conformance rules.
- Vendors can define additional top-level elements; again provided that they use a non-null namespace URI, and that they do not cause nonconformant behavior for standard elements and attributes. An example of such an element is Microsoft's
element, for defining external functions in VBScript or JScript. Any processor that doesn't recognize the namespace URI will ignore such top-level elements.
- Certain XSLT-defined attributes have an open-ended set of values, where vendors have discretion on the range of values to be supported. Examples are the
lang
attribute of
and
, which provides language-dependent numbering and sorting; the
method
attribute of
, which defines how the result tree is output to a file; and the
format
attribute of
, which allows the vendor to provide additional numbering sequences beyond those defined in the standard. The list of system properties supplied in the first argument of the
system-property()
function is similarly open-ended.
Extension Functions
Extension functions provide a mechanism for extending the capabilities of XSLT by escaping into another language such as Java or JavaScript. The most usual reasons for doing this are as follows:
- To improve performance
- To exploit system capabilities and services
- To reuse code that already exists in another language
- For convenience, as complex algorithms and computations can sometimes be verbose when written in XSLT
XSLT 2.0 allows functions to be written using the
declaration in a stylesheet (these are referred to as stylesheet functions, and they are not considered to be extension functions). This facility, together with the increase in the size of the core function library, greatly reduces the need to escape into other programming languages. However, it is still necessary if you need access to external resources or services from within the stylesheet.
The term
extension function
is used both for functions supplied by the vendor beyond the core functions defined in the XSLT and XPath standards (those described in Chapter 13 of this book), and also for functions written by users and third parties.
The XSLT Recommendation allows extension functions to be called, but does not define how they are written, or how they should be bound to the stylesheet, or which languages should be supported. This means that it is quite difficult to write extension functions that work with more than one vendor's XSLT processor, even though in the Java world there are some conventions that several vendors have adopted.
In December 2000 the XSL Working Group in W3 C published a working draft for XSLT 1.1, which proposed detailed conventions for writing extension functions in Java and JavaScript. These proposals met a rather hostile reception, for a variety of reasons. The working draft was subsequently withdrawn, and the work hasn't been taken forward. It is still available, if you are interested, at
http://www.w3.org/TR/xslt11
.
A function name in the XPath expression syntax is a
QName
, that is, a name with an optional namespace prefix. Under XSLT, the default namespace for functions (the namespace that is assumed when the function name has no prefix) is always the namespace for the core function library. This function library includes the a repertoire of over a hundred functions defined in the XPath 2.0 specifications, together with another twenty or so that are available only for use in XSLT. These are all described in Chapter 13 of this book. For example the core function
not()
can be invoked as follows:
If the function name has a prefix, the function can come from a number of other sources, depending on its namespace:
- Functions in the XML Schema namespace
http://www.w3.org/2001/XMLSchema
(traditionally associated with the prefix
xs
, though
xsd
is also used) are used to construct values of built-in types. For example, the function call
xs:date(‘2004-02-29’)
is used to convert a string to an
xs:date
value. You can also use such functions to construct values of user-defined types in an imported schema. These are referred to as constructor functions.
- XSLT vendors will often provide additional functions in their own namespace. For example, Saxon provides a number of functions in the namespace
http://saxon.sf.net/
. An example is
saxon:evaluate()
, which allows an XPath expression to be constructed dynamically from a string, and then executed.
- Third parties may also define function libraries. Of particular note is the EXSLT library at
http://www.exslt.org/
. This provides, among other things, a useful library of mathematical functions. (It also provides capabilities such as date and time handling, and regular expression processing, that have largely been overtaken by standard facilities in XSLT 2.0 and XPath 2.0.) This is primarily a library of function specifications, but implementations of the functions are available for many popular XSLT processors, either from the XSLT vendor or from some other party. This ensures that you can use these functions in a stylesheet and still retain portability across XSLT processors. Note, however, that implementations of these functions are not generally portable: an implementation of
math:sqrt()
that's written for MSXML3 won't work with Xalan, for example.
- You can write your own functions in XSLT, using the
declaration. These will be completely portable across XSLT 2.0 implementations, but, of course, they are restricted to things that can be coded in XSLT and XPath. These functions can be in any namespace apart from a small number of reserved namespaces. The namespaces that are reserved are the obvious ones such as the XSLT, XML, and XML Schema namespaces.
- The
element has an attribute
override
that can be set to
yes
or
no
to indicate whether the stylesheet function should override any vendor-defined function of the same name. This is useful because there might be a portable cross-platform implementation of a function such as
math:sqrt()
specified in a third-party library such as EXSLT, as well as a native implementation provided by the XSLT vendor. This attribute allows you to choose which implementation is preferred.
- Finally, if the XSLT processor allows it, you may be able to write functions in an external programming language. Microsoft's XSLT processors, for example, allow you to invoke functions in scripting languages such as JavaScript, and all the Java-based processors such as Xalan-J and Saxon allow you to invoke methods written in Java. Saxon also allows you to call functions written in XQuery, and when used on the .NET platform it allows access to methods defined in any loadable .NET assembly, regardless of the source language. Other processors will tend to support the native language of the processor: Xalan-C++ allows you to write extension functions in C++ (you need to be aware that installing these is lot more complex than in the case of Java), while the 4XSLT processor (
http://4suite.org
) focuses on Python, and Gestalt (
http://sf.net/projects/gestalt
) on Eiffel.