10 Callable Components

This section describes three constructs that can be used to provide subroutine-like functionality that can be invoked from anywhere in the stylesheet: named templates (see 10.1 Named Templates), named attribute sets (see 10.2 Named Attribute Sets), and stylesheet functions (see 10.3 Stylesheet Functions).

[Definition: The following constructs are classified as invocation constructs: the instructions xsl:call-template, xsl:apply-templates, xsl:apply-imports, and xsl:next-match; XPath function calls that bind to stylesheet functions; XPath dynamic function calls; the functions accumulator-before and accumulator-after; the [xsl:]use-attribute-sets attribute. These all have the characteristic that they can cause evaluation of constructs that are not lexically contained within the calling construct.]

10.1 Named Templates

<!-- Category: instruction -->
<xsl:call-template
  name = eqname >
  <!-- Content: xsl:with-param* -->
</xsl:call-template>

[Definition: Templates can be invoked by name. An xsl:template element with a name attribute defines a named template.] The value of the name attribute is an EQName, which is expanded as described in 5.1.1 Qualified Names. If an xsl:template element has a name attribute, it may, but need not, also have a match attribute. An xsl:call-template instruction invokes a template by name; it has a required name attribute that identifies the template to be invoked. Unlike xsl:apply-templates, the xsl:call-template instruction does not change the focus.

The match, mode and priority attributes on an xsl:template element have no effect when the template is invoked by an xsl:call-template instruction. Similarly, the name and visibility attributes on an xsl:template element have no effect when the template is invoked by an xsl:apply-templates instruction.

[ERR XTSE0650] It is a static error if a package contains an xsl:call-template instruction whose name attribute does not match the name attribute of any named template visible in the containing package (this includes any template defined in this package, as well as templates accepted from used packages whose visibility in this package is not hidden). For more details of the process of binding the called template, see 3.5.3.5 Binding References to Components.

[ERR XTSE0660] It is a static error if a package contains more than one non-hidden template with the same name and the same import precedence, unless it also contains a template with the same name and higher import precedence.

The target template for an xsl:call-template instruction is established using the binding rules described in 3.5.3.5 Binding References to Components. This will always be a template whose name attribute matches the name attribute of the xsl:call-template instruction. It may be a template defined in the same package that has higher import precedence than any other template with this name, or it may be a template accepted from a used package, or (if the template is not defined as private or final) it may be an overriding template in a package that uses the containing package. The result of evaluating an xsl:call-template instruction is the sequence produced by evaluating the sequence constructor contained in its target template (see 5.7 Sequence Constructors).

The template name xsl:initial-template is specially recognized in that it provides a default entry point for stylesheet execution (see 2.3 Initiating a Transformation.)

10.1.1 Declaring the Context Item for a Template

The xsl:context-item element is used as a child of xsl:template, to declare the required type of the context item. It is intended particularly for use when the containing template is called using an xsl:call-template instruction, but it also constrains the context item if the same template is invoked using xsl:apply-templates, xsl:apply-imports, or xsl:next-match.

<xsl:context-item
  as? = item-type
  use? = "required" | "optional" | "absent" />

If the as attribute is present then its value must be an ItemTypeXP30. If the attribute is omitted this is equivalent to specifying as="item()".

[ERR XTSE3088] It is a static error if the as attribute is present when use="absent" is specified.

A type error is signaled if the supplied context item does not match its required type. No attempt is made to convert the context item to the required type (using the function conversion rules or otherwise). The error code is the same as for xsl:param: [see ERR XTTE0590].

If an xsl:context-item element is present as the first child element of xsl:template, it defines whether the template requires a context item to be supplied, and if so, what the type of the context item must be. If this template is the initial named template, then this has the effect of placing constraints on the global context item for the transformation as a whole.

The use attribute of xsl:context-item takes the value required, optional, or absent. The default is optional.

If the containing xsl:template element has no name attribute then the only permitted value is required.

  • If the value required is specified, then there must be a context item. (This will automatically be the case if the template is invoked using xsl:apply-templates, xsl:apply-imports, or xsl:next-match, but not if it is invoked using xsl:call-template.)

  • If the value optional is specified, or if the attribute is omitted, or if the xsl:context-item element is omitted, then there may or may not be a context item when the template is invoked.

  • If the value absent is specified, then the contained sequence constructor, and any xsl:param elements, are evaluated with an absent focus.

    Note:

    It is not an error to call such a template with a non-absent focus; the context item is simply treated as absent. This option is useful when streaming, since an xsl:call-template instruction may become streamable if the referenced template is declared to make no use of the context item.

The processor may signal a type error statically if the required context item type is incompatible with the match pattern, that is, if no item that satisfies the match pattern can also satisfy the required context item type.

The xsl:context-item element plays no part in deciding whether and when the template rule is invoked in response to an xsl:apply-templates instruction.

[ERR XTTE3090] It is a type error if the xsl:context-item child of xsl:template specifies that a context item is required and none is supplied by the caller, that is, if the context item is absent at the point where xsl:call-template is evaluated.

10.1.2 Passing Parameters to Named Templates

Parameters are passed to named templates using the xsl:with-param element as a child of the xsl:call-template instruction.

[ERR XTSE0680] In the case of xsl:call-template, it is a static error to pass a non-tunnel parameter named x to a template that does not have a non-tunnel template parameter named x, unless the xsl:call-template instruction is processed with XSLT 1.0 behavior. This is not an error in the case of xsl:apply-templates, xsl:apply-imports, and xsl:next-match; in these cases the parameter is simply ignored.

The optional tunnel attribute may be used to indicate that a parameter is a tunnel parameter. The default is no. Tunnel parameters are described in 10.1.3 Tunnel Parameters.

Example: Calling a Named Template with a Parameter

This example defines a named template for a numbered-block with a parameter to control the format of the number.

<xsl:template name="numbered-block">
  <xsl:param name="format">1. </xsl:param>
  <fo:block>
    <xsl:number format="{$format}"/>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

