6 Template Rules

Template rules define the processing that can be applied to items that match a particular pattern.

6.1 Defining Templates

<!-- Category: declaration -->
<xsl:template
  match? = pattern
  name? = eqname
  priority? = decimal
  mode? = tokens
  as? = sequence-type
  visibility? = "public" | "private" | "final" | "abstract" >
  <!-- Content: (xsl:context-item?, xsl:param*, sequence-constructor) -->
</xsl:template>

[Definition: An xsl:template declaration defines a template, which contains a sequence constructor; this sequence constructor is evaluated to determine the result of the template. A template can serve either as a template rule, invoked by matching items against a pattern, or as a named template, invoked explicitly by name. It is also possible for the same template to serve in both capacities.]

[ERR XTSE0500] An xsl:template element must have either a match attribute or a name attribute, or both. An xsl:template element that has no match attribute must have no mode attribute and no priority attribute. An xsl:template element that has no name attribute must have no visibility attribute.

If an xsl:template element has a match attribute, then it is a template rule. If it has a name attribute, then it is a named template.

A template may be invoked in a number of ways, depending on whether it is a template rule, a named template, or both. The result of invoking the template is the result of evaluating the sequence constructor contained in the xsl:template element (see 5.7 Sequence Constructors).

For details of the optional xsl:context-item child element, see 10.1.1 Declaring the Context Item for a Template.

If an as attribute of the xsl:template element is present, the as attribute defines the required type of the result. The result of evaluating the sequence constructor is then converted to the required type using the function conversion rules. If no as attribute is specified, the default value is item()*, which permits any value. No conversion then takes place.

[ERR XTTE0505] It is a type error if the result of evaluating the sequence constructor cannot be converted to the required type.

If the visibility attribute is present with the value abstract then (a) the sequence constructor defining the template body must be empty: that is, the only permitted children are xsl:context-item and xsl:param, and (b) there must be no match attribute.

If the parent of the xsl:template element is an xsl:override element, then either or both of the following conditions must be true:

  1. There is a name attribute, and the package identified by the containing xsl:use-package element contains among its components a named template whose symbolic identifier is the same as that of this named template, and which has a compatible signature.

  2. Both the following conditions are true:

    1. There is a match attribute.

    2. The value of the mode attribute, or in its absence the string #default, is a whitespace-separated sequence of tokens in which each token satisfies one of the following conditions:

      1. The token is an EQName representing the name of a mode that is exposed, with visibility equal to public, by the package identified by the containing xsl:use-package element.

      2. The token is #default, and there is an ancestor-or-self element with a default-mode attribute whose value is an EQName representing the name of a mode that is exposed, with visibility equal to public, by the package identified by the containing xsl:use-package element.

    Note:

    The token #unnamed is not allowed because the unnamed mode never has public visibility. The token #all is not allowed because its intended meaning would not be obvious.

6.2 Defining Template Rules

This section describes template rules. Named templates are described in 10.1 Named Templates.

A template rule is specified using the xsl:template element with a match attribute. The match attribute is a Pattern that identifies the items to which the rule applies. The result of applying the template rule is the result of evaluating the sequence constructor contained in the xsl:template element, with the matching item used as the context item.

Example: A Simple Template Rule

For example, an XML document might contain:

This is an <emph>important</emph> point.

The following template rule matches emph elements and produces a fo:wrapper element with a font-weight property of bold.

<xsl:template match="emph">
  <fo:wrapper font-weight="bold" 
              xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:apply-templates/>
  </fo:wrapper>
</xsl:template>

A template rule is evaluated when an xsl:apply-templates instruction selects an item that matches the pattern specified in the match attribute. The xsl:apply-templates instruction is described in the next section. If several template rules match a selected item, only one of them is evaluated, as described in 6.4 Conflict Resolution for Template Rules.

6.3 Applying Template Rules

<!-- Category: instruction -->
<xsl:apply-templates
  select? = expression
  mode? = token >
  <!-- Content: (xsl:sort | xsl:with-param)* -->
</xsl:apply-templates>

The xsl:apply-templates instruction takes as input a sequence of items (typically nodes in a source tree), and produces as output a sequence of items; these will often be nodes to be added to a result tree.

If the instruction has one or more xsl:sort children, then the input sequence is sorted as described in 13 Sorting. The result of this sort is referred to below as the sorted sequence; if there are no xsl:sort elements, then the sorted sequence is the same as the input sequence.

Each item in the input sequence is processed by finding a template rule whose pattern matches that item. If there is more than one such template rule, the best among them is chosen, using rules described in 6.4 Conflict Resolution for Template Rules. If there is no template rule whose pattern matches the item, a built-in template rule is used (see 6.7 Built-in Template Rules). The chosen template rule is evaluated. The rule that matches the Nth item in the sorted sequence is evaluated with that item as the context item, with N as the context position, and with the length of the sorted sequence as the context size. Each template rule that is evaluated produces a sequence of items as its result. The resulting sequences (one for each item in the sorted sequence) are then concatenated, to form a single sequence. They are concatenated retaining the order of the items in the sorted sequence. The final concatenated sequence forms the result of the xsl:apply-templates instruction.

Example: Applying Template Rules

Suppose the source document is as follows:

<message>Proceed <emph>at once</emph> to the exit!</message>

This can be processed using the two template rules shown below.

<xsl:template match="message">
  <p>
    <xsl:apply-templates select="child::node()"/>
  </p>
</xsl:template>

<xsl:template match="emph">
  <b>
    <xsl:apply-templates select="child::node()"/>
  </b>
</xsl:template>

