XSLT 2.0 implementation

The context item, position, and size are now unset on entry to a stylesheet function. This means that if the function depends on the context item (or the document containing the context item), then an explicit parameter must be defined. For example, if the function defines <xsl:result select="count(//*)"/>, this must be changed to <xsl:result select="count($x//*)"/>, with $x being supplied as a parameter in the function call. If the function attempts to reference the context item, position, or size, a dynamic error is reported.

This change gives optimization benefits in all cases where functions are NOT dependent on the context.

The value attribute of <xsl:number> is now handled as described in the XSLT 2.0 specification: the value may be a sequence, and the items in the sequence are converted to integers using the casting rules. A recoverable error occurs if casting to an integer is not possible, or if the value is not positive. {numb07, numb20}

A side-effect of this change is that a user-written Numberer must be changed to handle a long argument rather than an int as previously.

The code for assignment of variables and parameters has been changed to use the argument conversion rules defined in XPath (without backwards compatibility mode). This is a weaker conversion than previously: essentially, the select expression must deliver a value of the correct type, it will not be converted to the required type except in the case where the supplied value is an untyped node. This means, for example, that if the required type is xs:integer, you can supply an attribute node, but you cannot supply a string or a double. If a cast to the required type is wanted, it must now be written explicitly in the select expression. The error will be reported statically if the expression could never yield a value of the right type, and will be reported dynamically otherwise.

In a pattern starting key('k', $x)/..., the variable $x can now be multi-valued; the pattern matches if it matches any of the values. {idky30}

The XSLT 1.0 rule that xsl:text elements may not contain child elements has been reinstated. This change anticipates changes to the XSLT 2.0 specification.

In limited circumstances, stylesheet functions (xsl:function) now optimise tail-recursion. The circumstances are that the select expression of the xsl:result instruction must contain a call on the same function in the then or else part of a conditional expression (which may be nested in further conditional expressions). It may require a little care to write functions to exploit this.

The attribute override=yes|no on xsl:function is implemented. This determines whether a user-written stylesheet function should override a vendor-supplied or user-written Java function. The default is "yes". {func19, func21}

This involved taking the function binding logic out of the ExpressionParser and putting it all in the static context. A simpler version of the routine is provided for StandaloneContext. The code has been structured so it can also test for arity (or even static type of arguments) as part of the binding algorithm, but this is not yet exploited.

A side-effect of this change is that it is now possible to call Saxon and EXSLT extension functions when using free-standing XPath expressions, that is, expressions executed using the XPath API from Java, or using saxon:evaluate(). It is also possible to call user-supplied Java extension functions provided the URI maps implicitly to a Java class name (i.e., not relying on saxon:script). {saxon36, 37}

Sorting using xsl:sort: I have changed the way data types are specified (in anticipation of changes to the W3C specification). The data-type attribute may now take values text or number only. The values text and number convert the actual sort key to xs:string or xs:double respectively before doing the comparison. If the data-type attribute is omitted there is no conversion. Values are then compared as supplied; if they are not comparable, a run-time error occurs. If you want to force conversion to a type such as xs:dateTime, use a casting function within the select expression, for example <xsl:sort select="xs:date(@birth-date)"/>. There is a small risk of backwards incompatibility if your stylesheet computes a numeric sort key and doesn't specify a data-type: previously it would have been sorted as a string, it will now be sorted as a number.

I added a check (really a bug fix for 7.3) that when an element is annotated with a simple type such as xs:integer, the element is not allowed to have attributes. The type annotation for an element with attributes must always be a complex type.