<xsl:template match="ol//ol/li">
  <xsl:call-template name="numbered-block">
    <xsl:with-param name="format">a. </xsl:with-param>
  </xsl:call-template>
</xsl:template>

10.1.3 Tunnel Parameters

[Definition: A parameter passed to a template may be defined as a tunnel parameter. Tunnel parameters have the property that they are automatically passed on by the called template to any further templates that it calls, and so on recursively.] Tunnel parameters thus allow values to be set that are accessible during an entire phase of stylesheet processing, without the need for each template that is used during that phase to be aware of the parameter.

Note:

Tunnel parameters are conceptually similar to the dynamically scoped variables found in some functional programming languages (for example, early versions of LISP), where evaluating a variable reference involves searching down the dynamic call stack for a matching variable name. There are two main use cases for the feature:

  1. They provide a way to supply context information that might be needed by many templates (for example, the fact that the output is to be localized for a particular language), but which cannot be placed in a global variable because it might vary from one phase of processing to another. Passing such information using conventional parameters is error-prone, because a single xsl:apply-templates or xsl:call-template instruction that neglects to pass the information on will lead to failures that are difficult to diagnose.

  2. They are particularly useful when writing a customization layer for an existing stylesheet. For example, if you want to override a template rule that displays chemical formulae, you might want the new rule to be parameterized so you can apply the house-style of a particular scientific journal. Tunnel parameters allow you to pass this information to the overriding template rule without requiring modifications to all the intermediate template rules. Again, a global variable could be used, but only if the same house-style is to be used for all chemical formulae processed during a single transformation.

A tunnel parameter is created by using an xsl:with-param element that specifies tunnel="yes". A template that requires access to the value of a tunnel parameter must declare it using an xsl:param element that also specifies tunnel="yes".

On any template call using an xsl:apply-templates, xsl:call-template, xsl:apply-imports or xsl:next-match instruction, a set of tunnel parameters is passed from the calling template to the called template. This set consists of any parameters explicitly created using <xsl:with-param tunnel="yes">, overlaid on a base set of tunnel parameters. If the xsl:apply-templates, xsl:call-template, xsl:apply-imports or xsl:next-match instruction has an xsl:template declaration as an ancestor element in the stylesheet, then the base set consists of the tunnel parameters that were passed to that template; otherwise (for example, if the instruction is within a global variable declaration, an attribute set declaration, or a stylesheet function), the base set is empty. If a parameter created using <xsl:with-param tunnel="yes"> has the same expanded QName as a parameter in the base set, then the parameter created using xsl:with-param overrides the parameter in the base set; otherwise, the parameter created using xsl:with-param is added to the base set.

When a template accesses the value of a tunnel parameter by declaring it with <xsl:param tunnel="yes">, this does not remove the parameter from the base set of tunnel parameters that is passed on to any templates called by this template.

Two sibling xsl:with-param elements must have distinct parameter names, even if one is a tunnel parameter and the other is not. Equally, two sibling xsl:param elements representing template parameters must have distinct parameter names, even if one is a tunnel parameter and the other is not. However, the tunnel parameters that are implicitly passed in a template call may have names that duplicate the names of non-tunnel parameters that are explicitly passed on the same call.

Tunnel parameters are not passed in calls to stylesheet functions.

All other options of xsl:with-param and xsl:param are available with tunnel parameters just as with non-tunnel parameters. For example, parameters may be declared as mandatory or optional, a default value may be specified, and a required type may be specified. If any conversion is required from the supplied value of a tunnel parameter to the required type specified in xsl:param, then the converted value is used within the receiving template, but the value that is passed on in any further template calls is the original supplied value before conversion. Equally, any default value is local to the template: specifying a default value for a tunnel parameter does not change the set of tunnel parameters that is passed on in further template calls.

Tunnel parameters are passed unchanged through a built-in template rule (see 6.7 Built-in Template Rules).

If a tunnel parameter is declared in an xsl:param element with the attribute tunnel="yes", and if the parameter is explicitly or implicitly mandatory, then a dynamic error occurs [see ERR XTDE0700] if the set of tunnel parameters passed to the template does not include a parameter with a matching expanded QName.

Example: Using Tunnel Parameters

Suppose that the equations in a scientific paper are to be sequentially numbered, but that the format of the number depends on the context in which the equations appear. It is possible to reflect this using a rule of the form:

<xsl:template match="equation">
  <xsl:param name="equation-format" select="'(1)'" tunnel="yes"/>
  <xsl:number level="any" format="{$equation-format}"/>
</xsl:template>

At any level of processing above this level, it is possible to determine how the equations will be numbered, for example:

<xsl:template match="appendix">
  ...
  <xsl:apply-templates>
    <xsl:with-param name="equation-format" select="'[i]'" tunnel="yes"/>
  </xsl:apply-templates>
  ...
</xsl:template>

The parameter value is passed transparently through all the intermediate layers of template rules until it reaches the rule with match="equation". The effect is similar to using a global variable, except that the parameter can take different values during different phases of the transformation.

10.2 Named Attribute Sets

<!-- Category: declaration -->
<xsl:attribute-set
  name = eqname
  use-attribute-sets? = eqnames
  visibility? = "public" | "private" | "final" | "abstract"
  streamable? = boolean >
  <!-- Content: xsl:attribute* -->
</xsl:attribute-set>

Attribute sets generate named collections of attributes that can be used repeatedly on different constructed elements. The xsl:attribute-set declaration is used to declare attribute sets. The required name attribute specifies the name of the attribute set. The value of the name attribute is an EQName, which is expanded as described in 5.1.1 Qualified Names.

[Definition: An attribute set is defined as a set of xsl:attribute-set declarations in the same package that share the same expanded QName.]

The content of the xsl:attribute-set element consists of zero or more xsl:attribute instructions that are evaluated to produce the attributes in the set.

10.2.1 Using Attribute Sets