There is no template rule for the document node; the built-in template rule for this node will cause the message element to be processed. The template rule for the message element causes a p element to be written to the result tree; the contents of this p element are constructed as the result of the xsl:apply-templates instruction. This instruction selects the three child nodes of the message element (a text node containing the value Proceed , an emph element node, and a text node containing the value to the exit!). The two text nodes are processed using the built-in template rule for text nodes, which returns a copy of the text node. The emph element is processed using the explicit template rule that specifies match="emph".

When the emph element is processed, this template rule constructs a b element. The contents of the b element are constructed by means of another xsl:apply-templates instruction, which in this case selects a single node (the text node containing the value at once). This is again processed using the built-in template rule for text nodes, which returns a copy of the text node.

The final result of the match="message" template rule thus consists of a p element node with three children: a text node containing the value Proceed , a b element that is the parent of a text node containing the value at once, and a text node containing the value to the exit!. This result tree might be serialized as:

<p>Proceed <b>at once</b> to the exit!</p>

The default value of the select attribute is child::node(), which causes all the children of the context node to be processed.

[ERR XTTE0510] It is a type error if an xsl:apply-templates instruction with no select attribute is evaluated when the context item is not a node.

A select attribute can be used to process items selected by an expression instead of processing all children. The value of the select attribute is an expression.

Example: Applying Templates to Selected Nodes

The following example processes all of the given-name children of the author elements that are children of author-group:

<xsl:template match="author-group">
  <fo:wrapper>
    <xsl:apply-templates select="author/given-name"/>
  </fo:wrapper>
</xsl:template>

 

Example: Applying Templates to Nodes that are not Descendants

It is also possible to process elements that are not descendants of the context node. This example assumes that a department element has group children and employee descendants. It finds an employee’s department and then processes the group children of the department.

<xsl:template match="employee">
  <fo:block>
    Employee <xsl:apply-templates select="name"/> belongs to group
    <xsl:apply-templates select="ancestor::department/group"/>
  </fo:block>
</xsl:template>

 

Example: Matching Nodes by Schema-Defined Types

It is possible to write template rules that are matched according to the schema-defined type of an element or attribute. The following example applies different formatting to the children of an element depending on their type:

<xsl:template match="product">
  <table>
    <xsl:apply-templates select="*"/>
  </table>
</xsl:template>

<xsl:template match="product/*" priority="3">
  <tr>
    <td><xsl:value-of select="name()"/></td>
    <td><xsl:next-match/></td>
  </tr>
</xsl:template>

<xsl:template match="product/element(*, xs:decimal) | 
                     product/element(*, xs:double)" priority="2">  
  <xsl:value-of select="format-number(xs:double(.), '#,###0.00')"/>
</xsl:template>

<xsl:template match="product/element(*, xs:date)" priority="2">
  <xsl:value-of select="format-date(., '[Mn] [D], [Y]')"/>
</xsl:template>

<xsl:template match="product/*" priority="1.5">
  <xsl:value-of select="."/>
</xsl:template>

The xsl:next-match instruction is described in 6.8 Overriding Template Rules.

 

Example: Re-ordering Elements in the Result Tree

Multiple xsl:apply-templates elements can be used within a single template to do simple reordering. The following example creates two HTML tables. The first table is filled with domestic sales while the second table is filled with foreign sales.

<xsl:template match="product">
  <table>
    <xsl:apply-templates select="sales/domestic"/>
  </table>
  <table>
    <xsl:apply-templates select="sales/foreign"/>
  </table>
</xsl:template>

 

Example: Processing Recursive Structures

It is possible for there to be two matching descendants where one is a descendant of the other. This case is not treated specially: both descendants will be processed as usual.

For example, given a source document

<doc><div><div></div></div></doc>

the rule

<xsl:template match="doc">
  <xsl:apply-templates select=".//div"/>
</xsl:template>

will process both the outer div and inner div elements.

This means that if the template rule for the div element processes its own children, then these grandchildren will be processed more than once, which is probably not what is required. The solution is to process one level at a time in a recursive descent, by using select="div" in place of select=".//div"

 

Example: Applying Templates to Atomic Values

This example reads a non-XML text file and processes it line-by-line, applying different template rules based on the content of each line:

<xsl:template name="main">
  <xsl:apply-templates select="unparsed-text-lines('input.txt')"/>
</xsl:template>

<xsl:template match=".[starts-with(., '==')]">
  <h2><xsl:value-of select="replace(., '==', '')"/></h2>
</xsl:template>

<xsl:template match=".[starts-with(., '::')]">
  <p class="indent"><xsl:value-of select="replace(., '::', '')"/></p>
</xsl:template>

<xsl:template match=".">
  <p class="body"><xsl:value-of select="."/></p>
</xsl:template>

Note:

The xsl:apply-templates instruction is most commonly used to process nodes that are descendants of the context node. Such use of xsl:apply-templates cannot result in non-terminating processing loops. However, when xsl:apply-templates is used to process elements that are not descendants of the context node, the possibility arises of non-terminating loops. For example,

<xsl:template match="foo">
  <xsl:apply-templates select="."/>
</xsl:template>

Implementations may be able to detect such loops in some cases, but the possibility exists that a stylesheet may enter a non-terminating loop that an implementation is unable to detect. This may present a denial of service security risk.

6.4 Conflict Resolution for Template Rules

