XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (572 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
12.8Mb size Format: txt, pdf, ePub

There is no way of finding out at runtime what the types of the arguments should be, which means that knowing a function is available is not enough to ensure that any given call on the function will be successful.

The functions that are considered to be available are those in the static context of the XPath expression containing the call on
function-available()
. If
function-available()
is evaluated from the
use-when
attribute, this includes core XPath and XSLT functions, constructor functions for built-in types, and extension functions. If
function-available()
is evaluated during stylesheet execution, it also includes stylesheet functions (defined using

) and constructor functions for types imported from a schema.

Usage

There are two ways of using
function-available()
: it can be used to achieve backward compatibility when using standard functions defined after version 1.0 of the specification, and it can be used to test for the presence of vendor or third-party extensions.

The ability to test for the existence of stylesheet functions is not particularly useful, especially as this cannot be done within a
use-when
attribute (it will always return false, because stylesheet functions are not present in the static context for evaluating
use-when
).

Testing for the Existence of System-Defined Functions

The ability to test whether a particular system-defined function is available was not especially useful with version 1.0 of the specification. It was designed to come into its own when later versions of the specification were published. If you want to use a function that is newly defined in version 2.0, then you can test to see whether it is available with a particular XSLT processor, before using it. If it is not available, you can use

to avoid executing it. Provided that you enable
forward-compatible mode
by setting the
version
attribute on the

element to
“2.0”
, a conformant XSLT 1.0 processor should not object to the presence of an expression in your stylesheet that calls an unknown function, unless the expression is actually executed.

For example, the function
current-date()
becomes available in XPath 2.0. You can test for its existence by writing:


For a fuller example, see the end of this section.

In theory, you could test whether a function such as
current-date()
is available by calling
system-property(‘xsl-version’)
and testing whether the result is equal to
2.0
. But the reality is that there will be processors that have implemented some of the XPath 2.0 functions but not yet all of them. A processor isn't supposed to return
2.0
as the value of
system-property(‘xsl:version’)
unless it is a fully conformant XSLT 2.0 processor; but if it isn't a fully conformant processor, then by definition you can't be sure whether it follows the rules. So it's better to use the finer-grained check offered by
function-available()
.

Testing for Vendor or Third-Party Extensions

The second way of using
function-available()
is to test for vendor or third-party extensions. If you know that a particular extension function is present in some implementations and not others, you can use the
function-available()
test to see whether it is present, and use the new
use-when
attribute to handle the situation when it isn't.

The
use-when
attribute provides a way of conditionally including or excluding parts of a stylesheet at compile time, based on a compile-time condition. There are more details of this feature on page 127 in Chapter 3. The compile-time condition is an XPath expression, restricted to operate with a very limited context, which means that it can only access information known at compile time. It cannot, for example, access a source document, or refer to variables. But the context does include the set of extension functions that are available. This is illustrated in the example that follows.

Example 1: Testing for xx:node-set() Extensions

The XSLT 2.0 working draft allows you to use a temporary tree (the value constructed when an

element is not empty) in any context where a node can be used. This feature was not available in XSLT 1.0, which handled temporary trees as a distinct type, known as a result tree fragment. Many vendors filled the gap by allowing a temporary tree to be converted to a node-set using an extension function (for example,
xt:node-set()
or
msxml:node-set()
). If you want to write a stylesheet that is as portable as possible, you need to write code that discovers which of these facilities is available.

Stylesheet

The following stylesheet (
node-set-available.xsl
) contains a named template that takes a temporary tree as a parameter and calls

to process its root node in a particular mode. When running with an XSLT 2.0 processor, it does this simply by passing the tree to

directly; in other cases, it tries to determine whether one of the proprietary
node-set()
extension functions is available, and uses that.

          xmlns:xsl=“http://www.w3.org/1999/XSL/Transform”

          version=“2.0”>

          xmlns:msxml=“urn:schemas-microsoft-com:xslt”

          xmlns:xt=“http://www.jclark.com/xt”

          xmlns:saxon6=“ http://icl.com/saxon”>

  

  

    

      

                           select=“$fragment”/>

    

    

      

        

          

                               select=“msxml:node-set($fragment)”/>

        

        

          

                               select=“xt:node-set($fragment)”/>

        

        

          

                               select=“saxon6:node-set($fragment)”/>

        

        

          

            Cannot convert result tree fragment to node-set

          

        

      

    

  



This named template can be called as follows, to process all the nodes in the result tree fragment.


   


The logic here is slightly tortuous. You need to look at it in two different ways: as an XSLT 1.0 stylesheet, and as a 2.0 stylesheet.

As a 1.0 stylesheet, the outer

takes the

branch, because the processor version is 1.0. The
use-when
attribute on the

element is ignored: the XSLT 1.0 processor will be operating in forward-compatible mode, because the stylesheet specifies
version=“2.0”
, and in forward-compatible mode, unknown attributes on XSLT elements are ignored. The 1.0 processor then takes one of the branches of the inner

, depending on which of the
xx:node-set()
extension functions is available.

As an XSLT 2.0 stylesheet, the outer

takes the

branch. It completely ignores the

branch, by virtue of the
use-when
condition. The
use-when
condition is necessary, because an XSLT 2.0 processor would otherwise report a static (compile time) error when it sees an XPath expression that calls an unknown function such as
saxon6:node-set()
, even though the function is not actually evaluated at runtime.

When this example is run with an XSLT 2.0 processor, it doesn't actually invoke the
function- available()
function—which arguably makes it a poor choice of example for this section. The next example attempts to remedy this.

Other books

Star Wars: Scourge by Jeff Grubb
Son of Thunder by Libby Bishop
My Favorite Mistake by Chelsea M. Cameron
And So To Murder by John Dickson Carr
Holman Christian Standard Bible by B&H Publishing Group
A Cold Christmas by Charlene Weir
The Ghost Road by Pat Barker