Attribute sets are used by specifying a use-attribute-sets attribute on the xsl:element or xsl:copy instruction, or by specifying an xsl:use-attribute-sets attribute on a literal result element. An attribute set may be defined in terms of other attribute sets by using the use-attribute-sets attribute on the xsl:attribute-set element itself. The value of the [xsl:]use-attribute-sets attribute is in each case a whitespace-separated list of names of attribute sets. Each name is specified as an EQName, which is expanded as described in 5.1.1 Qualified Names.

[ERR XTSE0710] It is a static error if the value of the use-attribute-sets attribute of an xsl:copy, xsl:element, or xsl:attribute-set element, or the xsl:use-attribute-sets attribute of a literal result element, is not a whitespace-separated sequence of EQNames, or if it contains an EQName that does not match the name attribute of any xsl:attribute-set declaration in the containing package.

An attribute set may be considered as comprising a sequence of instructions, each of which is either an xsl:attribute instruction or an attribute set invocation. Starting with the declarations making up an attribute set, this sequence of instructions can be generated by the following rules:

  1. The relevant attribute set declarations (that is, all declarations of attribute sets within a package sharing the same expanded QName) are considered in order: first in increasing order of import precedence, and within each precedence, in declaration order.

  2. Each declaration is expanded to a sequence of instructions as follows. First, one attribute set invocation is generated for each EQName present in the use-attribute-sets attribute, if present, retaining the order in which the EQNames appear. This is followed by the sequence of contained xsl:attribute instructions, in order.

    [Definition: An attribute set invocation is a pseudo-instruction corresponding to a single EQName appearing within an [xsl:]use-attribute-sets attribute; the effect of the pseudo-instruction is to cause the referenced attribute set to be evaluated.]

Similarly, an [xsl:]use-attribute-sets attribute of an xsl:copy, xsl:element, or xsl:attribute-set element, or of a literal result element, is expanded to a sequence of attribute set invocations, one for each EQName in order.

An attribute set is a named component, and the binding of QNames appearing in an attribute set invocation to attribute set components follows the rules in 3.5.3.5 Binding References to Components.

The following two (mutually recursive) rules define how an [xsl:]use-attribute-set attribute is expanded:

  1. An attribute set is evaluated by evaluating each of the contained attribute set invocations and xsl:attribute instructions in order, to deliver a sequence of attribute nodes.

  2. An attribute set invocation is evaluated by evaluating the attribute set to which it is bound, as determined by the rules in 3.5.3.5 Binding References to Components.

For rules regarding cycles in attribute set declarations, see 9.11 Circular Definitions.

Note:

The effect of an attribute set invocation on the dynamic context is the same as the effect of an xsl:call-template instruction. In particular, it does not change the focus. Although attribute sets are often defined with fixed values, or with values that depend only on global variables, it is possible to define an attribute set in such a way that the values of the constructed attributes are dependent on the context item.

Note:

In all cases the result of evaluating an attribute set is subsequently used to create the attributes of an element node, using the rules in 5.7.1 Constructing Complex Content. The effect of those rules is that when the result of evaluating the attribute set contains attributes with duplicate names, the last duplicate wins. The optimization rules allow a processor to avoid evaluating or validating an attribute if it is able to determine that the attribute will subsequently be discarded as a duplicate.

10.2.2 Visibility of Attribute Sets

The visibility attribute determines the potential visibility of the attribute set in packages other than the containing package. If the visibility attribute is present on any of the xsl:attribute-set declarations making up the definition of an attribute set (that is, all declarations within the same package sharing the same name), then it must be present, with the same value, on every xsl:attribute-set declaration making up the definition of that attribute set.

If the visibility attribute is present with the value abstract then there must be no xsl:attribute children and no use-attribute-sets attribute.

10.2.3 Streamability of Attribute Sets

An attribute set may be designated as streamable by including the attribute streamable="yes" on each xsl:attribute-set declaration making up the attribute set. If any xsl:attribute-set declaration for an attribute set has the attribute streamable="yes", then every xsl:attribute-set declaration for that attribute set must have the attribute streamable="yes".

An attribute set is guaranteed-streamable if all the following conditions are satisfied:

  1. Every xsl:attribute-set declaration for the attribute set has the attribute streamable="yes".

  2. Every xsl:attribute-set declaration for the attribute set is grounded and motionless according to the analysis in 19.8.6 Classifying Attribute Sets.

Specifying streamable="yes" on an xsl:attribute-set element declares an intent that the attribute set should be streamable, either because it is guaranteed-streamable, or because it takes advantage of streamability extensions offered by a particular processor. The consequences of declaring the attribute set to be streamable when it is not in fact guaranteed streamable depend on the conformance level of the processor, and are explained in 19.10 Streamability Guarantees.

[ERR XTSE0730] If an xsl:attribute set element specifies streamable="yes" then every attribute set referenced in its use-attribute-sets attribute (if present) must also specify streamable="yes".

Note:

It is common for attribute sets to create attributes with constant values, and such attribute sets will always be grounded and motionless and therefore streamable. Although such cases are fairly simple for a processor to detect, references to attribute sets are not guaranteed streamable unless the attribute set is declared with the attribute streamable="yes", which should therefore be used if interoperable streaming is required.

10.2.4 Evaluating Attribute Sets

Attribute sets are evaluated as follows:

  • The xsl:copy and xsl:element instructions have a use-attribute-sets attribute. The sequence of attribute nodes produced by evaluating this attribute is prepended to the sequence produced by evaluating the sequence constructor contained within the instruction.

  • Literal result elements allow an xsl:use-attribute-sets attribute, which is evaluated in the same way as the use-attribute-sets attribute of xsl:element and xsl:copy. The sequence of attribute nodes produced by evaluating this attribute is prepended to the sequence of attribute nodes produced by evaluating the attributes of the literal result element, which in turn is prepended to the sequence produced by evaluating the sequence constructor contained with the literal result element.