It is possible for a selected item to match more than one template rule with a given mode M. When this happens, only one template rule is evaluated for the item. The template rule to be used is determined as follows:

  1. First, only the matching template rule or rules with the highest import precedence are considered. Other matching template rules with lower precedence are eliminated from consideration.

  2. Next, of the remaining matching rules, only those with the highest priority are considered. Other matching template rules with lower priority are eliminated from consideration.

    [Definition: The priority of a template rule is specified by the priority attribute on the xsl:template declaration. If no priority is specified explicitly for a template rule, its default priority is used, as defined in 6.5 Default Priority for Template Rules.]

    [ERR XTSE0530] The value of the priority attribute must conform to the rules for the xs:decimal type defined in [XML Schema Part 2]. Negative values are permitted.

  3. If this leaves more than one matching template rule, then:

    1. If the mode M has an xsl:mode declaration, and the attribute value on-multiple-match="fail" is specified in the mode declaration, a dynamic error is signaled. The error is treated as occurring in the xsl:apply-templates instruction, and can be recovered by wrapping that instruction in an xsl:try instruction.

      [ERR XTDE0540] It is a dynamic error if the conflict resolution algorithm for template rules leaves more than one matching template rule when the declaration of the relevant mode has an on-multiple-match attribute with the value fail.

    2. Otherwise, of the matching template rules that remain, the one that occurs last in declaration order is used.

    Note:

    This was a recoverable error in XSLT 2.0, meaning that it was implementation-defined whether the error was signaled, or whether the ambiguity was resolved by taking the last matching rule in declaration order. In XSLT 3.0 this situation is not an error unless the attribute value on-multiple-match="fail" is specified in the mode declaration. It is also possible to request warnings when this condition arises, by means of the attribute warning-on-multiple-match="yes".

6.5 Default Priority for Template Rules

[Definition: If no priority attribute is specified on an xsl:template element, a default priority is computed, based on the syntax of the pattern supplied in the match attribute.] The rules are as follows.

  1. If the top-level pattern is a ParenthesizedExprP then the outer parentheses are effectively stripped; these rules are applied recursively to the UnionExprP contained in the ParenthesizedExprP.

  2. If the top-level pattern is a UnionExprP consisting of multiple alternatives separated by | or union, then the template rule is treated equivalently to a set of template rules, one for each alternative. These template rules are adjacent to each other in declaration order, and the declaration order within this set of template rules (which affects the result of xsl:next-match if the alternatives have the same default priority) is the order of alternatives in the UnionExprP.

    Note:

    The splitting of a template rule into multiple rules occurs only if there is no explicit priority attribute.

  3. If the top-level pattern is an IntersectExceptExprP containing two or more PathExprP operands separated by intersect or except operators, then the priority of the pattern is that of the first PathExprP.

  4. If the pattern is a PredicatePattern then its priority is 1 (one), unless the PredicateListXP30 is empty, in which case the priority is −1 (minus one).

  5. If the pattern is a PathExprP taking the form /, then the priority is −0.5 (minus 0.5).

  6. If the pattern is a PathExprP taking the form of an EQName optionally preceded by a ForwardAxisP or has the form processing-instruction( StringLiteralXP30 ) or processing-instruction( NCNameNames ) optionally preceded by a ForwardAxisP, then the priority is 0 (zero).

  7. If the pattern is a PathExprP taking the form of an ElementTestXP30 or AttributeTestXP30, optionally preceded by a ForwardAxisP, then the priority is as shown in the table below. In this table, the symbols E, A, and T represent an arbitrary element name, attribute name, and type name respectively, while the symbol * represents itself. The presence or absence of the symbol ? following a type name does not affect the priority.

    Default Priority of Patterns
    Format Priority Notes
    element() −0.5 (equivalent to *)
    element(*) −0.5 (equivalent to *)
    attribute() −0.5 (equivalent to @*)
    attribute(*) −0.5 (equivalent to @*)
    element(E) 0 (equivalent to E)
    element(*,T) 0 (matches by type only)
    attribute(A) 0 (equivalent to @A)
    attribute(*,T) 0 (matches by type only)
    element(E,T) 0.25 (matches by name and type)
    schema-element(E) 0.25 (matches by substitution group and type)
    attribute(A,T) 0.25 (matches by name and type)
    schema-attribute(A) 0.25 (matches by name and type)
  8. If the pattern is a PathExprP taking the form of a DocumentTestXP30, then if it includes no ElementTestXP30 or SchemaElementTestXP30 the priority is −0.5. If it does include an ElementTestXP30 or SchemaElementTestXP30, then the priority is the same as the priority of that ElementTestXP30 or SchemaElementTestXP30, computed according to the table above.

  9. If the pattern is a PathExprP taking the form of an NCNameNames:* or *:NCNameNames, optionally preceded by a ForwardAxisP, then the priority is −0.25.

  10. If the pattern is a PathExprP taking the form of any other NodeTestXP30, optionally preceded by a ForwardAxisP, then the priority is −0.5.

  11. In all other cases, the priority is +0.5.

Note:

In many cases this means that highly selective patterns have higher priority than less selective patterns. The most common kind of pattern (a pattern that tests for a node of a particular kind, with a particular expanded QName or a particular type) has priority 0. The next less specific kind of pattern (a pattern that tests for a node of a particular kind and an expanded QName with a particular namespace URI) has priority −0.25. Patterns less specific than this (patterns that just test for nodes of a given kind) have priority −0.5. Patterns that specify both the name and the required type have a priority of +0.25, putting them above patterns that only specify the name or the type. Patterns more specific than this, for example patterns that include predicates or that specify the ancestry of the required node, have priority 0.5.

However, it is not invariably true that a more selective pattern has higher priority than a less selective pattern. For example, the priority of the pattern node()[self::*] is higher than that of the pattern salary. Similarly, the patterns attribute(*, xs:decimal) and attribute(*, xs:short) have the same priority, despite the fact that the latter pattern matches a subset of the nodes matched by the former. Therefore, to achieve clarity in a stylesheet it is good practice to allocate explicit priorities.

