[This local archive copy is from the official and canonical URL, http://www.w3.org/TR/1999/WD-xslt-19990421; please refer to the canonical source document if possible.]


W3C

XSL Transformations (XSLT) Specification
Version 1.0

W3C Working Draft 21 Apr 1999

This version:
http://www.w3.org/TR/1999/WD-xslt-19990421
http://www.w3.org/TR/1999/WD-xslt-19990421.xml
http://www.w3.org/TR/1999/WD-xslt-19990421.html
Latest version:
http://www.w3.org/TR/WD-xslt
Previous versions:
http://www.w3.org/TR/1998/WD-xsl-19981216
http://www.w3.org/TR/1998/WD-xsl-19980818
Editor:
James Clark <jjc@jclark.com>

Abstract

XSLT is a language for transforming XML documents into other XML documents.

XSLT is designed for use as part of XSL, which is a stylesheet language for XML. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.

XSLT is also designed to be used independently of XSL. However, XSLT is not intended as a completely general-purpose XML transformation language. Rather it is designed primarily for the kinds of transformation that are needed when XSLT is used as part of XSL.

Status of this document

This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. The material in this draft was previously part of the XSL Working Draft. The XSL Working Group will not allow early implementation to constrain its ability to make changes to this specification prior to final release. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than "work in progress". A list of current W3C working drafts can be found at http://www.w3.org/TR.

This draft is intended to be "feature complete". The Working Group plans to use future drafts to stabilize the current functionality; it does not intend to add any new functionality in version 1.0.

The XSL WG and the XML Linking WG have agreed to unify XSLT expressions and XPointers [XPointer]. A common core semantic model for querying has been agreed upon, and this draft follows this model (see [6.1 Location Paths]). However, further changes particularily in the syntax will probably be necessary.

This is part of the Style activity.

Comments may be sent to xsl-editors@w3.org; archives of the comments are available. Public discussion of XSL, including XSL Transformations, takes place on the XSL-List mailing list.

Table of contents

1. Introduction
2. Stylesheet Structure
3. Forwards-compatible Processing
4. Data Model
    4.1 Root Node
    4.2 Element Nodes
        4.2.1 Unique IDs
        4.2.2 Base URI
    4.3 Attribute Nodes
    4.4 Namespace Nodes
    4.5 Processing Instruction Nodes
    4.6 Comment Nodes
    4.7 Text Nodes
    4.8 Whitespace Stripping
5. Using the Result Tree
6. Expressions and Patterns
    6.1 Location Paths
        6.1.1 Axes
        6.1.2 Node Tests
        6.1.3 Predicates
        6.1.4 Abbreviated Syntax
    6.2 Expressions
        6.2.1 Basics
        6.2.2 Node-sets
        6.2.3 Booleans
        6.2.4 Numbers
        6.2.5 Strings
        6.2.6 Result Tree Fragments
        6.2.7 Extension Functions
        6.2.8 System Functions
        6.2.9 Lexical Structure
    6.3 Patterns
    6.4 Declarations
        6.4.1 Declaring Keys
        6.4.2 Declaring Extension Functions
        6.4.3 Declaring Locales
7. Template Rules
    7.1 Processing Model
    7.2 Defining Template Rules
    7.3 Applying Template Rules
    7.4 Conflict Resolution for Template Rules
    7.5 Built-in Template Rules
    7.6 Modes
8. Named Templates
9. Creating the Result Tree
    9.1 Creating Elements and Attributes
        9.1.1 Literal Result Elements
        9.1.2 Creating Elements with xsl:element
        9.1.3 Creating Attributes with xsl:attribute
        9.1.4 Named Attribute Sets
    9.2 Creating Text
    9.3 Creating Processing Instructions
    9.4 Creating Comments
    9.5 Copying
    9.6 Computing Generated Text
        9.6.1 Generating Text with xsl:value-of
        9.6.2 Attribute Value Templates
    9.7 Numbering
        9.7.1 Number to String Conversion Attributes
10. Repetition
11. Conditional Processing
    11.1 Conditional Processing with xsl:if
    11.2 Conditional Processing with xsl:choose
12. Sorting
13. Variables and Parameters
14. Messages
15. Combining Stylesheets
    15.1 Stylesheet Import
    15.2 Stylesheet Inclusion
    15.3 Embedding Stylesheets

Appendices

A. DTD Fragment for XSLT Stylesheets
B. References
    B.1 Normative References
    B.2 Other References
C. Examples
    A Formatting Objects Example
    B XHTML Example
D. Acknowledgements
E. Changes from Previous Public Working Draft

1. Introduction

A transformation expressed in XSLT describes rules for transforming a source tree into a result tree. The transformation is achieved by associating patterns with templates. A pattern is matched against elements in the source tree. A template is instantiated to create part of the result tree. The result tree is separate from the source tree. The structure of the result tree can be completely different from the structure of the source tree. In constructing the result tree, elements from the source tree can be filtered and reordered, and arbitrary structure can be added.

A transformation expressed in XSLT is called a stylesheet. This is because, in the case when XSLT is transforming into the XSL formatting vocabulary, the transformation functions as a stylesheet.

This document does not specify how an XSLT stylesheet is associated with an XML document. It is recommended that XSL processors support the mechanism described in [XML Stylesheet].

A stylesheet contains a set of template rules. A template rule has two parts: a pattern which is matched against nodes in the source tree and a template which can be instantiated to form part of the result tree. This allows a stylesheet to be applicable to a wide class of documents that have similar source tree structures.

A template is instantiated for a particular source element to create part of the result tree. A template can contain elements that specify literal result element structure. A template can also contain elements that are instructions for creating result tree fragments. When a template is instantiated, each instruction is executed and replaced by the result tree fragment that it creates. Instructions can select and process descendant source elements. Processing a descendant element creates a result tree fragment by finding the applicable template rule and instantiating its template. Note that elements are only processed when they have been selected by the execution of an instruction. The result tree is constructed by finding the template rule for the root node and instantiating its template.

In the process of finding the applicable template rule, more than one template rule may have a pattern that matches a given element. However, only one template rule will be applied. The method for deciding which template rule to apply is described in [7.4 Conflict Resolution for Template Rules].

XSLT uses XML namespaces [XML Names] to distinguish elements that are instructions to the XSLT processor from elements that specify literal result tree structure. Instruction elements all belong to the XSLT namespace. The examples in this document use a prefix of xsl: for elements in the XSLT namespace.

XSLT includes an expression language (see [6 Expressions and Patterns]) that is used for selecting elements for processing, for conditional processing and for generating text. The expression language is not a complete programming language. XSLT provides an extension mechanism to allow access from the expression language to a complete programming language such as ECMAScript or Java. XSLT does not require support for any programming language. Therefore XSLT stylesheets that must be portable across all XSLT implementations cannot depend on this extension mechanism.

2. Stylesheet Structure

A stylesheet is represented by an xsl:stylesheet element in an XML document. xsl:transform is allowed as a synonym for xsl:stylesheet.

XSLT processors must use the XML namespaces mechanism [XML Names] for both source documents and stylesheets. All XSLT defined elements, that is those specified in this document with a prefix of xsl:, will only be recognized by the XSLT processor if they belong to a namespace with the URI http://www.w3.org/XSL/Transform/1.0; XSLT defined elements are recognized only in the stylesheet not in the source document.

The xsl:stylesheet element may contain the following types of elements:

This example shows the structure of a stylesheet. Ellipses (...) indicate where attribute values or content have been omitted. Although this example shows one of each type of allowed element, stylesheets may contain zero or more of each of these elements.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
  <xsl:import href="..."/>

  <xsl:include href="..."/>

  <xsl:strip-space elements="..."/>
  
  <xsl:preserve-space elements="..."/>

  <xsl:key name="..." match="..." use="..."/>

  <xsl:functions ns="...">
  ...
  </xsl:functions>

  <xsl:locale name="...">
  ...
  </xsl:locale>

  <xsl:attribute-set name="...">
  ...
  </xsl:attribute-set>

  <xsl:variable name="...">...</xsl:variable>

  <xsl:param-variable name="...">...</xsl:param-variable>

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

  <xsl:template name="...">
   ...
  </xsl:template>

</xsl:stylesheet>

The order in which the children of the xsl:stylesheet element occur is not significant except for xsl:import elements and for error recovery. Users are free to order the elements as they prefer, and stylesheet creation tools need not provide control over the order in which the elements occur.

3. Forwards-compatible Processing

An XSLT processor must treat any namespace whose URI starts with the http://www.w3.org/XSL/Transform/ in the same way as the XSLT 1.0 namespace (http://www.w3.org/XSL/Transform/1.0) except that it must recover from errors as follows:

Ed. Note: What happens with stylesheets that mix XSLT namespaces with different versions?

Thus any XSLT 1.0 processor must be able to process the following stylesheet without error:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.1">
  <xsl:template name="/">
    <xsl:choose>
      <xsl:when test="system-property('xsl:version') >= 1.1">
        <xsl:exciting-new-1.1-feature/>
      </xsl:when>
      <xsl:otherwise>
        <p>Sorry this stylesheet requires XSLT 1.1.</p>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

4. Data Model

XSLT operates on an XML document, whether a stylesheet or a source document, as a tree. Any two stylesheets or source documents that have the same tree will be processed the same by XSLT. The XML document resulting from the tree construction process is also a tree. This section describes how XSLT models an XML document as a tree. This model is conceptual only and does not mandate any particular implementation.

XML documents operated on by XSLT must conform to the XML namespaces specification [XML Names].

The tree contains nodes. There are seven kinds of node:

Neither processing instruction nodes nor comment nodes are included in the tree for the stylesheet.

For every type of node there is a way of determining a string value for a node of that type. For some types of node, the value is part of the node; for other types of node, the value is computed from the value of descendant nodes.

Issue (data-entity): Should XSLT provide support for external data entities and notations?

Issue (entity-ref): Should XSLT provide support for entity references?

Issue (dtd): Should XSLT provide support for DTDs in the data model?

4.1 Root Node

The root node is the root of the tree. It does not occur anywhere else in the tree. It has a single child which is the element node for the document element of the document.

The value of the root node is the value of the document element.

4.2 Element Nodes

There is an element node for every element in the document. An element has an expanded name consisting of a local name and a possibly null URI reference (see [XML Names]); the URI reference will be null if the element type name has no prefix and there is no default namespace in scope. A relative URI reference should be resolved into an absolute URI during namespace processing.

The children of an element node are the element nodes, comment nodes, processing instruction nodes and text nodes for its content. Entity references to both internal and external entities are expanded. Character references are resolved.

The descendants of an element node are the children of the element node and the descendants of the children that are element nodes.

The value of an element node is the string that results from concatenating all characters that are descendants of the element node in the order in which they occur in the document.

The set of all element nodes in a document can be ordered according to the order of the start-tags of the elements in the document; this is known as document order.

Ed. Note: Need a definition of document order that handles arbitrary node types, including attributes.

4.2.1 Unique IDs

An element object may have a unique identifier (ID). This is the value of the attribute which is declared in the DTD as type ID. No two elements in a document may have the same unique ID. If an XML processor reports two elements in a document as having the same unique ID (which is possible only if the document is invalid) then the second element must be treated as not having a unique ID.

NOTE: If a document does not have a DTD, then no element in the document will have a unique ID.

4.2.2 Base URI

An element node also has an associated URI called its base URI which is used for resolving attribute values that represent relative URIs into absolute URIs. If an element occurs in an external entity, the base URI of that element is the URI of the external entity. Otherwise the base URI is the base URI of the document.

4.3 Attribute Nodes

Each element node has an associated set of attribute nodes. A defaulted attribute is treated the same as a specified attribute. If an attribute was declared for the element type in the DTD, but the default was declared as #IMPLIED, and the attribute was not specified on the element, then the element's attribute set does not contain a node for the attribute.

An attribute node has an expanded name and has a string value. The expanded name consists of a local name and a possibly null URI (see [XML Names]); the URI will be null if the specified attribute name did not have a prefix. The value is the normalized value as specified by the XML Recommendation [XML]. An attribute whose normalized value is a zero-length string is not treated specially: it results in an attribute node whose value is a zero-length string.

There are no attribute nodes for attributes that declare namespaces (see [XML Names]).

Issue (external-dtd): Should we specify something about how we expect XSLT processors to process external DTDs and parameter entities? For example, what happens if an attribute default is declared in an external DTD?

4.4 Namespace Nodes

Each element has an associated set of namespace nodes, one for each namespace prefix that is in scope for the element and one for the default namespace if one is in scope for the element. This means that an element will have a namespace node:

A namespace node has a name which is a string giving the prefix. This is empty if the namespace node is for the default namespace. A namespace node also has a value which is the namespace URI. If the namespace declaration specifies a relative URI, then the resolved absolute URI is used as the value.

When writing an element node in the result tree out as XML, an XSLT processor must add sufficient namespace-declaring attributes to the start-tag to ensure that if a tree were recreated from the XML, then the set of namespace nodes on the element node in the recreated tree would be equal to or a superset of the set of namespace nodes of the element node in the result tree.

NOTE: The semantics of a document type may treat parts of attribute values or data content as namespace prefixes. The presence of namespace nodes ensures that the semantics can be preserved when the tree is written out as XML.

4.5 Processing Instruction Nodes

There is a processing instruction node for every processing instruction.

Ed. Note: What about processing instructions in the internal subset or elsewhere in the DTD?

A processing instruction has a name. This is a string equal to the processing instruction's target. It also has a value. This is a string equal to the part of the processing instruction following the target and any whitespace. It does not include the terminating ?>.

4.6 Comment Nodes

There is a comment node for every comment.

Ed. Note: What about comments in the internal subset or elsewhere in the DTD?

A comment has a value. This is a string equal to the text of the comment not including the opening <!-- or the closing -->.

4.7 Text Nodes

Character data is grouped into text nodes. As much character data as possible is grouped into each text node: a text node never has an immediately following or preceding sibling that is a text node. The value of a text node is the character data.

Each character within a CDATA section is treated as character data. Thus <![CDATA[<]]> in the source document will treated the same as &lt;. Both will result in a single < character in a text node in the tree.

NOTE: When a text node that contains a < character is written out as XML, the < character must be escaped by, for example, using &lt;, or including it in a CDATA section.

Characters inside comments or processing instructions are not character data. Line-endings in external entities are normalized to #xA as specified in the XML Recommendation [XML].

4.8 Whitespace Stripping

After the tree has been constructed, but before it is otherwise processed by XSLT, some text nodes may be stripped. The stripping process takes as input a set of element types for which whitespace must be preserved. The stripping process is applied to both stylesheets and source documents, but the set of whitespace-preserving element types is determined differently for stylesheets and for source documents.

A text node is preserved if any of the following apply:

Otherwise the text node is stripped.

The xml:space attributes are not stripped from the tree.

NOTE: This implies that if an xml:space attribute is specified on a literal result element, it will be included in the result.

For stylesheets, the set of whitespace-preserving element types consists of just xsl:text.

For source documents, the set of whitespace-preserving element types is determined using the stylesheet as follows:

Ed. Note: Clarify how these declarations interact with each other and with xsl:import.

5. Using the Result Tree

The xsl:stylesheet element has an optional result-ns attribute; the value must be a namespace prefix. If there is a namespace declared as the default namespace, then an empty string may be used as the value to specify that the default namespace is the result namespace.

The result-ns attribute is a hint to the XSLT processor that it should do something with the result tree other than simply output it as XML. XSLT processors are not required to pay attention to the hint and may simply output the result tree as XML. If the result-ns attribute is not specified, then the result tree must be output as XML. If the result-ns attribute is specified, all elements in the result tree must belong to the namespace identified by this prefix (the result namespace).

When an XSLT processor outputs the result tree as a sequence of bytes that represents the result tree in XML, it must do so in such a way that the sequence of bytes is a well-formed XML document conforming to the XML Namespaces Recommendation [XML Names] and that if a new tree was constructed from the sequence of bytes as specified in [4 Data Model], the new tree would be the same as the result tree, with the following possible exceptions:

A result namespace of http://www.w3.org/XSL/Format/1.0 indicates that the result tree should be interpreted according to the semantics defined in [XSL]. XSL requires that XSL processors respect this hint. The examples in this document use the fo: prefix for this namespace.

A result namespace of http://www.w3.org/TR/REC-html40 indicates that the result tree should be output as HTML that conforms to the HTML 4.0 Recommendation rather than as XML; for example,

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
  xmlns="http://www.w3.org/TR/REC-html40"
  result-ns="">

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

...

</xsl:stylesheet>

The xsl:stylesheet element can include an indent-result attribute with values yes or no. If the stylesheet specifies indent-result="yes", then the XSLT processor may add whitespace to the result tree (possibly based on whitespace stripped from either the source document or the stylesheet) in order to indent the result nicely; if indent-result="no", it must not add any whitespace to the result. When adding whitespace with indent-result="yes", the XSLT processor can use any algorithm provided that the result is the same as the result with indent-result="no" after whitespace is stripped from both using the process described with the set of whitespace-preserving element types consisting of just xsl:text.

6. Expressions and Patterns

Ed. Note: The XSL WG and the XML Linking WG have agreed to unify XSLT expressions and XPointers. A common core semantic model for querying has been agreed upon, and this draft follows this model. However, further changes particularily in the syntax will probably be necessary.

Expressions are used in XSLT for a variety of purposes including:

An expression is evaluated to yield an object which has one of the following types:

Expression evaluation occurs with respect to a context, which consists of:

The context node is always a member of the context node list. The variable bindings consist of a mapping from variable names to variable values. The value of a variable is an object which can have any of the types which are possible for the value of an expression.

The variable bindings, node key function, extension functions and namespace declarations used to evaluate a subexpression are always the same as those used to evaluate the containing expression. The context node and context node list used to evaluate a subexpression is sometimes different from the context node and context node list used to evaluate the containing expression. When the evaluation of a kind of expression is described, it will always be explicitly stated if the context node and node list change for the evaluation of subexpressions; if nothing is said about the context node and context node list, they remain unchanged for the evaluation of subexpressions of that kind of expression.

The node key function takes a pair of strings (a key name and a key value) and a document and returns a set of nodes (the nodes in the document that have a key with the specified name and value).

In XSLT, expressions occur in attribute values. The grammar specified in this section applies to the attribute value after XML 1.0 normalization. So, for example, if the grammar uses the character < this must not appear in the XML source for the stylesheet as < but must be quoted according to XML 1.0 rules by, for example, entering it as &lt;.

A top-level expression (an expression not occurring within an expression) gets its context as follows:

One important kind of expression is a location path. A location path selects a set of nodes relative to the context node. The result of evaluating an expression that is a location path is the node-set containing the nodes selected by the location path. Location paths can recursively contain expressions which are used to filter lists of nodes.

Certain contexts in XSLT make use of a pattern. A pattern specifies a set of conditions on a node. A node that satisfies the conditions matches the pattern; a node that does not satisfy the conditions does not match the pattern. The syntax for patterns is a subset of the syntax for expressions. In particular location paths that meet certain restrictions can be used as patterns. An expression that is also a pattern always evaluates to an object of type node-set. A node matches a pattern if the node is a member of the result of evaluating the pattern as an expression with respect to some possible context; the possible contexts are those whose context node is the node being matched or one of its ancestors.

In the following grammar, the nonterminals QName and NCName are defined in [XML Names], and S is defined in [XML].

Expressions (including patterns and location paths) are parsed by first dividing up the character string to be parsed into tokens and then parsing the resulting sequence of tokens. Whitespace can be freely used between tokens. The tokenization process is described in [6.2.9 Lexical Structure].

6.1 Location Paths

Every location path can be expressed using a straightforward but rather verbose syntax. There are also a number of syntactic abbreviations that allow common cases to be expressed concisely. This section will explain the semantics of location paths using the unabbreviated syntax. The abbreviated syntax will then be explained by showing how it expands into the unabbreviated syntax (see [6.1.4 Abbreviated Syntax]).

Here are some examples of location paths using the unabbreviated syntax:

There are two kinds of location path: relative location paths and absolute location paths.

A relative location path consists of a sequence of one or more location steps separated by /. The steps in a relative location path are composed together from left to right. Each step in turn selects a set of nodes relative to a context node. An initial sequence of steps is composed together with a following step as follows. The initial sequence of steps selects a set of nodes relative to a context node. Each node in that set is used as a context node for the following step. The sets of nodes identified by the second step are unioned together. The set of nodes identified by the composition of the steps is this union. For example, from-children(div)/from-children(para) selects the para element children of the div element children of the context node, or, in other words, the para element grandchildren that have div parents.

An absolute location path consists of / optionally followed by a relative location path. A / by itself selects the root node of the document containing the context node. If it is followed by a relative location path, then the location path selects the set of nodes that would be selected by the relative location path relative to the root node of the document containing the context node.

A location step consists of

The axis identifier selects an initial list of nodes relative to the context node. The initial list of nodes is filtered first by the node test; the result of filtering by the node test is then filtered by the first predicate; the result of that is then filtered by the next predicate and so on. The node test selects nodes from the initial list based on the node type and node name. Each predicate selects nodes that satisfy a condition specified by an arbitrary expression. The result of the location step is the set of nodes that are members of the list that results from filtering the initial list by the node test and all the predicates. Note that although a location step selects a set of nodes, an axis selects a list of nodes and the predicates operate on a list of nodes.

The axis identifier is followed by the node test and predicates in parentheses. For example, from-descendants(para) selects the descendants of the context node that are para elements: from-descendants specifies the axis, and para is a test that is true for elements with name para. Each predicate is specified as an expression in square brackets.

Location Paths
[1]    LocationPath    ::=    RelativeLocationPath
| AbsoluteLocationPath
[2]    AbsoluteLocationPath    ::=    '/' RelativeLocationPath?
| AbbreviatedAbsoluteLocationPath
[3]    RelativeLocationPath    ::=    Step
| RelativeLocationPath '/' Step
| AbbreviatedRelativeLocationPath
[4]    Step    ::=    AxisIdentifier '(' NodeTest Predicate* ')'
| AbbreviatedStep

6.1.1 Axes

An axis identifies a list of nodes based on the kind of tree relationship that the nodes have to the context node. For example, the children of the context node are one axis, the ancestors of the context node are another axis. Note that an axis identifies an ordered list, not a set. The order of nodes in an axis is in the direction away from the context node.

The following axes are defined:

In an axis identifier the name of the axis is preceded by from- to distinguish it from a function name.

Axes
[5]    AxisIdentifier    ::=    'from-ancestors'
| 'from-ancestors-or-self'
| 'from-attributes'
| 'from-children'
| 'from-descendants'
| 'from-descendants-or-self'
| 'from-following'
| 'from-following-siblings'
| 'from-parent'
| 'from-preceding'
| 'from-preceding-siblings'
| 'from-self'

6.1.2 Node Tests

A node test that is a QName tests whether the node is an element or attribute with the specified name. For example, from-attributes(href) selects the href attribute of the context node; if the context node has no href attribute, it will select an empty set of nodes.

A QName in the node test is expanded into a local name and a possibly null URI. This expansion is done using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the URI is null (this is the same way attribute names are expanded). The expanded names are then compared for equality. Two expanded names are equal if they have the same local part, and either both have no URI or both have the same URI.

A node test * is true for any element or attribute node. For example, from-children(*) will select all element children of the context node, and from-attributes(*) will select all attributes of the context node.

A node test can have the form NCName:*. In this case the prefix is expanded in the same way as with a QName using the context namespace declarations. The node test will be true for an element or attribute whose expanded name has the URI to which the prefix expands, whatever the local part of the name.

The node test text() is true for any text node. For example from-children(text()) will select the text node children of the context node. Similarly, the node test comment() is true for any comment node, and the node test pi() is true for any processing instruction. The pi() test may have an argument that is Literal; in this case it is true for any processing instruction that has a name equal to the value of the Literal.

A node test node() is true for any node.

[6]    NodeTest    ::=    WildcardName
| NodeType '(' ')'
| 'pi' '(' Literal ')'

6.1.3 Predicates

A predicate filters a list of nodes to produce a new list of nodes. For each node in the list to be filtered, the PredicateExpr is evaluated with that node as the context node and with the complete list of nodes to be filtered as the context node list; if PredicateExpr evaluates to true for that node, the node is included in the new list; otherwise it is not included.

A PredicateExpr is evaluated by evaluating the Expr and converting the result to a boolean. If the result is a number, the result will be converted to true if the number is equal to the position of the context node in the context node list and will be converted to false otherwise; if the result is not a number, then the result will be converted as if by a call to the boolean() function. Thus a location path para[3] is equivalent to para[position()=3].

Predicates
[7]    Predicate    ::=    '[' PredicateExpr ']'
[8]    PredicateExpr    ::=    Expr

6.1.4 Abbreviated Syntax

Here are some examples of location paths using abbreviated syntax:

The most important abbreviation is that when the axis is the children axis, the from-children and surrounding parentheses can be omitted. In effect the children axis is the default axis. For example, a location path div/para is short for from-children(div)/from-children(para).

There's also an abbreviation for the attributes axis. Instead of using from-attributes and parentheses around the node test, the node test can be preceded by @ to indicate the attributes axis. For example, a location path para[@type="warning"] is short for from-children(para[from-attributes(type)="warning"]) and so selects para children with a type attribute with value equal to warning.

// is short for /from-descendants-or-self(node())/. For example, //para is short for /from-descendants-or-self(node())/from-children(para) and so will select any para element in the document (even a para element that is a document element will be selected by //para since the document element node is a child of the root node); div//para is short for div/from-descendants-or-self(node())/from-children(para) and so will select all para descendants of div children.

A location step of . is short for from-self(node()). This is particularly useful in conjunction with //. For example, the location path .//para is short for

from-self(node())/from-descendants-or-self(node())/from-children(para)

and so will select all para descendant elements of the context node.

Similarly a location step of .. is short for from-parent(node()). For example, ../title is short for from-parent(node())/from-children(title) and so will select the title children of the parent of the context node.

Abbreviations
[9]    AbbreviatedAbsoluteLocationPath    ::=    '//' RelativeLocationPath
[10]    AbbreviatedRelativeLocationPath    ::=    RelativeLocationPath '//' Step
[11]    AbbreviatedStep    ::=    AbbreviatedNodeTestStep
| '.'
| '..'
[12]    AbbreviatedNodeTestStep    ::=    '@'? NodeTest Predicate*

6.2 Expressions

6.2.1 Basics

A VariableReference evaluates to the value to which the variable name is bound in the set of variable bindings in the context.

Parentheses may be used for grouping.

[13]    Expr    ::=    OrExpr
[14]    PrimaryExpr    ::=    VariableReference
| '(' Expr ')'
| Literal
| Number
| FunctionCall
[15]    FunctionCall    ::=    NodeSetFunctionCall
| BooleanFunctionCall
| StringFunctionCall
| NumberFunctionCall
| SystemFunctionCall
| ExtensionFunctionCall

6.2.2 Node-sets

A location path can be used as an expression. The expression returns the set of nodes selected by the path.

The | operator computes the union of its operands which must be node-sets.

Square brackets are used to filter expressions in the same way that they are used in location paths. It is an error if the expression to be filtered does not evaluate to a node-set. The context node list used for evaluating the expression in square brackets is the node-set to be filtered listed in document order.

The / operator and // operators combine an arbitrary expression and a relative location path. It is an error if the expression does not evaluate to a node-set. The / operator does composition in the same way as when / is used in a location path. As in location paths, // is short for /from-descendants-or-self(node())/.

There are no types of objects that can be converted to node-sets. It is an error if evaluating a NodeSetExpr yields an object that is not a node-set.

The last() function returns the number of nodes in the context node list. The position() function returns the position of the context node in the context node list. The first position is 1, and so the last position will be equal to last().

The count() function returns the number of nodes in the argument node-set.

The id() and idref() functions select elements by their unique ID (see [4.2.1 Unique IDs]). id() converts its argument to a string and returns a node-set containing the element in the same document as the context node with unique ID equal to that string, if there is such an element, and otherwise returns an empty node-set. idref() requires that its argument be a node-set; for each node in the node-set, the value is split into a whitespace-separated list of tokens; idref() returns a node-set containing the elements in the same document as the context node that have a unique ID equal to any of the tokens in the value of any of the nodes in the node-set. For example,

Ed. Note: No way to get an ID in another document. Can workaround with xsl:for-each. Maybe add optional second argument which gives document.

Issue (id-inverse): Should there be a way to get back from an element to the elements that reference it (eg by IDREF attributes)?

The key() and keyref() functions select a set of nodes using the node key function in the expression evaluation context. Both functions have a string as the first argument that specifies the name of the key and have an expression as the second argument. key() has a second argument that is a string and returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to this string. keyref() has a second argument that is a node-set and returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to the value of any of the nodes in the argument node-set. See [6.4.1 Declaring Keys] for how to declare a key.

The doc() and docref() functions allow access to XML documents other than the initial source document. They both rely on the ability to treat a string as a URI reference that is mapped to a node-set; this mapping always takes places relative to a node that can be used to resolve a relative URI into an absolute URI. If the URI reference does not contain a fragment identifier, then it will be mapped to a node-set containing the root node in a tree representing the XML document whose document entity is the resource identified by the URI. If the URI reference contains a fragment identifier, then it will first map the URI to a tree representing the XML document whose document entity is the resource identified by the URI and then use the fragment identifier to select a set of nodes in that tree; the semantics of the fragment identifier is dependant on media type of the result of retrieving the URI. doc() takes a string argument which it treats as a URI reference which is mapped to a node-set relative to the element in the stylesheet containing the expression. Note that a zero-length URI reference is a reference to the document relative to which the URI reference is being resolved; thus doc("") refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document. docref() takes a node-set argument; for each node in the node-set, docref() treats the value of the node as a URI reference that is mapped to a node-set relative to that same node; docref() returns the union of the resulting node-sets.

Ed. Note: What if the fragment identifier identifies something that isn't a set of nodes (eg a span or a substring within a text node)? What are the allowed media types for the returned data? What is document order for node sets including nodes from multiple documents?

The local-part() function returns a string containing the local part of the name of the first node in the argument node-set. If the node-set is empty or the first node has no name, an empty string is returned. If the argument is omitted it defaults to the context node.

The namespace() function returns a string containing namespace of the name of the first node in the argument node-set. If the node-set is empty or the first node has no name or the name has no namespace, an empty string is returned. If the argument is omitted it defaults to the context node.

The qname() function returns a string containing a QName representing the name of the first node in the argument. The QName must represent the name with respect to the namespace declarations in effect on the node whose name is being represented. Typically this will be the form in which the name occurred in the XML source. This need not be the case if there are namespace declarations in effect on the node that associate multiple prefixes with the same namespace. However, an implementation may include information about the original prefix in its representation of nodes; in this case an implementation can ensure that the returned string is always the same as the QName used in the XML source. If the argument it omitted it defaults to the context node.

The generate-id() function returns a string that can be used as a unique identifier for the first node in the argument node-set. The unique identifier must consist of ASCII alphanumeric characters and must start with an alphabetic character. An implementation is free to generate an identifier in any convenient way provided that it always generates the same identifier for the same node and that different identifiers are always generated from different nodes. An implementation is under no obligation to generate the same identifiers each time a a document is transformed. If the argument node-set is empty, the empty string is returned. If the argument is omitted, it defaults to the context node.

[16]    NodeSetExpr    ::=    Expr
[17]    UnionExpr    ::=    PathExpr
| UnionExpr '|' PathExpr
[18]    PathExpr    ::=    LocationPath
| FilterExpr
| FilterExpr '/' RelativeLocationPath
| FilterExpr '//' RelativeLocationPath
[19]    FilterExpr    ::=    PrimaryExpr
| FilterExpr Predicate
[20]    NodeSetFunctionCall    ::=    'last' '(' ')'
| 'position' '(' ')'
| 'count' '(' NodeSetExpr ')'
| 'id' '(' StringExpr ')'
| 'idref' '(' NodeSetExpr ')'
| 'key' '(' StringExpr ',' StringExpr ')'
| 'keyref' '(' StringExpr ',' NodeSetExpr ')'
| 'doc' '(' StringExpr ')'
| 'docref' '(' NodeSetExpr ')'
| 'local-part' '(' NodeSetExpr? ')'
| 'namespace' '(' NodeSetExpr? ')'
| 'qname' '(' NodeSetExpr? ')'
| 'generate-id' '(' NodeSetExpr? ')'

6.2.3 Booleans

An object of type boolean can have two values, true and false.

The boolean() function converts its argument to a boolean as follows:

If the argument is omitted, it defaults to the context node.

A BooleanExpr is evaluated by converting the result of evaluating the Expr to a boolean as if by a call to the boolean() function.

An = expression is evaluated as follows. If at least one operand is a boolean, then each operand is converted to a boolean as if by applying the boolean() function and the operands are compared as booleans. Otherwise, if at least one operand is a number, then each operand is converted to a number as if by applying the number() function and the operands are compared as numbers; positive and negative zero compare equal. Otherwise both operands are converted to strings as if by applying the string() function and the operands are compared as strings; two strings are equal if they contain the same sequence of UCS characters.

A <, >, <= or >= expression is evaluated by first converting each operand to a number as if by a call to the number() function and then comparing the two numbers.

Issue (node-set-comparision): What should the semantics of comparison operators be when either or both of the operands are node-sets? Should there be an "any" or "all" semantic?

An or expression is evaluated by evaluating each operand and converting its value to a boolean. The result is true if either value is true and false otherwise.

An and expression is evaluated by evaluating each operand and converting its value to a boolean. The result is true if both values are true and false otherwise.

The not() function returns true if its argument is false, and false otherwise.

The true() function returns true.

The false() function returns false.

The lang() function returns true or false depending on whether the language of the context node as specified by xml:lang attributes is the same as or is a sublanguage of the language specified by the argument string. The language of the context node is determined by the value of the xml:lang attribute on the context node, or, if the context node has no xml:lang attribute, by the value of the xml:lang attribute on the nearest ancestor of the context node that has an xml:lang attribute. If there is no such attribute, then lang() returns false. If there is such an attribute, then lang() returns true if the attribute value is equal to the argument ignoring case, or if there is some suffix starting with - such that the attribute value is equal to the argument ignoring that suffix of the attribute value and ignoring case. For example, lang("en") would return true if the context node is any of these five elements:

<para xml:lang="en"/>
<div xml:lang="en"><para/></div>
<para xml:lang="EN"/>
<para xml:lang="en-us"/>
[21]    BooleanExpr    ::=    Expr
[22]    OrExpr    ::=    AndExpr
| OrExpr 'or' AndExpr
[23]    AndExpr    ::=    EqualityExpr
| AndExpr 'and' EqualityExpr
[24]    EqualityExpr    ::=    RelationalExpr
| EqualityExpr '=' RelationalExpr
[25]    RelationalExpr    ::=    AdditiveExpr
| RelationalExpr '<' AdditiveExpr
| RelationalExpr '>' AdditiveExpr
| RelationalExpr '<=' AdditiveExpr
| RelationalExpr '>=' AdditiveExpr
[26]    BooleanFunctionCall    ::=    'not' '(' BooleanExpr ')'
| 'true' '(' ')'
| 'false' '(' ')'
| 'boolean' '(' Expr? ')'
| 'lang' '(' StringExpr ')'

6.2.4 Numbers

A number represents a floating point number. A number can have any double-precision 64-bit format IEEE 754 value. These include a special "Not-a-Number" (NaN) value, positive and negative infinity, and positive and negative zero.

A NumberExpr is evaluated by converting the result of evaluating the Expr to a number as if by a call to the number() function.

The number() function converts its argument to a number as follows:

If the argument is omitted, it defaults to the context node.

The div operator performs floating point division according to IEEE 754.

The quo operator performs a floating point division and then truncates the result to an integer. For example,

The mod operator returns the remainder from the quo operation. For example,

NOTE: This is the same as the % operator in Java and ECMAScript.
NOTE: This is not the same as the IEEE remainder operation which returns the remainder from a rounding division.

The sum() function returns the sum of the values of the nodes in the argument node-set.

The floor() function returns the largest (closest to positive infinity) number that is not greater than the argument and that is an integer.

The ceiling() function returns the smallest (closest to negative infinity) number that is not less than the argument and that is an integer.

The round() function returns the number that is closest to the argument and that is an integer. If there are two such numbers, then the one that is even is returned.

Numeric Expressions
[27]    AdditiveExpr    ::=    MultiplicativeExpr
| AdditiveExpr '+' MultiplicativeExpr
| AdditiveExpr '-' MultiplicativeExpr
[28]    MultiplicativeExpr    ::=    UnaryExpr
| MultiplicativeExpr MultiplyOperator UnaryExpr
| MultiplicativeExpr 'div' UnaryExpr
| MultiplicativeExpr 'mod' UnaryExpr
| MultiplicativeExpr 'quo' UnaryExpr
[29]    UnaryExpr    ::=    UnionExpr
| '-' UnaryExpr
[30]    NumberExpr    ::=    Expr
[31]    NumberFunctionCall    ::=    'number' '(' Expr? ')'
| 'floor' '(' NumberExpr ')'
| 'ceiling' '(' NumberExpr ')'
| 'round' '(' NumberExpr ')'
| 'sum' '(' NodeSetExpr ')'

6.2.5 Strings

A string consists of a sequence of UCS characters.

A StringExpr is evaluated by converting the result of evaluating the Expr to a string as if by a call to the string() function.

The string() function converts an object to a string as follows:

If the argument is omitted, it defaults to the context node.

The concat() function returns the concatenation of its arguments.

The starts-with() function returns true if the first argument string starts with the second argument string, and otherwise returns false.

The contains() function returns true if the first argument string contains the second argument string, and otherwise returns false.

The substring-before() function returns the substring of the first argument string that precedes the first occurrence of the second argument string in the first argument string, or the empty string if the first argument string does not contain the second argument string. For example, substring-before("1999/04/01","/") returns 1999.

The substring-after() function returns the substring of the first argument string that follows the first occurrence of the second argument string in the first argument string, or the empty string if the first argument string does not contain the second argument string. For example, substring-after("1999/04/01","/") returns 04/01.

Ed. Note: Should the first argument of the above functions default to the value of the current node?

The normalize() function returns the argument string with white space normalized by stripping leading and trailing whitespace and replacing sequences of whitespace characters by a single space. Whitespace characters are the same allowed by the S production in XML. If the argument is omitted, it defaults to the context node converted to a string, in other words the value of the context node.

The translate() function returns the first argument string with occurrences of characters in the second argument string replaced by the corresponding characters from the third argument string. For example, translate("bar","abc","ABC") returns the string BAr.

The format-number() function converts its first argument to a string using the format pattern string specified by the second argument and the locale named by the third argument, or the default locale, if there is no third argument. The format pattern string is in the syntax specified by the JDK 1.1 DecimalFormat class. The format pattern string is in a localized notation: the locale determines what characters have a special meaning in the pattern (with the exception of the quote character, which is not localized). The format pattern must not contain the currency sign (#x00A4); support for this feature was added after the initial release of JDK 1.1. See [6.4.3 Declaring Locales] for how to declare a locale.

[32]    StringExpr    ::=    Expr
[33]    StringFunction    ::=    'string' '(' Expr? ')'
| 'starts-with' '(' StringExpr ',' StringExpr ')'
| 'contains' '(' StringExpr ',' StringExpr ')'
| 'substring-before '(' StringExpr ',' StringExpr ')'
| 'substring-after '(' StringExpr ',' StringExpr ')'
| 'normalize' '(' StringExpr? ')'
| 'translate' '(' StringExpr ',' StringExpr ',' StringExpr ')'
| 'concat' '(' StringExpr (',' StringExpr)+ ')'
| 'format-number' '(' NumberExpr ',' StringExpr (',' StringExpr)? ')'

Issue (regex): Should XSLT support regular expressions for matching against any or all of pcdata content, attribute values, attribute names, element type names?

Issue (equality-case): Do we need to be able to do comparisons in a case insensitive way?

Issue (equality-normalize): Do we need to normalize strings before comparison? Does the stylesheet need to specify what kinds of normalization are required (eg compatibility character normalization)?

Issue (resolve-expr): Do we need a resolve(NodeSetExpr) string expression that treats the characters as a relative URI and turns it into an absolute URI using the base URI of the addressed node?

6.2.6 Result Tree Fragments

Ed. Note: Add explanation of what a result tree fragment is.

The only operations that can be performed on a result tree fragment are to convert it to a string or a boolean. In particular, it is not permitted to use the /, //, and [] on result tree fragments.

Expressions can only return values of type result tree fragment by referencing variables of type result tree fragment or calling extension functions that return a result tree fragment.

6.2.7 Extension Functions

[34]    ExtensionFunctionCall    ::=    CName '(' ( Expr ( ',' Expr)*)? ')'

The CName is expanded to a name using the namespace declarations from the evaluation context. The XSLT processor attempts to locate an implementation of the extension function with the specified name that it can use. The implementation may be provided by an xsl:functions element (see [6.4.2 Declaring Extension Functions]) or the XSLT processor may be able to locate an implementation by other means not specified by XSLT. If the XSLT processor cannot locate such a function, then evaluating the expression is an error. Otherwise the implementation is called passing it the values of the expressions and the value returned by the function is the value of the expression. The function-available() function can be used to test whether an implementation of a particular function is available (see [6.2.8 System Functions]). A XSLT processor is allowed always to give an error when evaluating an ExtensionFunctionCall (with such an XSLT processor the function-available() function would always return false). Therefore if an XSLT stylesheet includes an ExtensionFunctionCall and does not use the function-available() function to test for and handle the possibility that an implementation of the function is not available, then it may not be portable across all XSLT implementations.

6.2.8 System Functions

[35]    SystemFunctionCall    ::=    'system-property' '(' StringExpr ')'
| 'function-available' '(' StringExpr ')'

For both these functions, the StringExpr must evaluate to a string that is a QName. The QName is expanded into a name using the namespace declarations in scope for the expression.

The system-property() function returns an object representing the value of the system property identified by the name. If the name has no namespace, then the system-property() function must return the string value of the operating system environment variable whose name is equal to the local part of the name. If there is no such system property, the empty string should be returned.

Implementations must provide the following system properties which are all in the XSLT namespace:

The function-available() function returns true if an implementation of the named extension function is available. For example:

<xsl:if test="function-available('jjc:currentDate')">
  <xsl:value-of select="jjc:currentDate()"/>
</xsl:if>

6.2.9 Lexical Structure

When tokenizing, the longest possible token is always returned.

For readability, whitespace may be used in patterns even though not explicitly allowed by the grammar: ExprWhitespace may be freely added within patterns before or after any ExprToken.

A NodeType, FunctionName, CName or AxisIdentifier token is recognized only when the following token is (. An OperatorName token or MultiplyOperator token is recognized as such only when there is a preceding token and the preceding token is not one of @, (, [, , or an Operator.

Expression Lexical Structure
[36]    ExprToken    ::=    '(' | ')' | '[' | ']' | '.' | '..' | '@' | ','
| WildcardName
| NodeType
| Operator
| FunctionName
| AxisIdentifier
| Literal
| Number
| CName
| VariableReference
[37]    Literal    ::=    '"' [^"]* '"'
| "'" [^']* "'"
[38]    Number    ::=    [0-9]+ ('.' [0-9]+)?
| '.' [0-9]+
[39]    Operator    ::=    OperatorName
| MultiplyOperator
| '/' | '//' | '|' | '+' | '-' | '=' | '<'| '<=' | '>' | '>='
[40]    OperatorName    ::=    'and' | 'or' | 'mod' | 'div' | 'quo'
[41]    MultiplyOperator    ::=    '*'
[42]    FunctionName    ::=    'boolean'
| 'ceiling'
| 'concat'
| 'contains'
| 'count'
| 'doc'
| 'docref'
| 'false'
| 'floor'
| 'format-number'
| 'function-available'
| 'generate-id'
| 'id'
| 'idref'
| 'key'
| 'keyref'
| 'lang'
| 'last'
| 'local-part'
| 'namespace'
| 'normalize'
| 'not'
| 'number'
| 'position'
| 'qname'
| 'round'
| 'starts-with'
| 'string'
| 'substring-after'
| 'substring-before'
| 'sum'
| 'system-property'
| 'translate'
| 'true'
[43]    CName    ::=    NCName ':' NCName
[44]    VariableReference    ::=    '$' NCName
[45]    WildcardName    ::=    '*'
| NCName ':' '*'
| QName
[46]    NodeType    ::=    'comment'
| 'text'
| 'pi'
| 'node'
[47]    ExprWhitespace    ::=    S

6.3 Patterns

This section explains what expressions are allowed as patterns and what the semantics of matching a pattern are.

Here are some examples of patterns:

A pattern must match the grammar for Pattern. A Pattern is set of location path patterns separated by |. A location path pattern is a location path none of the steps of which use either AxisIdentifiers or . or ... Location path patterns can also start with an id() or key() function call with a literal argument (see [6.2.2 Node-sets]). Predicates in a pattern can use arbitrary expressions just like predicates in a location path.

Patterns
[48]    Pattern    ::=    LocationPathPattern
| Pattern '|' LocationPathPattern
[49]    LocationPathPattern    ::=    '/' RelativePathPattern?
| IdKeyPattern (('/' | '//') RelativePathPattern)?
| '//'? RelativePathPattern
[50]    IdKeyPattern    ::=    'id' '(' Literal ')'
| 'key' '(' Literal ',' Literal ')'
[51]    RelativePathPattern    ::=    StepPattern
| RelativePathPattern '/' StepPattern
| RelativePathPattern '//' StepPattern
[52]    StepPattern    ::=    AbbreviatedNodeTestStep

A pattern is defined to match a node if and only if there is possible context such that when the pattern is evaluated as an expression with that context, the node is a member of the resulting node-set. When a node is being matched the possible contexts have a context node that is the node being matched or any ancestor of that node, and a context node list containing just the context node.

For example, p matches any p element, because for any p if the expression p is evaluated with the parent of the p element as context the resulting node-set will contain that p element as one of its members.

NOTE: This matches even a p element that is the document element, since the document root is the parent of the document element.

Although the semantics of patterns are specified indirectly in terms of expression evaluation, it is easy to understand the meaning of a pattern directly without thinking in terms of expression evaluation. In a pattern, | indicates alternatives; a pattern with one or more | separated alternatives matches if any one of the alternative matches. A pattern that consists of a sequence of StepPatterns separated by / or // is matched from right to left. The pattern only matches if the rightmost StepPattern matches and a suitable element matches the rest of the pattern; if the separator is / then only the parent is a suitable element; if the separator is //, then any ancestor is a suitable element. A StepPattern that's a NodeTest matches if the NodeTest is true for the node and the node is not an attribute node. A StepPattern that starts with @ matches if the node is an attribute node and the WildcardName matches the name of the attribute. When [] is present, then the first PredicateExpr in a StepPattern is evaluated with the element being matched as the context node and the siblings of the elements that match the NodeTest as the context node list, unless the node being matched is an attribute node, in which case the context node list is all the attributes that have the same parent as the attribute being matched and that match the WildcardName.

For example

appendix//ulist/item[position()=1]

matches a node if and only if all of the following are true:

Ed. Note: Need to revise above paragraph if we decide not to call the element to which an attribute is attached the parent of the attribute.

6.4 Declarations

6.4.1 Declaring Keys

The xsl:key element is used to declare keys. The name specifies the name of the key. The match attribute is a Pattern; a xsl:key element gives information about the keys of any node that match the pattern specified in the match attribute. The use attribute is a NodeSetExpr, which specifies the set of values for which the node has a key of the specified name. A node x has a key with name y and value z if and only if there is a xsl:key element such that:

Note that the NodeSetExpr may return a node-set with more than one node; all of the returned nodes serve as a key value. Note also that there may be more than one xsl:key element that matches a given node; all of the matching xsl:key elements are used.

Ed. Note: Add some examples.

6.4.2 Declaring Extension Functions

Implementations of the extension functions in a namespace can be provided using the xsl:functions element. The required ns attribute specifies the namespace for which an implementation is being provided. The value of the ns attribute is a namespace prefix which is expanded to a namespace URI using the namespace declarations in effect on the xsl:functions element.

The implementation may be provided in two ways. If the code attribute is present, then its value is a URI that identifies a resource containing an implementation of the functions in the namespace; in this case a type attribute giving the MIME media type of the data providing the implementation may also be provided, so as to allow the XSLT processor to avoid fetching resources of types that it is unable to make use of. If the code attribute is not present, then the content of the xsl:functions element contains the implementation of the functions; in this case the type attribute must be present.

Multiple alternative implementations may be provided for the same namespace. For example,

<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
 xmlns:jjc="http://www.jclark.com">

<xsl:template match="/">
  <xsl:value-of select="jjc:currentDate()"/>
</xsl:template>

<xsl:functions ns="jjc" type="text/javascript">

function currentDate() {
 return Date().toString()
}

<p>When multiple alternative implementations are provided, it is up to
the XSLT processor to determine which to use.</p>

</xsl:functions>

<xsl:functions ns="jjc" code="clsid:9A447990-E64D-11D2-8C29-00A0CC2428DA"/>

</xsl:stylesheet>

The xsl:functions element may also have an archive attribute that specifies a whitespace-separated list of URIs of resources relevant to the provided implementation.

An XSLT processor is not required to be able to make use of implementations provided by xsl:functions elements. The MIME media types that an XSLT processor is able to make use of and the way the XSLT processor interfaces with implementations is dependent on the particular XSLT processor. Therefore if an XSLT stylesheet includes an ExtensionFunctionCall of an extension function in a namespace for which an implementation is provided by an xsl:functions element, then it may not be portable across all XSLT implementations.

6.4.3 Declaring Locales

The xsl:locale element declares a locale which controls the interpretation of a format pattern used by the format-number() function. If there is a name attribute then the element declares a named locale, otherwise it declares the default locale.

The other attributes on xsl:locale correspond to the methods on the JDK 1.1 DecimalFormatSymbols class. For each get/set method pair there is an attribute defined for the xsl:locale element. The default values are given in the XSLT DTD (see [A DTD Fragment for XSLT Stylesheets]).

The following attributes specify characters that may appear in the result of formatting the number and also control the interpretation of characters in the format pattern:

The following attributes control the interpretation of characters in the format pattern:

The following attributes specify strings that may appear in the result of formatting the number:

7. Template Rules

7.1 Processing Model

A list of source nodes is processed to create a result tree fragment. The result tree is constructed by processing a list containing just the root node. A list of source nodes is processed by appending the result tree structure created by processing each of the members of the list in order. A node is processed by finding all the template rules with patterns that match the node, and choosing the best amongst them. The chosen rule's template is then instantiated for the node. During the instantiation of a template, the node for which the template is being instantiated is called the current node; the list of source nodes that is being processed is called the current node list. The current node is always a member of the current node list. A template typically contains instructions that select an additional list of source nodes for processing. The process of matching, instantiation and selection is continued recursively until no new source nodes are selected for processing.

Implementations are free to process the source document in any way that produces the same result as if it were processed using this processing model.

7.2 Defining Template Rules

A template rule is specified with the xsl:template element. The match attribute is a Pattern that identifies the source node or nodes to which the rule applies. The match attribute is required unless the xsl:template element has a name attribute (see [8 Named Templates]). The content of the xsl:template element is the template.

Issue (template-match-default): Should the match attribute have a default? Any node? Any child node? The root node?

For example, an XML document might contain:

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

The following template rule matches emph elements and has a template which produces a fo:inline-sequence formatting object with a font-weight property of bold.

<xsl:template match="emph">
  <fo:inline-sequence font-weight="bold">
    <xsl:apply-templates/>
  </fo:inline-sequence>
</xsl:template>

As described later, the xsl:apply-templates element recursively processes the children of the source element.

7.3 Applying Template Rules

This example creates a block for a chapter element and then processes its immediate children.

<xsl:template match="chapter">
  <fo:block>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes. However, text nodes that have been stripped as specified in [4.8 Whitespace Stripping] will not be processed.

Ed. Note: There is no WG consensus on the use of xsl:apply-templates without a select attribute to process all children of a node.

A select attribute can be used to process nodes selected by an expression instead of all children. The value of the select attribute is a NodeSetExpr. The selected set of nodes are processed in document order, unless a sorting specification is present (see [12 Sorting]). The following example processes all of the author children of the author-group:

<xsl:template match="author-group">
  <fo:inline-sequence>
    <xsl:apply-templates select="author"/>
  </fo:inline-sequence>
</xsl:template>

The following example processes all of the first-names of the authors that are children of author-group:

<xsl:template match="author-group">
  <fo:inline-sequence>
    <xsl:apply-templates select="author/first-name"/>
  </fo:inline-sequence>
</xsl:template>

This example processes all of the heading elements contained in the book element.

<xsl:template match="book">
  <fo:block>
    <xsl:apply-templates select=".//heading"/>
  </fo:block>
</xsl:template>

It is also possible to process elements that are not descendants of the current node. This example assumes that a department element contains group and employee elements (at some level). 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="from-ancestors(department)/group"/>
  </fo:block>
</xsl:template>

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>
NOTE: 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.

Use of expressions in xsl:apply-templates can lead to infinite loops. It is an error if, during the invocation of a rule for a node, that same rule is invoked again for that node. An XSLT processor may signal the error; if it does not signal the error, it must recover by creating an empty result tree structure for the nested invocation.

Ed. Note: This isn't right with parameters.

Ed. Note: Also doesn't apply to built-in rules because they can be invoked in multiple modes.

7.4 Conflict Resolution for Template Rules

It is possible for a source node to match more than one template rule. The template rule to be used is determined as follows:

  1. First, all matching template rules that are less important than the most important matching template rule or rules are eliminated from consideration.

  2. Next, all matching template rules that have a lower priority than the matching template rule or rules with the highest priority are eliminated from consideration. The priority of a template rule is specified by the priority attribute on the template rule. The value of this must be a real number (positive or negative). The default priority is computed as follows:

    The idea is that the most common kind of pattern (a pattern that just tests for an element with a specific name) has priority 0; a pattern more specific than this has priority 1; a pattern less specific than this has priority -1.

    Ed. Note: Say exactly what syntax is allowed for real numbers.

It is an error if this leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.

7.5 Built-in Template Rules

There is a built-in template rule to allow recursive processing to continue in the absence of a successful pattern match by an explicit rule in the stylesheet. This rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

There is also a built-in template rule for text nodes that copies text through:

<xsl:template match="text()">
  <xsl:value-of select="."/>
</xsl:template>

The built-in rule does not apply to processing instructions and comments. When a comment or processing instruction is processed, and no rule is matched, nothing is created.

The built-in template rules are treated as if they were imported implicitly before the stylesheet and so are considered less important than all other template rules. Thus the author can override a built-in rule by including an explicit rule with match="*|/" or match="text()".

7.6 Modes

Modes allow an element to be processed multiple times, each time producing a different result.

Both xsl:template and xsl:apply-templates have an optional mode attribute whose value is a name. If xsl:template does not have a match attribute it must not have a mode attribute. If an xsl:apply-templates element has a mode attribute, then it applies only to those template rules from xsl:template elements that have a mode attribute with the same value; if an xsl:apply-templates element does not have a mode attribute, then it applies only to those template rules from xsl:template elements that do not have a mode attribute.

If there is no matching template, then the built-in template rules are applied, even if a mode attribute was specified in xsl:apply-templates.

Ed. Note: Add some examples.

8. Named Templates

Templates can be invoked by name. An xsl:template element with a name attribute specifies a named template. If a xsl:template element has a name attribute, it may, but need not, also have a match attribute. An xsl:call-template element invokes a template by name; it has a required name attribute that identifies the template to be invoked. Unlike xsl:apply-templates, xsl:call-template does not change the current node or the current node list.

Ed. Note: Expand this.

It is an error if a stylesheet contains more than one template with the same name and same importance. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the templates with highest importance the one that occurs last in the stylesheet.

9. Creating the Result Tree

This section describes instructions that directly create nodes in the result tree.

Issue (multiple-results): Should it be possible to create multiple result trees?

9.1 Creating Elements and Attributes

9.1.1 Literal Result Elements

In a template an element in the stylesheet that does not belong to the XSLT namespace is instantiated to create an element node of the same type. The created element node will have the attribute nodes that were present on the element node in the stylesheet tree. The created element node will also have the namespace nodes that were present on the element node in the stylesheet tree with the exception of any namespace node whose value is the XSLT namespace URI (http://www.w3.org/XSL/Transform/1.0).

The value of an attribute of a literal result element is interpreted as an attribute value template: it can contain string expressions contained in curly braces ({}).

Namespace URIs that occur literally in the stylesheet and that are being used to create nodes in the result tree can be quoted. This applies to:

A namespace URI is quoted by prefixing it with the string quote:. This prefix will be removed when the template is instantiated to create the result element node with its associated attribute nodes and namespace nodes.

When literal result elements are being used to create element, attribute, or namespace nodes that use the XSLT namespace URI, the namespace must be quoted to avoid misinterpretation by the XSLT processor.

NOTE: It may be necessary also to quote other namespaces. For example, literal result elements belonging to a namespace dealing with digital signatures might cause XSLT stylesheets to be mishandled by general purpose security software; quoting the namespace would avoid the possibility of such mishandling.

For example, the stylesheet

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
  xmlns:fo="http://www.w3.org/XSL/Format/1.0"
  xmlns:qxsl="quote:http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/">
  <qxsl:stylesheet result-ns="fo">
    <xsl:apply-templates/>
  </qxsl:stylesheet>
</xsl:template>

<xsl:template match="block">
  <qxsl:template match="{.}">
     <fo:block><qxsl:apply-templates/></fo:block>
  </qxsl:template>
</xsl:template>

</xsl:stylesheet>

will generate an XSLT stylesheet from a document of the form:

<elements>
<block>p</block>
<block>h1</block>
<block>h2</block>
<block>h3</block>
<block>h4</block>
</elements>

9.1.2 Creating Elements with xsl:element

The xsl:element element allows an element to be created with a computed name. The name of the element to be created is specified by a required name attribute and an optional namespace attribute. The content of the xsl:element element is a template for the attributes and children of the created element.

The name attribute is interpreted as an attribute value template; the string value from instantiating it must be a QName. If the namespace attribute is not present, then the QName is expanded into a name using the namespace declarations in effect for the xsl:element element, including any default namespace declaration.

Ed. Note: What should happen if the name is not a valid QName?

If the namespace attribute is present, then it also interpreted as an attribute value template; the string value from instantiating it should be a URI reference. This is used as the namespace of the name of the element to be created. The local part of the QName specified by the name attribute is used as the local part of the name of the element to be created.

Ed. Note: What should happen if the namespace is not a syntactically legal URI reference? Should URI escaping automatically be done?

XSLT processors may make use of the prefix of the QName specified in the name attribute when selecting the prefix used for outputting the created element as XML. They are not however required to do so.

9.1.3 Creating Attributes with xsl:attribute

The xsl:attribute element can be used to add attributes to result elements whether created by literal result elements in the stylesheet or by instructions such as xsl:element. The name of the attribute to be created is specified by a required name attribute and an optional namespace attribute. Instantiating an xsl:attribute element adds an attribute node to the containing result element node. The content of the xsl:attribute element is a template for the value of the created attribute.

The name attribute is interpreted as an attribute value template; the string value from instantiating it must be a QName. If the namespace attribute is not present, then the QName is expanded into a name using the namespace declarations in effect for the xsl:attribute element, not including any default namespace declaration.

Ed. Note: What should happen if the name is not a valid QName?

If the namespace attribute is present, then it also interpreted as an attribute value template; the string value from instantiating it should be a URI reference. This is used as the namespace of the name of the attribute to be created. The local part of the QName specified by the name attribute is used as the local part of the name of the attribute to be created.

Ed. Note: What should happen if the namespace is not a syntactically legal URI reference? Should URI escaping automatically be done?

XSLT processors may make use of the prefix of the QName specified in the name attribute when selecting the prefix used for outputting the created attribute as XML. They are not however required to do so.

The following are all errors:

9.1.4 Named Attribute Sets

The xsl:attribute-set element defines a named set of attributes. The name attribute specifies the name of the attribute set. The xsl:use element adds a named set of attributes to an element. It has a required attribute-set attribute that specifies the name of the attribute set. xsl:use is allowed in the same places as xsl:attribute. The content of the xsl:attribute-set consists of xsl:attribute elements that specify attributes; it may also contain xsl:use elements. The value of attributes in an attribute set is determined when the attribute set is used rather than when the attribute set is defined.

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

<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>

<xsl:template match="chapter/heading">
  <fo:block quadding="start">
    <xsl:use attribute-set="title-style"/>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

Any attribute in a named attribute set specified by xsl:use is not added to an element if the element already has an attribute of that name.

Multiple definitions of an attribute set with the same name are merged. An attribute from a definition that is more important takes precedence over an attribute from a definition that is less important. It is an error if there are two attribute sets with the same name that are equally important and that both contain the same attribute unless there is a more important definition of the attribute set that also contains the attribute. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the most important definitions that specify the attribute the one that was specified last in the stylesheet.

9.2 Creating Text

A template can also contain text nodes. Each text node in a template remaining after whitespace has been stripped as specified in [4.8 Whitespace Stripping] will create a text node with the same value in the result tree. Adjacent text nodes in the result tree are automatically merged.

Note that text is processed at the tree level. Thus, markup of &lt; in a template will be represented in the stylesheet tree by a text node that includes the character <. This will create a text node in the result tree that contains a < character, which will be represented by the markup &lt; (or an equivalent character reference) when the result tree is externalized as an XML document.

Literal data characters may also be wrapped in an xsl:text element. This wrapping may change what whitespace characters are stripped (see [4.8 Whitespace Stripping]) but does not affect how the characters are handled by the XSLT processor thereafter.

9.3 Creating Processing Instructions

The xsl:pi element is instantiated to create a processing instruction node. The content of the xsl:pi element is a template for the value of the processing instruction node. The xsl:pi element has a required name attribute that specifies the name of the processing instruction node. The value of the name attribute is interpreted as an attribute value template.

For example, this

<xsl:pi name="xml-stylesheet">href="book.css" type="text/css"</xsl:pi>

would create the processing instruction

<?xml-stylesheet href="book.css" type="text/css"?>

It is an error if instantiating the content of xsl:pi creates anything other than characters. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

It is an error if the result of instantiating the content of the xsl:pi contains the string ?>. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of ? that is followed by an >.

Ed. Note: What should happen if the name is not a valid NCName?

9.4 Creating Comments

The xsl:comment element is instantiated to create a comment node in the result tree. The content of the xsl:comment element is a template for the value of the comment node.

For example, this

<xsl:comment>This file is automatically generated. Do not edit!</xsl:comment>

would create the comment

<!--This file is automatically generated. Do not edit!-->

It is an error if instantiating the content of xsl:comment creates anything other than characters. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

It is an error if the result of instantiating the content of the xsl:comment contains the string -- or ends with -. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of - that is followed by another - or that ends the comment.

9.5 Copying

The xsl:copy element provides an easy way of copying the current node. The xsl:copy element is replaced by a copy of the current node. The namespace nodes of the current node are automatically copied as well, but the attributes and children of the node are not automatically copied. The content of the xsl:copy element is a template for the attributes and children of the created node; the content is not used for nodes of types that do not have attributes or children (attributes, text, comments and processing instructions).

The root node is treated specially because the root node of the result tree is created implicitly. When the current node is the root node, xsl:copy will not create a root node, but will just use the content template.

For example, the identity transformation can be written using xsl:copy as follows:

<xsl:template match="*|@*|comment()|pi()|text()">
  <xsl:copy>
    <xsl:apply-templates select="*|@*|comment()|pi()|text()"/>
  </xsl:copy>
</xsl:template>

The xsl:copy-of element copies a list of nodes specified by an expression. The required select attribute contains an expression. The result of evaluating the expression must be a node-set or a result tree fragment. When it is node-set, all the nodes in the set together with their content are copied in document order over into the result tree; when it is a result tree fragment; the complete fragment is copied over into the result tree.

When the current node is an attribute, then if it would be an error to use xsl:attribute to create an attribute with the same name as the current node, then it is also an error to use xsl:copy (see [9.1.3 Creating Attributes with xsl:attribute]).

9.6 Computing Generated Text

Within a template, the xsl:value-of element can be used to compute generated text, for example by extracting text from the source tree or by inserting the value of a variable. The xsl:value-of element does this with an expression that is specified as the value of the select attribute. String expressions can also be used inside attribute values of literal result elements by enclosing the string expression in curly brace ({}).

9.6.1 Generating Text with xsl:value-of

The xsl:value-of element is replaced by the result of evaluating the expression specified by the select attribute. The select attribute is required. The expression is a StringExpr, which means the result of evaluating the expression is converted to a string. The element is called xsl:value-of because a node-set is converted to a string by returning the value of the first node.

Issue (value-of-select-default): Should the select attribute have a default value of .?

For example, the following creates an HTML paragraph from a person element with first-name and surname attributes. The paragraph will contain the value of the first-name attribute of the current node followed by a space and the value of the surname attribute of the current node.

<xsl:template match="person">
  <p>
   <xsl:value-of select="@first-name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="@surname"/>
  </p>
</xsl:template>

For example, the following creates an HTML paragraph from a person element with first-name and surname children elements. The paragraph will contain the value of the first first-name child element of the current node followed by a space and the value of the first surname child element of the current node.

<xsl:template match="person">
  <p>
   <xsl:value-of select="first-name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="surname"/>
  </p>
</xsl:template>

The following precedes each procedure element with a paragraph containing the security level of the procedure. It assumes that the security level that applies to a procedure is determined by a security attribute on the procedure element or on an ancestor element of the procedure. It also assumes that if more than one such element has a security attribute then the security level is determined by the element that is closest to the procedure.

<xsl:template match="procedure">
  <fo:block>
    <xsl:value-of select="from-ancestors-or-self(*[@security][1])/@security"/>
  </fo:block>
  <xsl:apply-templates/>
</xsl:template>

9.6.2 Attribute Value Templates

In an attribute value that is interpreted as an attribute value template, such as an attribute of a literal result element, a StringExpr can be used by surrounding the StringExpr with curly braces ({}). The attribute value template is instantiated by replacing the string expression together with surrounding curly braces by the result of evaluating the string expression. Curly braces are not recognized in an attribute value in an XSLT stylesheet unless the attribute is specifically stated to be one which is interpreted as an attribute value template.

NOTE: Not all attributes are interpreted as attribute value templates. Attributes whose value is an expression or pattern, attributes of top-level elements (children of a xsl:stylesheet element) and attributes that refer to named XSLT objects are not interpreted as attribute value templates. Also xmlns attributes are not interpreted as attribute value templates: it would not be conformant with the XML Namespaces Recommendation to do this.

The following example creates an img result element from a photograph element in the source; the value of the SRC attribute of the img element is computed from the value of the image-dir constant and the content of the href child of the photograph element; the value of the width attribute of the img element is computed from the value of the width attribute of the size child of the photograph element:

<xsl:variable name="image-dir">/images</xsl:variable>

<xsl:template match="photograph">
<img src="{$image-dir}/{href}" width="{size/@width}"/>
</xsl:template>

With this source

<photograph>
  <href>headquarters.jpg</href>
  <size width="300"/>
</photograph>

the result would be

<img src="/images/headquarters.jpg" width="300"/>

When an attribute value template is instantiated, a double left or right curly brace outside a string expression will be replaced by a single curly brace. It is an error if a right curly brace occurs in an attribute value template outside a string expression without being followed by a second right curly brace; an XSLT processor may signal the error or recover by treating the right curly brace as if it had been doubled. A right curly brace inside a Literal in a string expression is not recognized as terminating the string expression.

Curly braces are not recognized recursively inside string expressions. For example:

<a href="#{id({@ref})/title}">

is not allowed. Instead use simply:

<a href="#{idref(@ref)/title}">

9.7 Numbering

The xsl:number element is used to insert a formatted number into the result tree. The number to be inserted may be specified by an expression. The expr attribute contains a NumberExpr. The value of the NumberExpr is rounded to an integer and then converted to a string using the attributes specified in [9.7.1 Number to String Conversion Attributes]; when used with xsl:number the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree. For example, the following example numbers a sorted list:

<xsl:template match="items">
  <xsl:for-each select="item">
    <xsl:sort select="."/>
    <p>
      <xsl:number expr="position()" format="1. "/>
      <xsl:value-of select="."/>
    </p>
  </xsl:for-each>
</xsl:template>

If no expr attribute is specified, then the xsl:number element inserts a number based on the position of the current node in the source tree. The following attributes control how the current node is to be numbered:

In addition the xsl:number element has the attributes specified in [9.7.1 Number to String Conversion Attributes] for number to string conversion.

The xsl:number element first constructs a list of positive integers using the level, count and from attributes:

The list of numbers is then converted into a string using the attributes specified in [9.7.1 Number to String Conversion Attributes]; when used with xsl:number the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree.

Ed. Note: Allowing them to be attribute value templates isn't consistent with the current DTD: the declared values would all have to be CDATA, and we couldn't use xml:lang because the XML spec doesn't allow the value to be expressed as a template.

The following would number the items in an ordered list:

<xsl:template match="ol/item">
  <fo:block>
    <xsl:number/><xsl:text>. </xsl:text><xsl:apply-templates/>
  </fo:block>
<xsl:template>

The following two rules would number title elements. This is intended for a document that contains a sequence of chapters followed by a sequence of appendices, where both chapters and appendices contain sections which in turn contain subsections. Chapters are numbered 1, 2, 3; appendices are numbered A, B, C; sections in chapters are numbered 1.1, 1.2, 1.3; sections in appendices are numbered A.1, A.2, A.3.

<xsl:template match="title">
  <fo:block>
     <xsl:number level="multi"
                 count="chapter|section|subsection"
                 format="1.1. "/>
     <xsl:apply-templates/>
  </fo:block>
</xsl:template>

<xsl:template match="appendix//title" priority="1">
  <fo:block>
     <xsl:number level="multi"
                 count="appendix|section|subsection"
                 format="A.1. "/>
     <xsl:apply-templates/>
  </fo:block>
</xsl:template>

The following example numbers notes sequentially within a chapter:

<xsl:template match="note">
  <fo:block>
     <xsl:number level="any" from="chapter" format="(1) "/>
     <xsl:apply-templates/>
  </fo:block>
</xsl:template>

The following example would number H4 elements in HTML with a three-part label:

<xsl:template match="H4">
 <fo:block>
   <xsl:number level="any" from="H1" count="H2"/>
   <xsl:text>.</xsl:text>
   <xsl:number level="any" from="H2" count="H3"/>
   <xsl:text>.</xsl:text>
   <xsl:number level="any" from="H3" count="H4"/>
   <xsl:text> </xsl:text>
   <xsl:apply-templates/>
 </fo:block>
</xsl:template>

9.7.1 Number to String Conversion Attributes

The following attributes are used to control conversion of a list of numbers into a string. The numbers are integers greater than 0. The attributes are all optional.

The main attribute is format. The default value for the format attribute is 1. The format attribute is split into a sequence of tokens where each token is a maximal sequence of alphanumeric characters or a maximal sequence of non-alphanumeric characters. Alphanumeric means any character that has a Unicode category of Nd, Nl, No, Lu, Ll, Lt, Lm or Lo. The alphanumeric tokens (format tokens) specify the format to be used for each number in the list. If the first token is a non-alphanumeric token, then the constructed string will start with that token; if the last token is non-alphanumeric token, then the constructed string will end with that token. Non-alphanumeric tokens that occur between two format tokens are separator tokens that are used to join numbers in the list. The n-th format token will be used to format the n-th number in the list. If there are more numbers than format tokens, then the last format token will be used to format remaining numbers. If there are no format tokens, then a format token of 1 is used to format all numbers. The format token specifies the string to be used to represent the number 1. Each number after the first will be separated from the preceding number by the separator token preceding the format token used to format that number, or, if there are no separator tokens, then by ..

Format tokens are a superset of the allowed values for the type attribute for the OL element in HTML 4.0 and are interpreted as follows:

When numbering with an alphabetic sequence, the xml:lang attribute specifies which language's alphabet is to be used.

NOTE: This can be considered as specifying the language of the value of the format attribute and hence is consistent with the semantics of xml:lang.

The letter-value attribute disambiguates between numbering schemes that use letters. In many languages there are two commonly used numbering schemes that use letters. One numbering scheme assigns numeric values to letters in alphabetic sequence, and the other assigns numeric values to each letter in some other manner. In English, these would correspond to the numbering sequences specified by the format tokens a and i. In some languages the first member of each sequence is the same, and so the format token alone would be ambiguous. A value of alphabetic specifies the alphabetic sequence; a value of other specifies the other sequence.

The digit-group-sep attribute gives the separator between groups of digits, and the optional n-digits-per-group specifies the number of digits per group. For example, digit-group-sep="," and n-digits-per-group="3" would produce numbers of the form 1,000,000.

The sequence-src attribute gives the URI of a text resource that contains a whitespace separated list of the members of the numbering sequence.

Ed. Note: Specify what should happen when the sequence runs out.

Here are some examples of conversion specifications:

10. Repetition

When the result has a known regular structure, it is useful to be able to specify directly the template for selected nodes. The xsl:for-each instruction contains a template which is instantiated for each node selected by the NodeSetExpr specified by the select attribute, which is required. The template is instantiated with the selected node as the current node, and with a list of all of the selected nodes as the current node list. The nodes are processed in document order, unless a sorting specification is present (see [12 Sorting]).

For example, given an XML document with this structure

<customers>
  <customer>
    <name>...</name>
    <order>...</order>
    <order>...</order>
  </customer>
  <customer>
    <name>...</name>
    <order>...</order>
    <order>...</order>
  </customer>
</customers>

the following would create an HTML document containing a table with a row for each customer element

<xsl:template match="/">
  <HTML>
    <HEAD>
      <TITLE>Customers</TITLE>
    </HEAD>
    <BODY>
      <TABLE>
	<TBODY>
	  <xsl:for-each select="customers/customer">
	    <TR>
	      <TH>
		<xsl:apply-templates select="name"/>
	      </TH>
	      <xsl:for-each select="order">
		<TD>
		  <xsl:apply-templates/>
		</TD>
	      </xsl:for-each>
	    </TR>
	  </xsl:for-each>
	</TBODY>
      </TABLE>
    </BODY>
  </HTML>
</xsl:template>

11. Conditional Processing

There are two instructions in XSLT which support conditional processing in a template: xsl:if and xsl:choose. The xsl:if instruction provides simple if-then conditionality; the xsl:choose instruction supports selection of one choice when there are several possibilities.

11.1 Conditional Processing with xsl:if

The xsl:if element has a single attribute, test which specifies a BooleanExpr. The content is a template. If the expression evaluates to true, then the content is instantiated; otherwise nothing is created. In the following example, the names in a group of names are formatted as a comma separated list:

<xsl:template match="namelist/name">
  <xsl:apply-templates/>
  <xsl:if test="not(position()=last())">, </xsl:if>
</xsl:template>

The following colors every other table row yellow:

<xsl:template match="item">
  <tr>
    <xsl:if test="position() mod 2 = 0">
       <xsl:attribute name="bgcolor">yellow</xsl:attribute>
    </xsl:if>
    <xsl:apply-templates/>
  </tr>
</xsl:template>

11.2 Conditional Processing with xsl:choose

The xsl:choose element selects one among a number of possible alternatives. It consists of a series of xsl:when elements followed by an optional xsl:otherwise element. Each xsl:when element has a single attribute, test, which specifies a BooleanExpr. The content of the xsl:when and xsl:otherwise elements is a template. When an xsl:choose element is processed, each of the xsl:when elements is tested in turn. The content of the first, and only the first, xsl:when element whose test is true is instantiated. If no xsl:when is true, the content of the xsl:otherwise element is instantiated. If no xsl:when element is true, and no xsl:otherwise element is present, nothing is created.

The following example enumerates items in an ordered list using arabic numerals, letters, or roman numerals depending on the depth to which the ordered lists are nested.

<xsl:template match="orderedlist/listitem">
  <fo:list-item indent-start='2pi'>
    <fo:list-item-label>
      <xsl:variable name="level"
                    expr="size(from-ancestors(orderedlist)) mod 3"/>
      <xsl:choose>
        <xsl:when test='$level=1'>
          <xsl:number format="i"/>
        </xsl:when>
        <xsl:when test='$level=2'>
          <xsl:number format="a"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:number format="1"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>. </xsl:text>
    </fo:list-item-label>
    <fo:list-item-body>
      <xsl:apply-templates/>
    </fo:list-item-body>
  </fo:list-item>
</xsl:template>

12. Sorting

Sorting is specified by adding xsl:sort elements as children of xsl:apply-templates or xsl:for-each. The first xsl:sort child specifies the primary sort key, the second xsl:sort child specifies the secondary sort key and so on. When xsl:apply-templates or xsl:for-each has one or more xsl:sort children, then instead of processing the selected elements in document order, it sorts the elements according to the specified sort keys and then processes them in sorted order. When used in xsl:for-each, xsl:sort elements must occur first.

Ed. Note: Say that the current node list is in sorted order.

xsl:sort has a select attribute whose value is a StringExpr. For each node to be processed, the StringExpr is evaluated with that node as the current node. The string that results from evaluating the expression is used as the sort key for that node. The default value of the select attribute is ., which, as a StringExpr, returns the value of the current node.

This string serves as a sort key for the node. The following optional attributes on xsl:sort control how the list of sort keys are sorted:

Ed. Note: We plan also to add an attribute whose value is a label identifying the sorting scheme, to be specified by the I18N WG.

The values of all of the above attributes are interpreted as attribute value templates.

NOTE: It is recommended that implementors consult [UNICODE TR10] for information on internationalized sorting.

The sort must be stable: in the sorted list of nodes, any sublist that has sort keys that all compare equal must be in document order.

For example, suppose an employee database has the form

<employees>
  <employee>
    <name>
      <first>James</first>
      <last>Clark</last>
    </name>
    ...
  </employee>
</employees>

Then a list of employees sorted by name could be generated using:

<xsl:template match="employees">
  <ul>
    <xsl:apply-templates select="employee">
      <xsl:sort select="name/last"/>
      <xsl:sort select="name/first"/>
    </xsl:apply-templates>
  </ul>
</xsl:template>

<xsl:template match="employee">
  <li>
    <xsl:value-of select="name/first"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="name/last"/>
  </li>
</xsl:template>

13. Variables and Parameters

A variable is a name that may be bound to a value. The value to which a variable is bound (the value of the variable) can be an object of any of the types that can be returned by expressions. There are two elements that can be used to bind variables: xsl:variable and xsl:param-variable. The difference is that the value specified on the xsl:param-variable variable is only a default value for the binding; when the template or stylesheet within which the xsl:param-variable element occurs is invoked, parameters may be passed that are used in place of the default values.

For any use of these variable binding elements, there is a region of the stylesheet tree within which the binding is visible; within this region any binding of the variable that was visible on the variable binding element itself is hidden. Thus only the innermost binding of a variable is visible. The set of variable bindings in scope for an expression consists of those bindings that are visible at the point in the stylesheet where the expression occurs.

A variable binding element can specify the value of the variable in two ways. It can have a expr attribute whose value is an expression, which is evaluated to give the value of the variable. If there is no expr attribute, then the contents of the variable binding element specifies the value. The contents is a template which is instantiated to give the value. In this case the value is a result tree fragment.

Both xsl:variable and xsl:param-variable are allowed at the top-level. A top-level variable binding element declares a global variable that is visible everywhere. A top-level xsl:param-variable element declares a parameter to the stylesheet; XSLT does not define the mechanism by which parameters are passed to the stylesheet. It is an error if a stylesheet contains more than one binding of a top-level variable the same name and same importance. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the bindings with highest importance the one that occurs last in the stylesheet. At the top-level, the expression or template specifying the variable value is evaluated with the same context as that used to process the root node of the source document: the current node is the root node of the source document and the current node list is a list containing just the root node of the source document. If the template or expression specifying the value of a global variable x references a global variable y, then the value for y must be computed before the value of x. It is an error if it is impossible to do this for all global variable definitions, in other words it is an error if the definitions are circular.

This example declares a global variable para-font-size which it references in an attribute value template.

<xsl:variable name="para-font-size">12pt</xsl:variable>

<xsl:template match="para">
 <fo:block font-size="{$para-font-size}">
   <xsl:apply-templates/>
 </fo:block>
</xsl:template>

As well as being allowed at the top-level, both xsl:variable and xsl:param-variable are also allowed in templates. xsl:variable is allowed anywhere within a template that an instruction is allowed. In this case the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:variable element itself. xsl:param-variable is allowed as a child at the beginning of an xsl:template element. In this context, the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:param-variable element itself.

Parameters are passed to templates using the xsl:param element. The required name attribute specifies the name of the parameter (the variable the value of whose binding is to be replaced). xsl:param is allowed within both xsl:call-template and xsl:apply-templates. The value of the parameter is specified in the same way as for xsl:variable and xsl:param-variable. The current node and current node list used for computing the value specified by xsl:param element is the same as that used for the xsl:apply-templates or xsl:call-template element within which it occurs. It is not an error to pass a parameter x to a template that does not have a xsl:param-variable element for x; the parameter is simply ignored.

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

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

<xsl:template match="appendix/title">
  <xsl:call-template name="numbered-block">
    <xsl:param name="format">A. </xsl:param>
  </xsl:call-template>
</xsl:template>

14. Messages

The xsl:message instruction sends a message in a way that is dependent on the XSLT processor. The content of the xsl:message instruction is a template. The xsl:message is instantiated by instantiating the content to create an XML fragment. This XML fragment is the content of the message.

NOTE: An XSLT processor might implement xsl:message by popping up an alert box or by writing to a log file.

15. Combining Stylesheets

XSLT provides two mechanisms to combine stylesheets:

15.1 Stylesheet Import

An XSLT stylesheet may contain xsl:import elements. All the xsl:import elements must occur at the beginning of the stylesheet. The xsl:import element has an href attribute whose value is the URI of a stylesheet to be imported. A relative URI is resolved relative to the base URI of the xsl:import element (see [4.2.2 Base URI]).

Ed. Note: Say what importing a stylesheet means.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
  <xsl:import href="article.xsl"/>
  <xsl:import href="bigfont.xsl"/>
  <xsl:attribute-set name="note-style">
    <xsl:attribute name="font-style">italic</xsl:attribute>
  </xsl:attribute-set>
</xsl:stylesheet>

Definitions and template rules in the importing stylesheet are defined to be more important than definitions and template rules in any imported stylesheets. Also definitions and template rules in one imported stylesheet are defined to be more important than definitions and template rules in previous imported stylesheets.

In general a more important definition or template rule takes precedence over a less important definition or template rule. This is defined in detail for each kind of definition and for template rules.

Ed. Note: Say something about the case where the same stylesheet gets imported twice. This should be treated the same as importing a stylesheet with the same content but different URIs. What about import loops?

xsl:apply-imports processes the current node using only template rules that were imported into the stylesheet containing the current rule; the node is processed in the current rule's mode.

Ed. Note: Expand this.

15.2 Stylesheet Inclusion

An XSLT stylesheet may include another XSLT stylesheet using an xsl:include element. The xsl:include element has an href attribute whose value is the URI of a stylesheet to be included. A relative URI is resolved relative to the base URI of the xsl:include element (see [4.2.2 Base URI]). The xsl:include element can occur as the child of the xsl:stylesheet element at any point after all xsl:import elements.

The inclusion works at the XML tree level. The resource located by the href attribute value is parsed as an XML document, and the children of the xsl:stylesheet element in this document replace the xsl:include element in the including document. Also any xsl:import elements in the included document are moved up in the including document to after any existing xsl:import elements in the including document. Unlike with xsl:import, the fact that rules or definitions are included does not affect the way they are processed.

Ed. Note: What happens when a stylesheet directly or indirectly includes itself?

15.3 Embedding Stylesheets

Normally an XSLT stylesheet is a complete XML document with the xsl:stylesheet element as the document element. However an XSLT stylesheet may also be embedded in another resource. Two forms of embedding are possible:

In the second case, the possibility arises of documents with inline style, that is documents that specify their own style. XSLT does not define a specific mechanism for this. This is because this can be done by means of a general purpose mechanism for associating stylesheets with documents provided that:

It is not in the scope of XSLT to define such a mechanism.

NOTE: This is because the mechanism should be independent of any one stylesheet mechanism.

The xsl:stylesheet element may have an ID attribute that specifies a unique identifier.

NOTE: In order for such an attribute to be used with the id XPointer location term, it must actually be declared in the DTD as being an ID.

The following example shows how inline style can be accomplished using the xml-stylesheet processing instruction mechanism for associating a stylesheet with an XML document. The URI uses an XPointer in a fragment identifier to locate the xsl:stylesheet element.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="#id(style1)"?>
<!DOCTYPE doc SYSTEM "doc.dtd">
<doc>
<head>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" id="style1">
<xsl:import href="doc.xsl"/>
<xsl:template match="id(foo)">
 <fo:block font-weight="bold"><xsl:apply-templates/></fo:block>
</xsl:template>
</xsl:stylesheet>
</head>
<body>
<para id="foo">
...
</para>
</body>
</doc>
NOTE: The type pseudo-attribute in the xml-stylesheet processing instruction identifies the stylesheet language, not the content type of the resource of which the stylesheet is a part.

A. DTD Fragment for XSLT Stylesheets

The following entity can be used to construct a DTD for XSLT stylesheets that create instances of a particular result DTD. Before referencing the entity, the stylesheet DTD must define a result-elements parameter entity listing the allowed result element types. For example:

<!ENTITY % result-elements "
  | fo:inline-sequence
  | fo:block
">

The use of the xsl: prefix in this DTD does not imply that XSLT stylesheets are required to use this prefix. Any of the elements declared in this DTD may have attributes whose name starts with xmlns: or is equal to xmlns in addition to the attributes declared in this DTD.

<!ENTITY % char-instructions "
  | xsl:apply-templates
  | xsl:call-template
  | xsl:apply-imports
  | xsl:for-each
  | xsl:value-of
  | xsl:copy-of
  | xsl:number
  | xsl:choose
  | xsl:if
  | xsl:text
  | xsl:copy
  | xsl:variable
  | xsl:message
">

<!ENTITY % instructions "
  %char-instructions;
  | xsl:pi
  | xsl:comment
  | xsl:element
  | xsl:attribute
  | xsl:use
">

<!ENTITY % char-template "
 (#PCDATA
  %char-instructions;)*
">

<!ENTITY % template "
 (#PCDATA
  %instructions;
  %result-elements;)*
">

<!-- Used for attribute values that are URIs.-->
<!ENTITY % URI "CDATA">

<!-- Used for attribute values that are patterns.-->
<!ENTITY % pattern "CDATA">

<!-- Used for attribute values that are expressions.-->
<!ENTITY % expr "CDATA">

<!-- Used for an attribute value that consists of a single character.-->
<!ENTITY % char "CDATA">

<!-- Used for attribute values that are a priority. -->
<!ENTITY % priority "NMTOKEN">

<!ENTITY % space-att "xml:space (default|preserve) #IMPLIED">

<!ENTITY % top-level "
 (xsl:import*,
  (xsl:include
  | xsl:strip-space
  | xsl:preserve-space
  | xsl:key
  | xsl:functions
  | xsl:locale
  | xsl:attribute-set
  | xsl:variable
  | xsl:param-variable
  | xsl:template)*)
">

<!ELEMENT xsl:stylesheet %top-level;>
<!ELEMENT xsl:transform %top-level;>

<!ATTLIST xsl:stylesheet
  result-ns NMTOKEN #IMPLIED
  default-space (preserve|strip) "preserve"
  indent-result (yes|no) "no"
  id ID #IMPLIED
  xmlns:xsl CDATA #FIXED "http://www.w3.org/XSL/Transform/1.0"
  %space-att;
>

<!ELEMENT xsl:import EMPTY>
<!ATTLIST xsl:import href %URI; #REQUIRED>

<!ELEMENT xsl:include EMPTY>
<!ATTLIST xsl:include href %URI; #REQUIRED>

<!ELEMENT xsl:strip-space EMPTY>
<!ATTLIST xsl:strip-space elements NMTOKENS #REQUIRED>

<!ELEMENT xsl:preserve-space EMPTY>
<!ATTLIST xsl:preserve-space elements NMTOKENS #REQUIRED>

<!ELEMENT xsl:key EMPTY>
<!ATTLIST xsl:key
  name NMTOKEN #REQUIRED
  match %pattern; #REQUIRED
  use %expr; #REQUIRED
>

<!ELEMENT xsl:functions (#PCDATA)>
<!ATTLIST xsl:functions
  ns NMTOKEN #REQUIRED
  code CDATA #IMPLIED
  archive CDATA #IMPLIED
>

<!ELEMENT xsl:locale EMPTY>
<!ATTLIST xsl:locale
  name NMTOKEN #IMPLIED
  decimal-separator %char; "."
  grouping-separator %char; ","
  infinity CDATA "&#x221E;"
  minus-sign %char; "-"
  NaN CDATA "&#xFFFD;"
  percent %char; "%"
  per-mill %char; "&#x2030;"
  zero-digit %char; "0"
  digit %char; "#"
  pattern-separator %char; ";"
>

<!ELEMENT xsl:template
 (#PCDATA
  %instructions;
  %result-elements;
  | xsl:param-variable)*
>

<!ATTLIST xsl:template
  match %pattern; #IMPLIED
  name NMTOKEN #IMPLIED
  priority %priority; #IMPLIED
  mode NMTOKEN #IMPLIED
  %space-att;
>

<!ELEMENT xsl:value-of EMPTY>
<!ATTLIST xsl:value-of
  select %expr; #REQUIRED
>

<!ELEMENT xsl:copy-of EMPTY>
<!ATTLIST xsl:copy-of select %expr; #REQUIRED>

<!ELEMENT xsl:number EMPTY>
<!ATTLIST xsl:number
   level (single|multi|any) "single"
   count CDATA #IMPLIED
   from CDATA #IMPLIED
   expr %expr; #IMPLIED
   format CDATA '1'
   xml:lang NMTOKEN #IMPLIED
   letter-value (alphabetic|other) #IMPLIED
   digit-group-sep CDATA #IMPLIED
   n-digits-per-group NMTOKEN #IMPLIED
   sequence-src %URI; #IMPLIED
>

<!ELEMENT xsl:apply-templates (xsl:sort|xsl:param)*>
<!ATTLIST xsl:apply-templates
  select %expr; "node()"
  mode NMTOKEN #IMPLIED
>

<!ELEMENT xsl:apply-imports EMPTY>

<!-- xsl:sort cannot occur after any other elements or
any non-whitespace character -->

<!ELEMENT xsl:for-each
 (#PCDATA
  %instructions;
  %result-elements;
  | xsl:sort)*
>

<!ATTLIST xsl:for-each
  select %expr; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:sort EMPTY>
<!ATTLIST xsl:sort
  select %expr; "."
  lang CDATA #IMPLIED
  data-type (text|number) "text"
  order (ascending|descending) "ascending"
  case-order (upper-first|lower-first) #IMPLIED
>

<!ELEMENT xsl:if %template;>
<!ATTLIST xsl:if
  test %expr; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:choose (xsl:when+, xsl:otherwise?)>
<!ATTLIST xsl:choose %space-att;>

<!ELEMENT xsl:when %template;>
<!ATTLIST xsl:when
  test %expr; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:otherwise %template;>
<!ATTLIST xsl:otherwise %space-att;>

<!ELEMENT xsl:attribute-set (xsl:attribute|xsl:use)*>
<!ATTLIST xsl:attribute-set
  name NMTOKEN #REQUIRED
>

<!ELEMENT xsl:call-template (xsl:param)*>
<!ATTLIST xsl:call-template
  name NMTOKEN #REQUIRED
>

<!ELEMENT xsl:param %template;>
<!ATTLIST xsl:param
  name NMTOKEN #REQUIRED
  expr %expr; #IMPLIED
>

<!ELEMENT xsl:variable %template;>
<!ATTLIST xsl:variable 
  name NMTOKEN #REQUIRED
  expr %expr; #IMPLIED
>

<!ELEMENT xsl:param-variable %template;>
<!ATTLIST xsl:param-variable 
  name NMTOKEN #REQUIRED
  expr %expr; #IMPLIED
>

<!ELEMENT xsl:text (#PCDATA)>

<!ELEMENT xsl:pi %char-template;>
<!ATTLIST xsl:pi 
  name CDATA #REQUIRED
  %space-att;
>

<!ELEMENT xsl:element %template;>
<!ATTLIST xsl:element 
  name CDATA #REQUIRED
  namespace CDATA #IMPLIED
  %space-att;
>

<!ELEMENT xsl:attribute %char-template;>
<!ATTLIST xsl:attribute 
  name CDATA #REQUIRED
  namespace CDATA #IMPLIED
  %space-att;
>

<!ELEMENT xsl:use EMPTY>
<!ATTLIST xsl:use attribute-set NMTOKEN #REQUIRED>

<!ELEMENT xsl:comment %char-template;>
<!ATTLIST xsl:comment %space-att;>

<!ELEMENT xsl:copy %template;>
<!ATTLIST xsl:copy %space-att;>

<!ELEMENT xsl:message %template;>
<!ATTLIST xsl:message %space-att;>

B. References

B.1 Normative References

XML
World Wide Web Consortium. Extensible Markup Language (XML) 1.0. W3C Recommendation. See http://www.w3.org/TR/1998/REC-xml-19980210
XML Names
World Wide Web Consortium. Namespaces in XML. W3C Recommendation. See http://www.w3.org/TR/REC-xml-names

B.2 Other References

CSS2
World Wide Web Consortium. Cascading Style Sheets, level 2 (CSS2). W3C Recommendation. See http://www.w3.org/TR/1998/REC-CSS2-19980512
DSSSL
International Organization for Standardization, International Electrotechnical Commission. ISO/IEC 10179:1996. Document Style Semantics and Specification Language (DSSSL). International Standard.
UNICODE TR10
Unicode Consortium. Draft Unicode Technical Report #10. Unicode Collation Algorithm. Draft Unicode Technical Report. See http://www.unicode.org/unicode/reports/tr10/index.html
.
XHTML
World Wide Web Consortium. XHTML 1.0: The Extensible HyperText Markup Language. W3C Working Draft. See http://www.w3.org/TR/WD-html-in-xml
XPointer
World Wide Web Consortium. XML Pointer Language (XPointer). W3C Working Draft. See http://www.w3.org/TR/WD-xptr
XML Stylesheet
World Wide Web Consortium. Associating stylesheets with XML documents. W3C Working Draft. See http://www.w3.org/TR/WD-xml-stylesheet
XSL
World Wide Web Consortium. Extensible Stylesheet Language (XSL). W3C Working Draft. See http://www.w3.org/TR/WD-xsl

C. Examples

C.1 Formatting Objects Example

The following is a simple but complete stylesheet.

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
                xmlns:fo="http://www.w3.org/XSL/Format/1.0"
                result-ns="fo"
                indent-result="yes">
<xsl:template match='/'>
 <fo:basic-page-sequence font-family="serif">
  <fo:simple-page-master page-master-name='scrolling'/>
  <fo:queue queue-name='body'>
   <xsl:apply-templates/>
  </fo:queue>
 </fo:basic-page-sequence>
</xsl:template>

<xsl:template match="title">
 <fo:block font-weight="bold">
  <xsl:apply-templates/>
 </fo:block>
</xsl:template>

<xsl:template match="p">
 <fo:block>
  <xsl:apply-templates/>
 </fo:block>
</xsl:template>

<xsl:template match="emph">
 <fo:inline-sequence font-style="italic">
  <xsl:apply-templates/>
 </fo:inline-sequence>
</xsl:template>

</xsl:stylesheet>

With the following source document

<doc>
<title>An example</title>
<p>This is a test.</p>
<p>This is <emph>another</emph> test.</p>
</doc>

it would produce the following result

<fo:basic-page-sequence xmlns:fo="http://www.w3.org/XSL/Format/1.0"
  font-family="serif">
<fo:simple-page-master page-master-name="scrolling"/>
<fo:queue queue-name="body">
<fo:block font-weight="bold">An example</fo:block>
<fo:block>This is a test.</fo:block>
<fo:block>This is <fo:inline-sequence
  font-style="italic">another</fo:inline-sequence> test.</fo:block>
</fo:queue>
</fo:basic-page-sequence>

C.2 XHTML Example

This is an example of using XSLT to create an XHTML document (see [XHTML]). The following stylesheet:

<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
  xmlns="http://www.w3.org/Profiles/xhtml1-transitional"
  default-space="strip"
  indent-result="yes">

        <xsl:template match="/">
<html>
        <head>
                <title>Sales Results By Division</title>
        </head>

        <body>
                <table border="1">
                <tr>
                        <th>Division</th>
                        <th>Revenue</th>
                        <th>Growth</th>
                        <th>Bonus</th>
                </tr>
        <xsl:apply-templates/>
                </table>
        </body>
</html>
        </xsl:template>

        <xsl:template match="sales">
                <xsl:apply-templates match="division">
                        <!-- order the result by revenue -->
                        <xsl:sort select="revenue"
                                  data-type="number"
                                  order="descending"/>
                </xsl:apply-templates>
        </xsl:template>

        <xsl:template match="division">
                        <tr>
                        <td><em><xsl:value-of select="@id"/></em></td>
                <xsl:apply-templates select="revenue"/>
                <xsl:apply-templates select="growth"/>
                <xsl:apply-templates select="bonus"/>
                        </tr>

        </xsl:template>

        <xsl:template match="revenue | growth | bonus">
                        <td><xsl:apply-templates/></td>
        </xsl:template>
</xsl:stylesheet>

with the following input document

<?xml version="1.0"?>

<sales>

        <division id="North">
                <revenue>10</revenue>
                <growth>9</growth>
                <bonus>7</bonus>
        </division>

        <division id="South">
                <revenue>4</revenue>
                <growth>3</growth>
                <bonus>4</bonus>
        </division>

        <division id="West">
                <revenue>6</revenue>
                <growth>-1.5</growth>
                <bonus>2</bonus>
        </division>

</sales>

would produce the following result

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/Profiles/xhtml1-transitional">
  <head>
    <title>Sales Results By Division</title>
  </head>
  <body>
    <table border="1">
      <tr>
	<th>Division</th>
	<th>Revenue</th>
	<th>Growth</th>
	<th>Bonus</th>
      </tr>
      <tr>
	<td><em>North</em></td>
	<td>10</td>
	<td>9</td>
	<td>7</td>
      </tr>
      <tr>
	<td><em>West</em></td>
	<td>6</td>
	<td>-1.5</td>
	<td>2</td>
      </tr>
      <tr>
	<td><em>South</em></td>
	<td>4</td>
	<td>3</td>
	<td>4</td>
      </tr>
    </table>
  </body>
</html>

D. Acknowledgements

The following have contributed to authoring this draft:

This specification was developed and approved for publication by the W3C XSL Working Group (WG). WG approval of this specification does not necessarily imply that all WG members voted for its approval. The current members of the XSL WG are:

Sharon Adler, Inso (Co-Chair); Anders Berglund, Inso; Scott Boag, Lotus; Jeff Caruso, Bitstream; James Clark (XSLT Editor); Peter Danielsen, Bell Labs; Don Day, IBM; Stephen Deach, Adobe; Angel Diaz, IBM; Dwayne Dicks, SoftQuad; Andrew Greene, Bitstream; Paul Grosso, ArborText; Eduardo Gutentag, Sun; Mickey Kimchi, Enigma; Chris Lilley, W3C; Daniel Lipkin, Oracle; Chris Maden, O'Reilly; Jonathan Marsh, Microsoft; Alex Milowski, CommerceOne; Boris Moore, RivCom; Steve Muench, Oracle; Carolyn Pampino, Interleaf; Scott Parnell, Xerox; Vincent Quint, W3C; Gregg Reynolds, Datalogics; Jonathan Robie, Software AG; Henry Thompson, University of Edinburgh; Philip Wadler, Bell Labs; Randy Waki, Novell; Norm Walsh, ArborText; Sanjiva Weerawarana, IBM; Umit Yalcinalp, Sun; Steve Zilles, Adobe (Co-Chair)

E. Changes from Previous Public Working Draft

The following is a summary of changes since the previous public working draft.

Select patterns, string expressions and boolean expressions have been combined and generalized into an expression language with multiple data types (see [6 Expressions and Patterns]).

xsl:strip-space and xsl:preserve-space have an elements attribute which specifies a list of element types, rather than a element attribute specifying a single element type.

The id() function has been split into id() and idref().

xsl:id has been replaced by the xsl:key element (see [6.4.1 Declaring Keys]), and associated key() and keyref() functions.

The doc() and docref() have been added to support multiple source documents.

Namespace wildcards (ns:*) have been added.

ancestor() and ancestor-or-self() have been replaced by a more general facility for addressing different axes.

Positional qualifiers (first-of-type(), first-of-any(), last-of-type(), last-of-any()) have been replaced by the position() and last() functions and numeric expressions inside [].

Counters have been removed. An expr attribute has been added to xsl:number which in conjunction with the position() allows numbering of sorted node lists.

Multiple adjacent uses of [] are allowed.

Macros and templates have been unified by allowing templates to be named and have parameters.

xsl:constant have been replaced by xsl:variable which allows variables to be typed and local.

The default for priority on xsl:template has changed (see [7.4 Conflict Resolution for Template Rules]).

An extension mechanism has been added (see [6.4.2 Declaring Extension Functions]).

The namespace URIs have been changed.

xsl:copy-of has been added (see [9.5 Copying]).

A error recovery mechanism to allow forwards-compatibility has been added (see [3 Forwards-compatible Processing]).

A namespace attribute has been added to xsl:element and xsl:attribute.