The xsl:attribute instructions are evaluated using the same focus as is used for evaluating the sequence constructor contained by the element that is the parent of the [xsl:]use-attribute-sets attribute forming the initial input to the algorithm. However, the static context for the evaluation depends on the position of the xsl:attribute instruction in the stylesheet: thus, only local variables declared within an xsl:attribute instruction, and global variables, are visible.

Note:

The above rule means that for an xsl:copy element with a select attribute, the focus for evaluating any referenced attribute sets is the node selected by the select attribute, rather than the context item of the xsl:copy instruction.

The set of attribute nodes produced by expanding xsl:use-attribute-sets may include several attributes with the same name. When the attributes are added to an element node, only the last of the duplicates will take effect.

The way in which each instruction uses the results of expanding the [xsl:]use-attribute-sets attribute is described in the specification for the relevant instruction: see 11.1 Literal Result Elements, 11.2 Creating Element Nodes Using xsl:element , and 11.9 Copying Nodes.

The result of evaluating an attribute set is a sequence of attribute nodes. Evaluating the same attribute set more than once can produce different results, because although an attribute set does not have parameters, it may contain expressions or instructions whose value depends on the evaluation context.

Each attribute node produced by expanding an attribute set has a type annotation determined by the rules for the xsl:attribute instruction that created the attribute node: see 11.3.1 Setting the Type Annotation for a Constructed Attribute Node. These type annotations may be preserved, stripped, or replaced as determined by the rules for the instruction that creates the element in which the attributes are used.

10.2.5 Attribute Sets: Examples

Example: A Simple Attribute Set

The following example creates a named attribute set title-style and uses it in a template rule.

<xsl:template match="chapter/heading">
  <fo:block font-stretch="condensed" xsl:use-attribute-sets="title-style">
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

<xsl:attribute-set name="title-style">
  <xsl:attribute name="font-size">12pt</xsl:attribute>
  <xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:attribute-set>

 

Example: Overriding Attributes in an Attribute Set

The following example creates a named attribute set base-style and uses it in a template rule with multiple specifications of the attributes:

font-family

is specified only in the attribute set

font-size

is specified in the attribute set, is specified on the literal result element, and in an xsl:attribute instruction

font-style

is specified in the attribute set, and on the literal result element

font-weight

is specified in the attribute set, and in an xsl:attribute instruction

Stylesheet fragment:

<xsl:attribute-set name="base-style">
  <xsl:attribute name="font-family">Univers</xsl:attribute>
  <xsl:attribute name="font-size">10pt</xsl:attribute>
  <xsl:attribute name="font-style">normal</xsl:attribute>
  <xsl:attribute name="font-weight">normal</xsl:attribute>
</xsl:attribute-set>

<xsl:template match="o">
  <fo:block xsl:use-attribute-sets="base-style"
            font-size="12pt"
            font-style="italic">
    <xsl:attribute name="font-size">14pt</xsl:attribute>
    <xsl:attribute name="font-weight">bold</xsl:attribute>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

Result:

<fo:block font-family="Univers"
          font-size="14pt"
          font-style="italic"
          font-weight="bold">
...
</fo:block>

10.3 Stylesheet Functions

[Definition: An xsl:function declaration declares the name, parameters, and implementation of a stylesheet function that can be called from any XPath expression within the stylesheet (subject to visibility rules).]

<!-- Category: declaration -->
<xsl:function
  name = eqname
  as? = sequence-type
  visibility? = "public" | "private" | "final" | "abstract"
  streamability? = "unclassified" | "absorbing" | "inspection" | "filter" | "shallow-descent" | "deep-descent" | "ascent" | eqname
  override-extension-function? = boolean
  [override]? = boolean
  new-each-time? = "yes" | "true" | "1" | "no" | "false" | "0" | "maybe"
  cache? = boolean >
  <!-- Content: (xsl:param*, sequence-constructor) -->
</xsl:function>

The xsl:function declaration defines a stylesheet function that can be called from any XPath expression used in the stylesheet (including an XPath expression used within a predicate in a pattern). The name attribute specifies the name of the function. The value of the name attribute is an EQName, which is expanded as described in 5.1.1 Qualified Names.

An xsl:function declaration can only appear as a top-level element in a stylesheet module.

The content of the xsl:function element consists of zero or more xsl:param elements that specify the formal arguments of the function, followed by a sequence constructor that defines the value to be returned by the function.

10.3.1 Function Name and Arity

The name of the function is given by the name attribute; the arguments are defined by child xsl:param elements; and the return type is defined by the as attribute. Together these definitions constitute the function signature.

[ERR XTSE0740] It is a static error if a stylesheet function has a name that is in no namespace.

Note:

To prevent the namespace declaration used for the function name appearing in the result document, use the exclude-result-prefixes attribute on the xsl:stylesheet element: see 11.1.3 Namespace Nodes for Literal Result Elements.

The name of the function must not be in a reserved namespace: [see ERR XTSE0080]

[Definition: The arity of a stylesheet function is the number of xsl:param elements in the function definition.] Optional arguments are not allowed.

Note:

Functions are not polymorphic. Although the XPath function call mechanism allows two functions to have the same name and different arity, it does not allow them to be distinguished by the types of their arguments.

10.3.2 Arguments

The xsl:param elements define the formal parameters to the function. These are interpreted positionally. When the function is called using a function call in an XPath expression, the first argument supplied is assigned to the first xsl:param element, the second argument supplied is assigned to the second xsl:param element, and so on.

Because arguments to a stylesheet function call must all be specified, the xsl:param elements within an xsl:function element must not specify a default value: this means they must be empty, and must not have a select attribute.

[ERR XTSE0760] It is a static error if an xsl:param child of an xsl:function element has either a select attribute or non-empty content.

The as attribute of the xsl:param element defines the required type of the parameter. The rules for converting the values of the actual arguments supplied in the function call to the types required by each xsl:param element, and the errors that can occur, are defined in [XPath 3.0]. The rules that apply are those for the case where XPath 1.0 compatibility mode is set to false.