6.6 Modes

[Definition:  A mode is a set of template rules; when the xsl:apply-templates instruction selects a set of items for processing, it identifies the rules to be used for processing those items by nominating a mode, explicitly or implicitly.] Modes allow a node in a source tree (for example) to be processed multiple times, each time producing a different result. They also allow different sets of template rules to be active when processing different trees, for example when processing documents loaded using the document function (see 20.1 fn:document).

Modes are identified by an expanded QName; in addition to any named modes, there is always one unnamed mode available. Whether a mode is named or unnamed, its properties may be defined in an xsl:mode declaration. If a mode name is used (for example in an xsl:template declaration or an xsl:apply-templates instruction) and no declaration of that mode appears in the stylesheet, the mode is implicitly declared with default properties.

6.6.1 Declaring Modes

<!-- Category: declaration -->
<xsl:mode
  name? = eqname
  streamable? = boolean
  use-accumulators? = tokens
  on-no-match? = "deep-copy" | "shallow-copy" | "deep-skip" | "shallow-skip" | "text-only-copy" | "fail"
  on-multiple-match? = "use-last" | "fail"
  warning-on-no-match? = boolean
  warning-on-multiple-match? = boolean
  typed? = boolean | "strict" | "lax" | "unspecified"
  visibility? = "public" | "private" | "final" />

[Definition: The unnamed mode is the default mode used when no mode attribute is specified on an xsl:apply-templates instruction or xsl:template declaration, unless a different default mode has been specified using the [xsl:]default-mode attribute of a containing element.]

Every mode other than the unnamed mode is identified by an expanded QName.

A stylesheet may contain multiple xsl:mode declarations and may include or import stylesheet modules that also contain xsl:mode declarations. The name of an xsl:mode declaration is the value of its name attribute, if any.

[Definition: All the xsl:mode declarations in a package that share the same name are grouped into a named mode definition; those that have no name are grouped into a single unnamed mode definition.]

The declared-modes attribute of the xsl:package element determines whether implicit mode declarations are allowed, as described in 3.5.4.1 Requiring Explicit Mode Declarations. If the package allows implicit mode declarations, then if a stylesheet does not contain a declaration of the unnamed mode, a declaration is implied equivalent to an xsl:mode element with no attributes. Similarly, if there is a mode that is named in an xsl:template or xsl:apply-templates element, or in the [xsl:]default-mode attribute of a containing element, and the stylesheet does not contain a declaration of that mode, then a declaration is implied comprising an xsl:mode element with a name attribute equal to that mode name, plus the attribute visibility="private".

The attributes of the xsl:mode declaration establish values for a number of properties of a mode. The allowed values and meanings of the attributes are given in the following table.

Attributes of the xsl:mode Element
Attribute Values Meaning
name An EQName Specifies the name of the mode. If omitted, this xsl:mode declaration provides properties of the unnamed mode
streamable yes or no (default no) Determines whether template rules in this mode are to be capable of being processed using streaming. If the value yes is specified, then the body of any template rule that uses this mode must conform to the rules for streamable templates given in 6.6.4 Streamable Templates.
use-accumulators List of accumulator names, or #all (default is an empty list) Relevant only when this mode is the initial mode of the transformation, determines which accumulators are applicable to documents containing nodes in the initial match selection. For further details see 18.2.2 Applicability of Accumulators.
on-no-match One of deep-copy, shallow-copy, deep-skip, shallow-skip, text-only-copy or fail (default text-only-copy) Determines selection of the built-in template rules that are used to process an item when an xsl:apply-templates instruction selects an item that does not match any user-written template rule in the stylesheet. For details, see 6.7 Built-in Template Rules.
on-multiple-match One of fail or use-last (default use-last) Defines the action to be taken when xsl:apply-templates is used in this mode and more than one user-written template rule is available to process an item, each having the same import precedence and priority. The value fail indicates that it is a dynamic error if more than one template rule matches an item. The value use-last indicates that the situation is not to be treated as an error (the last template in declaration order is the one that is used).
warning-on-no-match One of yes or no. The default is implementation-defined Requests the processor to output (or not to output) a warning message in the case where an xsl:apply-templates instruction selects an item that matches no user-written template rule. The form and destination of such warnings is implementation-defined. The processor may ignore this attribute, for example if the environment provides no suitable means of communicating with the user.
warning-on-multiple-match One of yes or no. The default is implementation-defined Requests the processor to output a warning message in the case where an xsl:apply-templates instruction selects an item that matches multiple template rules having the same import precedence and priority. The form and destination of such warnings is implementation-defined. The processor may ignore this attribute, for example if the environment provides no suitable means of communicating with the user.
typed One of yes, no, strict, lax, or unspecified. The default is unspecified. See 6.6.3 Declaring the Type of Nodes Processed by a Mode.
visibility One of public, private, or final. The default is private. See 3.5.3.1 Visibility of Components. If the mode is unnamed, that is, if the name attribute is absent, then the visibility attribute if present must have the value private. A named mode is not eligible to be used as the initial mode if its visibility is private.

[Definition: A streamable mode is a mode that is declared in an xsl:mode declaration with the attribute streamable="yes".]

For any named mode, the effective value of each attribute is taken from an xsl:mode declaration that has a matching name in its name attribute, and that specifies an explicit value for the required attribute. If there is no such declaration, the default value of the attribute is used. If there is more than one such declaration, the one with highest import precedence is used.