If the as attribute is omitted, no conversion takes place and any value is accepted.

10.3.3 Function Result

The result of the function is the result of evaluating the contained sequence constructor.

Within the sequence constructor, the focus is initially absent; this means that any attempt to reference the context item, context position, or context size is a dynamic error. (See [ERR XPDY0002] XP30.)

It is not possible within the body of the stylesheet function to access the values of local variables that were in scope in the place where the function call was written. Global variables, however, remain available.

The optional as attribute indicates the required type of the result of the function. The value of the as attribute is a SequenceType.

[ERR XTTE0780] If the as attribute is specified, then the result evaluated by the sequence constructor (see 5.7 Sequence Constructors) is converted to the required type, using the function conversion rules. It is a type error if this conversion fails. If the as attribute is omitted, the calculated result is used as supplied, and no conversion takes place.

10.3.4 Visibility and Overriding of Functions

If the visibility attribute is present with the value abstract then the sequence constructor defining the function body must be empty.

The XPath specification states that the function that is executed as the result of a function call is identified by looking in the in-scope functions of the static context for a function whose name and arity matches the name and number of arguments in the function call. In XSLT 3.0, final determination of the function to be called cannot be made until all packages have been assembled: see 3.5.3.5 Binding References to Components.

An xsl:function declaration defines a stylesheet function which forms a component in its containing package, unless

  • there is another stylesheet function with the same name and arity, and higher import precedence, or

  • the override-extension-function or override attribute has the value no and there is already a function with the same name and arity in the in-scope functions.

The visibility of the function in other packages depends on the value of the visibility attribute and other factors, as described in 3.5 Packages.

The optional override-extension-function attribute defines what happens if this function has the same name and arity as a function provided by the implementer or made available in the static context using an implementation-defined mechanism. If the override-extension-function attribute has the value yes, then this function is used in preference; if it has the value no, then the other function is used in preference. The default value is yes.

Note:

Specifying override-extension-function="yes" ensures interoperable behavior: the same code will execute with all processors. Specifying override-extension-function="no" is useful when writing a fallback implementation of a function that is available with some processors but not others: it allows the vendor’s implementation of the function (or a user’s implementation written as an extension function) to be used in preference to the stylesheet implementation, which is useful when the extension function is more efficient.

The override-extension-function attribute does not affect the rules for deciding which of several stylesheet functions with the same name and arity takes precedence.

The override attribute is a deprecated synonym of override-extension-function, retained for compatibility with XSLT 2.0. If both attributes are present then they must have the same value.

[ERR XTSE0770] It is a static error for a package to contain two or more xsl:function declarations with the same expanded QName, the same arity, and the same import precedence, unless there is another xsl:function declaration with the same expanded QName and arity, and a higher import precedence.

When the xsl:function declaration appears as a child of xsl:override, there must be a stylesheet function with the same expanded QName and arity in the package referenced by the containing xsl:use-package element; the visibility of that function must be public or abstract, and the overriding and overridden functions must have the same argument types and result type.

10.3.5 Streamability of Stylesheet Functions

The streamability attribute of xsl:function is used to assign the function to one of a number of streamability categories. The various categories, and their effect on the streamability of function calls, are described in 19.8.5 Classifying Stylesheet Functions.

The streamability category of a function characterizes the way in which the function processes any streamed nodes supplied in the first argument to the function. (In general, streamed nodes cannot be supplied in other arguments, unless they are atomized by the function conversion rules.) The streamability attribute is therefore not applicable unless the function takes at least one argument.

[ERR XTSE3155] It is a static error if an xsl:function element with no xsl:param children has a streamability attribute with any value other than unclassified.

10.3.6 Dynamic Access to Functions

If a stylesheet function with a particular expanded QName and arity exists in the stylesheet, then a call to the function-lookupFO30 function supplying that name and arity will return the function as a value. This applies only if the static context for the call on function-lookupFO30 includes the stylesheet function, which implies that the function is visible in the containing package.

The function-available function, when called with a particular expanded QName and arity, returns true if and only if a call on function-lookupFO30 with the same arguments, in the same static context, would return a function item.

Note:

For legacy reasons there is also a single-argument version of function-available, which returns true if there is a function with the given name regardless of arity.

The standard rules for function-lookupFO30 require that if the supplied name and arity identify a context-dependent function such as name#0FO30 or lang#1FO30 (call it F), then the returned function value includes in its closure a copy of the static and dynamic context of the call to function-lookupFO30, and the context item for a subsequent dynamic call of F is taken from this saved context. In the case where the context item is a node in a streamed input document, saving the node is not possible. In this case, therefore, the context is saved with an absent focus, so the call on F will fail with a dynamic error saying that there is no context item available.

10.3.7 Determinism of Functions

Stylesheet functions have been designed to be largely deterministic: unless a stylesheet function calls some extension function which is itself nondeterministic, the function will return results that depend only on the supplied arguments. This property (coupled with the fact that the effect of calling extension functions is entirely implementation-dependent) enables a processor to implement various optimizations, such as removing invariant function calls from the body of a loop, or combining common subexpressions.

One exception to the intrinsic determinism of stylesheet functions arises because constructed nodes have distinct identity. This means that when a function that creates a new node is called, two calls on the function will return nodes that can be distinguished: for example, with such a function, f:make-node() is f:make-node() will return false.

Three classes of functions can be identified:

  1. DeterministicFO31 functions: as the term is defined in [Functions and Operators 3.1], these offer a guarantee that when a function is called repeatedly with the same arguments, it returns the same results. A classic example is the docFO30 function, which offers the guarantee that doc($X) is doc($X): that is, two calls supplying the same URI return the same node.

  2. Proactive functions: these offer the guarantee that each invocation of the function causes a single execution of the function body, or behaves exactly as if it did so. In particular this means that when the function creates new nodes, it creates new nodes on each invocation. By default, stylesheet functions are proactive.

  3. Elidable functions: these offer no guarantee of determinism, and no guarantee of proactive evaluation. If the function creates new nodes, then two calls on the function with the same arguments may or may not return the same nodes, at the implementation’s discretion. Examples of elidable functions include the [Functions and Operators 3.1] functions analyze-stringFO30 and json-to-xml.

The new-each-time attribute of xsl:function allows a stylesheet function to be assigned to one of these three categories. The value new-each-time="no" means the function is deterministic; the value new-each-time="yes" means it is proactive; and the value new-each-time="maybe" means it is elidable.

The definition of determinismFO31 requires a definition of what it means for a function to be called twice with “the same” arguments and to return “the same” result. This is defined in [Functions and Operators 3.1], specifically by the definition of the term identicalFO31.

Processors have considerable freedom to optimize execution of stylesheets, and of function calls in particular, but the strategies that are adopted must respect the specification as to whether functions are deterministic, proactive, or elidable. For example, consider a function call that appears within an xsl:for-each instruction, where the supplied arguments to the function do not depend on the context item or on any variables declared within the xsl:for-each instruction. A possible optimization is to execute the function call only once, rather than executing it repeatedly each time round the loop (this is sometimes called loop-lifting). This optimization is safe when the function is deterministic or elidable, but it requires great care if the function is proactive; it is permitted only if the processor is able to determine that the results of stylesheet execution are equivalent to the results that would be obtained if the optimization had not been performed. Declaring a function call to be elidable (by writing new-each-time="maybe") makes it more likely that an implementation will be able to apply this optimization, as well as other optimizations such as caching or memoization.

10.3.8 Memoization

The cache attribute is an optimization hint which the processor can use or ignore at its discretion; however it should be taken seriously, because it may make a difference to whether execution of a stylesheet is practically feasible or not.

The default value is cache="no".

The value cache="yes" encourages the processor to retain memory of previous calls of this function during the same transformation and to reuse results from this memory whenever possible. The default value cache="no" encourages the processor not to retain memory of previous calls.

In all cases the results must respect the semantics. If a function is proactive (new-each-time="yes") then caching of results may be infeasible, especially if the function result can include nodes; but it is not an error to request it, since some implementations may be able to provide caching, or analogous optimizations, even for proactive functions. (One possible strategy is to return a copy of the cached result, thus creating the illusion that the function has been evaluated anew.)

Note:

Memoization is essentially a trade-off between time and space; a memoized function can be expected to use more memory to deliver faster execution. Achieving an optimum balance may require configuring the size of the cache that is used; implementations may use additional extension attributes or other mechanisms to provide finer control of this kind.

Note:

Memoization of a function generally involves creating an associative table (for example, a hash map) that maps argument values to function results. To get this right, it is vital that the key for this table should correctly reflect what it means for two function calls to have “the same arguments”. Does it matter, for example, that one call passes the xs:string value "Paris", while another passes the xs:untypedAtomic value "Paris"? If the function is declared with new-each-time="maybe", then the rules say that these cannot be treated as “the same arguments”: the definition of identicalFO31 requires them to have exactly the same type as well as being equal. However, an implementation that is able to determine that all references to the argument within the function body only make use of its string value might be able to take advantage of this fact, and thus perform more efficient caching.

10.3.9 Examples of Stylesheet Functions

Example: A Stylesheet Function

The following example creates a recursive stylesheet function named str:reverse that reverses the words in a supplied sentence, and then invokes this function from within a template rule.

<xsl:transform 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:str="http://example.com/namespace"
  version="3.0"
  exclude-result-prefixes="str">

<xsl:function name="str:reverse" as="xs:string">
  <xsl:param name="sentence" as="xs:string"/>
  <xsl:sequence  
     select="if (contains($sentence, ' '))
             then concat(str:reverse(substring-after($sentence, ' ')),
                         ' ',
                         substring-before($sentence, ' '))
             else $sentence"/>
</xsl:function>

<xsl:template match="/">
  <output>
    <xsl:value-of select="str:reverse('DOG BITES MAN')"/>
  </output>
</xsl:template>

</xsl:transform>

An alternative way of writing the same function is to implement the conditional logic at the XSLT level, thus:

<xsl:function name="str:reverse" as="xs:string">
  <xsl:param name="sentence" as="xs:string"/>
  <xsl:choose>
    <xsl:when test="contains($sentence, ' ')">  
      <xsl:sequence 
           select="concat(str:reverse(substring-after($sentence, ' ')),
                                ' ',
                                substring-before($sentence, ' '))"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="$sentence"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

 

Example: Declaring the Return Type of a Function

The following example illustrates the use of the as attribute in a function definition. It returns a string containing the representation of its integer argument, expressed as a roman numeral. For example, the function call num:roman(7) will return the string "vii". This example uses the xsl:number instruction, described in 12 Numbering. The xsl:number instruction returns a text node, and the function conversion rules are invoked to convert this text node to the type declared in the xsl:function element, namely xs:string. So the text node is atomized to a string.

<xsl:function name="num:roman" as="xs:string">
  <xsl:param name="value" as="xs:integer"/>
  <xsl:number value="$value" format="i"/>
</xsl:function>

 

Example: A Higher-Order Function

XPath 3.0 introduces the ability to pass function items as arguments to a function. A function that takes function items as arguments is known as a higher-order function.

The following example is a higher-order function that operates on any tree-structured data, for example an organization chart. Given as input a function that finds the direct subordinates of a node in this tree structure (for example, the direct reports of a manager, or the geographical subdivisions of an administrative area), it determines whether one object is present in the subtree rooted at another object (for example, whether one person is among the staff managed directly or indirectly by a manager, or whether one parcel of land is contained directly or indirectly within another parcel). The function does not check for cycles in the data.

<xsl:function name="f:is-subordinate" as="xs:boolean">
    <xsl:param name="superior" 
               as="node()"/>
    <xsl:param name="subordinate" 
               as="node()"/>
    <xsl:param name="get-direct-children" 
               as="function(node()) as node()*"/>
    <xsl:sequence select="
               some $sub in $get-direct-children($superior) satisfies
                 ($sub is $subordinate or
                  f:is-subordinate($sub, $subordinate, 
                                      $get-direct-children))"/>