For the unnamed mode, the effective value of each attribute is taken from an xsl:mode declaration that has no name attribute, and that specifies an explicit value for the required attribute. If there is no such declaration, the default value of the attribute is used. If there is more than one such declaration, the one with highest import precedence is used.

[ERR XTSE0545] It is a static error if for any named or unnamed mode, a package explicitly specifies two conflicting values for the same attribute in different xsl:mode declarations having the same import precedence, unless there is another definition of the same attribute with higher import precedence. The attributes in question are the attributes other than name on the xsl:mode element.

6.6.2 Using Modes

[Definition: A template rule is applicable to one or more modes. The modes to which it is applicable are defined by the mode attribute of the xsl:template element. If the attribute is omitted, then the template rule is applicable to the default mode specified in the [xsl:]default-mode attribute of the innermost containing element that has such an attribute, which in turn defaults to the unnamed mode. If the mode attribute is present, then its value must be a non-empty whitespace-separated list of tokens, each of which defines a mode to which the template rule is applicable.]

Each token in the mode attribute must be one of the following:

  • an EQName, which is expanded as described in 5.1.1 Qualified Names to define the name of the mode

  • the token #default, to indicate that the template rule is applicable to the default mode that would apply if the mode attribute were absent

  • the token #unnamed, to indicate that the template rule is applicable to the unnamed mode

  • the token #all, to indicate that the template rule is applicable to all modes (specifically, to the unnamed mode and to every mode that is named explicitly or implicitly in an xsl:apply-templates instruction anywhere in the stylesheet).

When a template rule specifies mode="#all" this is interpreted as meaning all modes declared implicitly or explicitly within the declaring package of the xsl:template element. This value cannot be used in the case of a template rule declared within an xsl:override element.

[ERR XTSE0550] It is a static error if the list of modes is empty, if the same token is included more than once in the list, if the list contains an invalid token, or if the token #all appears together with any other value.

[ERR XTSE3440] In the case of a template rule (that is, an xsl:template element having a match attribute) appearing as a child of xsl:override, it is a static error if the list of modes in the mode attribute contains #all or #unnamed, or if it contains #default and the default mode is the unnamed mode, or if the mode attribute is omitted when the default mode is the unnamed mode.

The xsl:apply-templates element also has an optional mode attribute. The value of this attribute must be one of the following:

If the attribute is omitted, the default mode for the stylesheet module is used.

When searching for a template rule to process each item selected by the xsl:apply-templates instruction, only those template rules that are applicable to the selected mode are considered.

[Definition: At any point in the processing of a stylesheet, there is a current mode. When the transformation is initiated, the current mode is the initial mode, as described in 2.3 Initiating a Transformation. Whenever an xsl:apply-templates instruction is evaluated, the current mode becomes the mode selected by this instruction.] When a non-contextual function call is made, the current mode is set to the unnamed mode. While evaluating global variables and parameters, and the sequence constructor contained in xsl:key or xsl:sort, the current mode is set to the unnamed mode. No other instruction changes the current mode. The current mode while evaluating an attribute set is the same as the current mode of the caller. On completion of the xsl:apply-templates instruction, or on return from a stylesheet function call, the current mode reverts to its previous value. The current mode is used when an xsl:apply-templates instruction uses the syntax mode="#current"; it is also used by the xsl:apply-imports and xsl:next-match instructions (see 6.8 Overriding Template Rules).

6.6.3 Declaring the Type of Nodes Processed by a Mode

Typically the template rules in a particular mode will be designed to process a specific kind of input document. The typed attribute of xsl:mode gives the stylesheet author the opportunity to provide information about this document to the processor. This information may enable the processor to improve diagnostics or to optimize performance.

The typed attribute of xsl:mode informs the processor whether the nodes to be processed by template rules in this mode are to be typed or untyped.

  • If the value yes is specified (synonyms true or 1), then all nodes processed in this mode must be typed. A dynamic error occurs if xsl:apply-templates in this mode selects an element or attribute node whose type annotation is xs:untyped or xs:untypedAtomic.

  • If the value no is specified (synonyms false or 0), then all nodes processed in this mode must be untyped. A dynamic error occurs if xsl:apply-templates in this mode selects an element or attribute whose type annotation is anything other than xs:untyped or xs:untypedAtomic.

  • The value strict is equivalent to yes, with the additional provision that in the match pattern of any template rule that is applicable to this mode, any NameTest used in the ForwardStepP of the first StepExprP of a RelativePathExprP is interpreted as follows:

    • If the NameTest is an EQName E, and the principal node kind of the axis of this step is Element, then:

      • It is a static error if the in-scope schema declarations do not include a global element declaration for element name E

      • When matching templates in this mode, the element name E appearing in this step is interpreted as schema-element(E). (Informally, this means that it will only match an element if it has been validated against this element declaration).

    • Otherwise (the NameTest is a wildcard or the principal node kind is Attribute or Namespace), the template matching proceeds as if the typed attribute were absent.

  • The value lax is equivalent to yes, with the additional provision that in the match pattern of any template rule that is applicable to this mode, any NameTest used in the ForwardStepP of the first StepExprP of a RelativePathExprP is interpreted as follows:

    • If the NameTest is an EQName E, and the principal node kind of the axis of this step is Element, and the in-scope schema declarations include a global element declaration for element name E, then:

      • When matching templates in this mode, the element name E appearing in this step is interpreted as schema-element(E). (Informally, this means that it will only match an element if it has been validated against this element declaration).

    • Otherwise (the NameTest is a wildcard, or the principal node kind is Attribute or Namespace, or there is no element declaration for E), the template matching proceeds as if the typed attribute were absent.