</xsl:function>

Given source data representing an organization chart in the form of elements such as:

<employee id="P57832" manager="P68951"/>

the following function can be defined to get the direct reports of a manager:

<xsl:function name="f:direct-reports" 
               as="element(employee)*">
    <xsl:param name="manager" as="element(employee)"/>
    <xsl:sequence select="$manager/../employee
                               [@manager = $manager/@id]"/>
</xsl:function>

It is then possible to test whether one employee $E reports directly or indirectly to another employee $M by means of the function call:

f:is-subordinate($M, $E, f:direct-reports#1)

10.4 Dynamic XPath Evaluation

<!-- Category: instruction -->
<xsl:evaluate
  xpath = expression
  as? = sequence-type
  base-uri? = { uri }
  with-params? = expression
  context-item? = expression
  namespace-context? = expression
  schema-aware? = { boolean } >
  <!-- Content: (xsl:with-param | xsl:fallback)* -->
</xsl:evaluate>

The xsl:evaluate instruction constructs an XPath expression in the form of a string, evaluates the expression in a specified context, and returns the result of the evaluation.

The expression given as the value of the xpath attribute is evaluated and the result is converted to a string using the function conversion rules.

[Definition: The string that results from evaluating the expression in the xpath attribute is referred to as the target expression.]

[ERR XTDE3160] It is a dynamic error if the target expression is not a valid expression (that is, if a static error occurs when analyzing the string according to the rules of the XPath specification).

The as attribute, if present, indicates the required type of the result. If the attribute is absent, the required type is item()*, which allows any result. The result of evaluating the target expression is converted to the required type using the function conversion rules. This may cause a type error if conversion is not possible. The result after conversion is returned as the result of the xsl:evaluate instruction.

The target expression may contain variable references; the values of such variables may be supplied using an xsl:with-param child instruction if the names of the variables are known statically, or using a map supplied as the value of the expression in the with-params attribute if the names are only known dynamically. If the with-params attribute is present then it must contain an expression whose value, when evaluated, is of type map(xs:QName, item()*) (see 21 Maps for details of maps).

[ERR XTTE3165] It is a type error if the result of evaluating the expression in the with-params attribute of the xsl:evaluate instruction is anything other than a single map of type map(xs:QName, item()*).

10.4.1 Static context for the target expression

The static contextXP30 for the target expression is as follows:

  • XPath 1.0 compatibility mode is false.

  • Statically known namespaces and default element/type namespace:

    • if the namespace-context attribute is present, then its value is an expression whose required type is a single node. The expression is evaluated, and the in-scope namespaces of the resulting node are used as the statically known namespaces for the target expression. The binding for the default namespace in the in-scope namespaces is used as the default namespace for elements and types in the target expression.

      [ERR XTTE3170] It is a type error if the result of evaluating the namespace-context attribute of the xsl:evaluate instruction is anything other than a single node.

    • if the namespace-context attribute is absent, then the in-scope namespaces of the xsl:evaluate instruction (with the exception of any binding for the default namespace) are used as the statically known namespaces for the target expression, and the value of the innermost [xsl:]xpath-default-namespace attribute, if any, is used as the default namespace for elements and types in the target expression.

    Note:

    XPath 3.0 allows expanded names to be written in a context-independent way using the syntax Q{namespace-uri}local-name

  • Default function namespace: the standard function namespace.

  • In-scope schema definitions: if the schema-aware attribute is present and has the effective value yes, then the in-scope schema definitions from the stylesheet context (that is, the schema definitions imported using xsl:import-schema). Otherwise, the built-in types (see 3.14 Built-in Types).

  • In-scope variables: the names of the in-scope variables are the union of the names appearing in the name attribute of the contained xsl:with-param elements, and the names present as keys in the map obtained by evaluating the with-params attribute, if present. The corresponding type is item()* in the case of a name found as a key in the with-params map, or the type named in the as attribute of xsl:with-param child (defaulting to item()*) otherwise.

    If a variable name is present both the static xsl:with-param children and also in the dynamic with-params map, the value from the latter takes precedence.

    Note:

    Variables declared in the stylesheet in xsl:variable or xsl:param elements are not in-scope within the target expression.

  • Function signatures:

    Note that this set deliberately excludes XSLT-defined functions in the standard function namespace including for example, key, current-group, and system-property. A list of these functions is in G.2 List of XSLT-defined functions.

  • Statically known collations: the same as the collations available at this point in the stylesheet.

  • Default collation: the same as the default collation defined at this point in the stylesheet (for example, by use of the [xsl:]default-collation attribute)

  • Base URI: if the base-uri attribute is present, then its effective value; otherwise, the base URI of the xsl:evaluate instruction.

  • Statically known documents: the empty set

  • Statically known collections: the empty set

  • Statically known default collection type: node()*

10.4.2 Dynamic context for the target expression

The dynamic context for evaluation of the target expression is as follows:

  • The context item, position, and size depend on the result of evaluating the expression in the context-item attribute. If this attribute is absent, or if the result is an empty sequence, then the context item, position, and size for evaluation of the target expression are all absent. If the result of evaluating the context-item expression is a single item, then the target expression is evaluated with a singleton focus based on this item.

    [ERR XTTE3210] If the result of evaluating the context-item expression is a sequence containing more than one item, then a type error is signaled.

  • The variable values consists of the values bound to parameters defined either in the contained xsl:with-param elements, which are evaluated as described in 9.3 Values of Variables and Parameters, or in the map that results from evaluation of the expression in the with-params attribute; if the same QName is bound in both, the value in the with-params map takes precedence.

  • The XSLT-specific aspects of the dynamic context described in 5.3.4 Additional Dynamic Context Components used by XSLT are all absent.

  • The named functionsXP30 (representing the functions accessible using function-available or function-lookupFO30) include all the functions available in the static context, and may also include an additional implementation-defined set of functions that are available dynamically but not statically.

  • All other aspects of the dynamic context are the same as the dynamic context for the xsl:evaluate instruction itself, except that an implementation may restrict the availability of external resources (for example, available documents) or provide options to restrict their availability, for security reasons.

    Note:

    For example, a processor may disallow access using the docFO30 or collectionFO30 functions to documents in local filestore.

10.4.3 The effect of the xsl:evaluate instruction

The XPath expression is evaluated in the same execution scopeFO30 as the calling XSLT transformation; this means that the results of deterministicFO30 functions such as docFO30 or current-dateTimeFO30 will be consistent between the calling stylesheet and the called XPath expression.

It is a dynamic error if evaluation of the XPath expression fails with a dynamic error. The XPath-defined error code is used unchanged.

Note:

Implementations wanting to avoid the cost of repeated compilation of the same XPath expression should cache the compiled form internally.

Stylesheet authors need to be aware of the security risks associated with the use of xsl:evaluate. The instruction should not be used to execute code from an untrusted source. To avoid the risk of code injection, user-supplied data should never be inserted into the expression using string concatenation, but should always be referenced by use of parameters.

10.4.4 xsl:evaluate as an optional feature

The xsl:evaluate instruction is newly introduced in XSLT 3.0. It is part of the dynamic evaluation feature, which is an optional feature of the specification (see 27.6 Dynamic Evaluation Feature). An XSLT 3.0 processor may disable the feature, or allow users to disable the feature. The processor may be able to determine during static analysis whether or not the feature is available, or it may only be able to determine this during dynamic evaluation. In the first case we refer to the feature being statically disabled, in the second case to it being dynamically disabled.

If the feature is statically disabled, then:

  • A call to element-available('xsl:evaluate') returns false, wherever it appears;

  • A call to system-property('xsl:supports-dynamic-evaluation') returns the string "no", wherever it appears;

  • If an xsl:evaluate instruction has an xsl:fallback child, fallback processing takes place;

  • No static error is raised if an xsl:evaluate instruction is present in the stylesheet (an error occurs only if it is actually evaluated).

If the feature is dynamically disabled, then:

  • A call to element-available('xsl:evaluate') appearing in a static expression (for example, in an [xsl:]use-when attribute) returns true;

  • A call to element-available('xsl:evaluate') appearing anywhere else returns false;

  • A call to system-property('xsl:supports-dynamic-evaluation') appearing in a static expression (for example, in an [xsl:]use-when attribute) returns the string "yes";

  • A call to system-property('xsl:supports-dynamic-evaluation') appearing anywhere else returns the string "no";

  • If an xsl:evaluate instruction has an xsl:fallback child, fallback processing takes place;

  • In the absence of an xsl:fallback child, a dynamic error is raised if an xsl:evaluate instruction is evaluated. The dynamic error may be caught using xsl:try and xsl:catch.

If a processor supports the dynamic evaluation feature, it is implementation-defined how the processor allows users to disable dynamic evaluation and it is implementation-defined whether the mechanism is static or dynamic.

[ERR XTDE3175] It is a dynamic error if an xsl:evaluate instruction is evaluated when use of xsl:evaluate has been statically or dynamically disabled.

In consequence of these rules, the recommended approach for stylesheet authors to write code that works whether or not xsl:evaluate is enabled is to use an xsl:fallback child instruction. For example:

<xsl:variable name="isValid" as="xs:boolean">
  <xsl:evaluate xpath="$validityCondition">
     <xsl:fallback><xsl:sequence select="true()"/></xsl:fallback>
  </xsl:evaluate>
</xsl:variable>

Note:

There may be circumstances where it is inappropriate to allow use of xsl:evaluate. For example:

  • There may be security risks associated with the ability to execute code from an untrusted source, which cannot be inspected during static analysis.

  • There may be environments where the available computing resources are sufficient to enable pre-compiled stylesheets to be executed, but not to enable XPath expressions to be compiled into executable code.

Processors that implement xsl:evaluate should provide mechanisms allowing calls on xsl:evaluate to be disabled. Implementations may disable the feature by default, and they may disable it unconditionally.

10.4.5 Examples of xsl:evaluate

Example: Using a Dynamic Sort Key

A common requirement is to sort a table on the value of an expression which is selected at run-time, perhaps by supplying the expression as a string-valued parameter to the stylesheet. Suppose that such an expression is supplied to the parameter:

<xsl:param name="sortkey" as="xs:string" select="'@name'"/>

Then the data may be sorted as follows:

<xsl:sort>
   <xsl:evaluate xpath="$sortkey" as="xs:string" context-item="."/>
</xsl:sort>

Note the importance in this use case of caching the compiled expression, since it is evaluated repeatedly, once for each item in the list being sorted.

 

Example: Getting a Function if it Exists

If the function-lookupFO30 function were not available in the standard library, then a very similar function could be implemented like this:

<xsl:function name="f:function-lookup">
  <xsl:param name="name" as="xs:QName"/>
  <xsl:param name="arity" as="xs:integer"/>
  <xsl:try>
    <xsl:evaluate xpath="'Q{' || namespace-uri-from-QName($name) || '}' 
                || local-name-from-QName($name) || '#' || $arity">
      <xsl:with-param name="name" as="xs:QName" select="$name"/>
      <xsl:with-param name="arity" as="xs:integer" select="$arity"/>
    </xsl:evaluate>
    <xsl:catch errors="err:XTDE3160" select="()"/>
  </xsl:try>  
</xsl:function>  
     

Note:

The main difference between this function and the standard function-lookupFO30 function is that there are differences in the functions that are visible: for example function-lookupFO30 gives access to user-defined functions with private visibility, whereas xsl:evaluate does not.

The xsl:evaluate instruction uses the supplied QName and arity to construct an expression of the form Q{namespace-uri}local#arity, which is then evaluated to return a function item representing the requested function.