[ERR XTTE3100] It is a type error if an xsl:apply-templates instruction in a particular mode selects an element or attribute whose type is xs:untyped or xs:untypedAtomic when the typed attribute of that mode specifies the value yes, strict, or lax.

[ERR XTSE3105] It is a static error if a template rule applicable to a mode that is defined with typed="strict" uses a match pattern that contains a RelativePathExprP whose first StepExprP is an AxisStepP whose ForwardStepP uses an axis whose principal node kind is Element and whose NodeTest is an EQName that does not correspond to the name of any global element declaration in the in-scope schema components.

[ERR XTTE3110] It is a type error if an xsl:apply-templates instruction in a particular mode selects an element or attribute whose type is anything other than xs:untyped or xs:untypedAtomic when the typed attribute of that mode specifies the value no.

6.6.4 Streamable Templates

A template rule that is applicable to a mode M is guaranteed-streamable if and only if all the following conditions are satisfied:

  1. Mode M is declared in an xsl:mode declaration that specifies streamable="yes".

  2. The pattern defined in the match attribute of the xsl:template element is a motionless pattern as defined in 19.8.10 Classifying Patterns.

  3. The sweep of the sequence constructor forming the body of the xsl:template element is either motionless or consuming.

  4. The type-adjusted posture of the sequence constructor forming the body of the xsl:template element, with respect to the U-type that corresponds to the declared return type of the template (defaulting to item()*), is grounded.

    Note:

    This means that either (a) the sequence constructor is grounded as written (that is, it does not return streamed nodes), or (b) it effectively becomes grounded because the declared result type of the template is atomic, leading to implicit atomization of the result.

  5. Every expression and contained sequence constructor in a contained xsl:param element (the construct that provides the default value of the parameter) is motionless.

Specifying streamable="yes" on an xsl:mode declaration declares an intent that every template rule that includes that mode (explicitly or implicitly, including by specifying #all), 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 mode to be streamable when there is such a template rule that is not guaranteed streamable depend on the conformance level of the processor, and are explained in 19.10 Streamability Guarantees.

Processing of a document using streamable templates may be initiated using code such as the following, where S is a mode declared with streamable="yes":

<xsl:source-document streamable="yes" href="bigdoc.xml">
  <xsl:apply-templates mode="S"/>
</xsl:source-document>

Alternatively, streamed processing may be initiated by invoking the transformation with an initial mode declared as streamable, while supplying the initial match selection (in an implementation-defined way) as a streamed document.

Note:

Invoking a streamable template using the construct <xsl:apply-templates select="doc('bigdoc.xml')"/> does not ensure streamed processing. As always, processors may use streamed processing if they are able to do so, but when the docFO30 or document functions are used, processors are obliged to ensure that the results are deterministic, which may be difficult to reconcile with streaming (if the same document is read twice, the results must be identical). The use of xsl:source-document with streamable="yes" does not offer the same guarantees of determinism.

For an example of processing a collection of documents by use of the function uri-collectionFO30 in conjunction with xsl:source-document, see 18.1.2 Examples of xsl:source-document.

6.7 Built-in Template Rules

When an item is selected by xsl:apply-templates and there is no user-specified template rule in the stylesheet that can be used to process that item, then a built-in template rule is evaluated instead.

The built-in template rules have lower import precedence than all other template rules. Thus, the stylesheet author can override a built-in template rule by including an explicit template rule.

There are six sets of built-in template rules available. The set that is chosen is a property of the mode selected by the xsl:apply-templates instruction. This property is set using the on-no-match attribute of the xsl:mode declaration, which takes one of the six values deep-copy, shallow-copy, deep-skip, shallow-skip, text-only-copy, or fail, the default being text-only-copy. The effect of these six sets of built-in template rules is explained in the following subsections.

6.7.1 Built-in Templates: Text-only Copy

The effect of processing a tree using a mode that specifies on-no-match="text-only-copy" is that the textual content of the source document is retained while losing the markup, except where explicit template rules dictate otherwise. When an element is encountered for which there is no explicit template rule, the processing continues with the children of that element. Text nodes are copied to the output.

The built-in rule for document nodes and element nodes is equivalent to calling xsl:apply-templates with no select attribute, and with the mode attribute set to #current. If the built-in rule was invoked with parameters, those parameters are passed on in the implicit xsl:apply-templates instruction.

This is equivalent to the following in the case where there are no parameters:

<xsl:template match="document-node()|element()" mode="M">
  <xsl:apply-templates mode="#current"/>
</xsl:template>

The built-in template rule for text and attribute nodes returns a text node containing the string value of the context node. It is effectively:

<xsl:template match="text()|@*" mode="M">
  <xsl:value-of select="string(.)"/>
</xsl:template>

Note:

This text node may have a string value that is zero-length.

The built-in template rule for atomic values returns a text node containing the value. It is effectively:

<xsl:template match=".[. instance of xs:anyAtomicType]" mode="M">
  <xsl:value-of select="string(.)"/>
</xsl:template>

Note:

This text node may have a string value that is zero-length.

The built-in template rule for processing instructions, comments, and namespace nodes does nothing (it returns the empty sequence).

<xsl:template 
   match="processing-instruction()|comment()|namespace-node()" 
   mode="M"/>

The built-in template rule for functions (including maps) does nothing (it returns the empty sequence).

<xsl:template 
   match=".[. instance of function(*)]" 
   mode="M"/>

The built-in template rule for arrays (see 27.7.1 Arrays) is to apply templates to the members of the array. It is equivalent to invoking xsl:apply-templates with the select attribute set to ?* (which selects the members of the array), and with the mode attribute set to #current. If the built-in rule was invoked with parameters, those parameters are passed on in the implicit xsl:apply-templates instruction.

This is equivalent to the following in the case where there are no parameters:

<xsl:template match=".[. instance of array(*)]" mode="M">
  <xsl:apply-templates mode="#current" select="?*"/>
</xsl:template>

The following example illustrates the use of built-in template rules when there are parameters.

Example: Using a Built-In Template Rule

Suppose the stylesheet contains the following instruction:

<xsl:apply-templates select="title" mode="M">
  <xsl:with-param name="init" select="10"/>
</xsl:apply-templates>

If there is no explicit template rule that matches the title element, then the following implicit rule is used:

<xsl:template match="title" mode="M">
  <xsl:param name="init"/>
  <xsl:apply-templates mode="#current">
    <xsl:with-param name="init" select="$init"/>
  </xsl:apply-templates>
</xsl:template>

6.7.2 Built-in Templates: Deep Copy

The effect of processing a tree using a mode that specifies on-no-match="deep-copy" is that an unmatched element in the source tree is copied unchanged to the output, together with its entire subtree. Other unmatched items are also copied unchanged. The subtree is copied unconditionally, without attempting to match nodes in the subtree against template rules.

When this default action is selected for a mode M, all items (nodes, atomic values, and functions, including maps and arrays) are processed using a template rule that is equivalent to the following:

<xsl:template match="." mode="M">
  <xsl:copy-of select="." validation="preserve"/>
</xsl:template>

6.7.3 Built-in Templates: Shallow Copy

The effect of processing a tree using a mode that specifies on-no-match="shallow-copy" is that the source tree is copied unchanged to the output, except for nodes where different processing is specified using an explicit template rule.

When this default action is selected for a mode M, all items (nodes, atomic values, and functions, including maps and arrays) are processed using a template rule that is equivalent to the following, except that all parameters supplied in xsl:with-param elements are passed on implicitly to the called templates:

<xsl:template match="." mode="M">
  <xsl:copy validation="preserve">
    <xsl:apply-templates select="@*" mode="M"/>
    <xsl:apply-templates select="node()" mode="M"/>
  </xsl:copy>
</xsl:template>

This rule is often referred to as the identity template, though it should be noted that it does not preserve node identity.

Note:

This rule differs from the traditional identity template rule by using two xsl:apply-templates instructions, one to process the attributes and one to process the children. The only observable difference from the traditional select="node() | @*" is that with two separate instructions, the value of position() in the called templates forms one sequence starting at 1 for the attributes, and a new sequence starting at 1 for the children.

Example: Modified Identity Transformation

The following stylesheet transforms an input document by deleting all elements named note, together with their attributes and descendants:

<xsl:stylesheet version="3.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
				  
<xsl:mode on-no-match="shallow-copy" streamable="true"/>

<xsl:template match="note">
  <!-- no action -->
</xsl:template>

</xsl:stylesheet>

6.7.4 Built-in Templates: Deep Skip

The effect of processing a tree using a mode that specifies on-no-match="deep-skip" is that where no explicit template rule is specified for an element, that element and all its descendants are ignored, and are not copied to the result tree.

The effect of choosing on-no-match="deep-skip" is as follows:

  • The built-in rule for document nodes is equivalent to calling xsl:apply-templates with no select attribute, and with the mode attribute set to #current. If the built-in rule was invoked with parameters, those parameters are passed on in the implicit xsl:apply-templates instruction.

    In the case where there are no parameters, this is equivalent to the following rule:

    <xsl:template match="document-node()" mode="M">
      <xsl:apply-templates mode="#current"/>
    </xsl:template>
  • The built-in rule for all items other than document nodes (that is, for all other kinds of node, as well as atomic values and functions, including maps and and arrays) is to do nothing, that is, to return an empty sequence (without applying templates to any children or ancestors).

    This is equivalent to the following rule:

    <xsl:template match="." mode="M"/>

6.7.5 Built-in Templates: Shallow Skip

The effect of processing a tree using a mode that specifies on-no-match="shallow-skip" is to drop both the textual content and the markup from the result document, except where there is an explicit user-written template rule that dictates otherwise.

The built-in rule for document nodes and element nodes applies templates (in the current mode) first to the node’s attributes and then to its children. If the built-in rule was invoked with parameters, those parameters are passed on in the implicit xsl:apply-templates instructions.

In the case where there are no parameters, this is equivalent to the following rule:

<xsl:template match="document-node()|element()" mode="M">
  <xsl:apply-templates select="@*" mode="#current"/>
  <xsl:apply-templates mode="#current"/>
</xsl:template>

The built-in template rule for all other kinds of node, and for atomic values and functions (including maps, but not arrays) is empty: that is, when the item is matched, the built-in template rule returns an empty sequence.

This is equivalent to the following rule:

<xsl:template match="." mode="M"/>

The built-in template rule for arrays (see 27.7.1 Arrays) is to apply templates to the members of the array. It is equivalent to invoking xsl:apply-templates with the select attribute set to ?* (which selects the members of the array), and with the mode attribute set to #current. If the built-in rule was invoked with parameters, those parameters are passed on in the implicit xsl:apply-templates instruction.

This is equivalent to the following in the case where there are no parameters:

<xsl:template match=".[. instance of array(*)]" mode="M">
  <xsl:apply-templates mode="#current" select="?*"/>
</xsl:template>

6.7.6 Built-in Templates: Fail

The effect of choosing on-no-match="fail" for a mode is that every item selected in an xsl:apply-templates instruction must be matched by an explicit user-written template rule.

The built-in template rule is effectively:

<xsl:template match="." mode="M">
  <xsl:message terminate="yes" error-code="err:XTDE0555"/>
</xsl:template>

with an implementation-dependent message body.

[ERR XTDE0555] It is a dynamic error if xsl:apply-templates, xsl:apply-imports or xsl:next-match is used to process a node using a mode whose declaration specifies on-no-match="fail" when there is no template rule in the stylesheet whose match pattern matches that node.

6.8 Overriding Template Rules

<!-- Category: instruction -->
<xsl:apply-imports>
  <!-- Content: xsl:with-param* -->
</xsl:apply-imports>

<!-- Category: instruction -->
<xsl:next-match>
  <!-- Content: (xsl:with-param | xsl:fallback)* -->
</xsl:next-match>

A template rule that is being used to override another template rule (see 6.4 Conflict Resolution for Template Rules) can use the xsl:apply-imports or xsl:next-match instruction to invoke the overridden template rule. The xsl:apply-imports instruction only considers template rules in imported stylesheet modules; the xsl:next-match instruction considers all other template rules of lower import precedence and/or priority, and also declarations of the same precedence and priority that appear earlier in declaration order. Both instructions will invoke the built-in template rule for the context item (see 6.7 Built-in Template Rules) if no other template rule is found.

[Definition: At any point in the processing of a stylesheet, there may be a current template rule. Whenever a template rule is chosen as a result of evaluating xsl:apply-templates, xsl:apply-imports, or xsl:next-match, the template rule becomes the current template rule for the evaluation of the rule’s sequence constructor.]

The current template rule is cleared (becomes absent) by any instruction that evaluates an operand with changed focus. It is therefore cleared when evaluating instructions contained within:

Note:

The current template rule is not affected by invoking named attribute sets (see 10.2 Named Attribute Sets), or named templates (see 10.1 Named Templates) unless <xsl:context-item use="absent"/> is specified. While evaluating a global variable or the default value of a stylesheet parameter (see 9.5 Global Variables and Parameters) the current template rule is absent.

These rules ensure that when xsl:apply-imports or xsl:next-match is called, the context item is the same as when the current template rule was invoked.

Both xsl:apply-imports and xsl:next-match search for a template rule that matches the context item, and that is applicable to the current mode (see 6.6 Modes). In choosing a template rule, they use the usual criteria such as the priority and import precedence of the template rules, but they consider as candidates only a subset of the template rules in the stylesheet. This subset differs between the two instructions:

If a matching template rule R is found, then the result of the xsl:next-match or xsl:apply-imports instruction is the result of invoking R, with the values of parameters being set using the child xsl:with-param elements as described in 9.10 Setting Parameter Values. The template rule R is evaluated with the same focus as the xsl:next-match or xsl:apply-imports instruction. The current template rule changes to be R. The current mode does not change.

Note:

In the case where the current template rule T is declared within an xsl:override element in a using package P, while the selected rule R is declared within a different package Q, and where the current mode is MP (mode M in package P), the effect is that the current mode for evaluation of R remains MP rather than reverting to its corresponding mode MQ (mode M in package Q). If R contains an xsl:apply-templates instruction that uses mode="#current", then the set of template rules considered by this instruction will therefore include any overriding template rules declared in P as well as the original rules declared in Q.

If no matching template rule is found that satisfies these criteria, the built-in template rule for the context item is used (see 6.7 Built-in Template Rules).

An xsl:apply-imports or xsl:next-match instruction may use xsl:with-param child elements to pass parameters to the chosen template rule (see 9.10 Setting Parameter Values). It also passes on any tunnel parameters as described in 10.1.3 Tunnel Parameters.

[ERR XTDE0560] It is a dynamic error if xsl:apply-imports or xsl:next-match is evaluated when the current template rule is absent.

Example: Using xsl:apply-imports

For example, suppose the stylesheet doc.xsl contains a template rule for example elements:

<xsl:template match="example">
  <pre><xsl:apply-templates/></pre>
</xsl:template>

Another stylesheet could import doc.xsl and modify the treatment of example elements as follows:

<xsl:import href="doc.xsl"/>

<xsl:template match="example">
  <div style="border: solid red">
     <xsl:apply-imports/>
  </div>
</xsl:template>

The combined effect would be to transform an example into an element of the form:

<div style="border: solid red"><pre>...</pre></div>

An xsl:fallback instruction appearing as a child of an xsl:next-match instruction is ignored by an XSLT 2.0 or 3.0 processor, but can be used to define fallback behavior when the stylesheet is processed by an XSLT 1.0 processor with forwards compatible behavior.

6.9 Passing Parameters to Template Rules

A template rule may have parameters. The parameters are declared in the body of the template using xsl:param elements, as described in 9.2 Parameters.

Values for these parameters may be supplied in the calling xsl:apply-templates, xsl:apply-imports, or xsl:next-match instruction by means of xsl:with-param elements appearing as children of the calling instruction. The expanded QName represented by the name attribute of the xsl:with-param element must match the expanded QName represented by the name attribute of the corresponding xsl:param element.

It is not an error for these instructions to supply a parameter that does not match any parameter declared in the template rule that is invoked; unneeded parameter values are simply ignored.

A parameter may be declared as a tunnel parameter by specifying tunnel="yes" in the xsl:param declaration; in this case the caller must supply the value as a tunnel parameter by specifying tunnel="yes" in the corresponding xsl:with-param element. Tunnel parameters differ from ordinary template parameters in that they are passed transparently through multiple template invocations. They are fully described in 10.1.3 Tunnel Parameters.