W3C
Logo

WD-xsl-19980818


Extensible Stylesheet Language (XSL)

Version 1.0

World Wide Web Consortium Working Draft 18-August-1998

This version

http://www.w3.org/TR/1998/WD-xsl-19980818
http://www.w3.org/TR/1998/WD-xsl-19980818.xml
http://www.w3.org/TR/1998/WD-xsl-19980818.html
http://www.w3.org/TR/1998/WD-xsl-19980818.pdf

Latest version

http://www.w3.org/TR/WD-xsl

Editors

James Clark () [Tree Construction]
Stephen Deach, Adobe () [Formatting Objects]

Copyright  ©  1998 W3C (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.

Status of this document

This is a W3C Working Draft for review by W3C members and other interested parties. It is the first working draft of XSL. It is based on the XSL Submission, but differs substantially in many important respects. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. 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.

Comments may be sent to xsl-editors@w3.org. Public discussion of XSL takes place on the XSL-List mailing list.

Abstract

XSL is a language for expressing stylesheets. It consists of two parts:

  1. a language for transforming XML documents, and

  2. an XML vocabulary for specifying formatting semantics.

An XSL stylesheet specifies the presentation of a class of XML documents by describing how an instance of the class is transformed into an XML document that uses the formatting vocabulary.

Table of Contents

1. Overview
2. Tree Construction
2.1 Overview
2.2 Stylesheet Structure
2.3 Processing Model
2.4 Data Model
2.4.1 Root Node
2.4.2 Element Nodes
2.4.3 Attribute Nodes
2.4.4 Character Data
2.4.5 Whitespace Stripping
2.5 Template Rules
2.5.1 Conflict Resolution for Template Rules
2.5.2 Built-in Template Rule
2.6 Patterns
2.6.1 Alternative Patterns
2.6.2 Matching on Element Ancestry
2.6.3 Anchors
2.6.4 Matching the Root Node
2.6.5 Matching on Element Types
2.6.6 Qualifiers
2.6.7 Matching on Children
2.6.8 Matching on Attributes
2.6.9 Matching on Position
2.6.10 Whitespace in Patterns
2.6.11 Specificity
2.7 Templates
2.7.1 Overview
2.7.2 Literal Result Elements
2.7.3 Named Attribute Sets
2.7.4 Literal Text in Templates
2.7.5 Processing with xsl:process-children
2.7.6 Processing with xsl:process
2.7.7 Direct Processing
2.7.8 Numbering in the Source Tree
2.7.9 Number to String Conversion Attributes
2.7.10 Conditionals within a Template
2.7.11 Computing Generated Text
2.7.12 String Constants
2.7.13 Macros
2.8 Style Rules
2.9 Combining Stylesheets
2.9.1 Stylesheet Import
2.9.2 Stylesheet Inclusion
2.9.3 Embedding Stylesheets
2.10 Extensibility
3. Formatting Objects
3.1 Introduction
3.2 Notations Used in this Section
3.3 Formatting Objects and Their Properties
3.4 Formatting Objects to be Defined in Subsequent Drafts
3.5 Page-sequence Layout Object
3.5.1 Purpose
3.5.2 Formatting Object Summary
3.5.3 Formatting Object's Formal Specification
3.5.4 To Resolve
3.6 Simple-page-master Layout Object
3.6.1 Purpose
3.6.2 Formatting Object Summary
3.6.3 Formatting Object's Formal Specification
3.6.4 To Resolve
3.7 Queue Flow Object
3.7.1 Purpose
3.7.2 Formatting Object Summary
3.7.3 Formatting Object's Formal Specification
3.8 Sequence Flow Object
3.8.1 Purpose
3.8.2 Formatting Object Summary
3.8.3 Formatting Object's Formal Specification
3.9 Block Flow Object
3.9.1 Purpose
3.9.2 Formatting Object Summary
3.9.3 Formatting Object's Formal Specification
3.9.4 To Resolve
3.10 Character Flow Object
3.10.1 Purpose
3.10.2 Formatting Object Summary
3.10.3 Formatting Object's Formal Specification
3.10.4 To Resolve
3.11 List Flow Object
3.11.1 Purpose
3.11.2 Formatting Object Summary
3.11.3 Formatting Object's Formal Specification
3.12 List-Item Flow Object
3.12.1 Purpose
3.12.2 Formatting Object Summary
3.12.3 Formatting Object's Formal Specification
3.13 List-Item-Label Flow Object
3.13.1 Purpose
3.13.2 Formatting Object Summary
3.13.3 Formatting Object's Formal Specification
3.14 List-Item-Body Flow Object
3.14.1 Purpose
3.14.2 Formatting Object Summary
3.14.3 Formatting Object's Formal Specification
3.15 Rule-Graphic Flow Object
3.15.1 Purpose
3.15.2 Formatting Object Summary
3.15.3 Formatting Object's Formal Specification
3.15.4 To Resolve
3.16 Graphic Flow Object
3.16.1 Purpose
3.16.2 Formatting Object Summary
3.16.3 Formatting Object's Formal Specification
3.16.4 To Resolve
3.17 Score Flow Object
3.17.1 Purpose
3.17.2 Formatting Object Summary
3.17.3 Formatting Object's Formal Specification
3.17.4 To Resolve
3.18 Inline-box Flow Object
3.18.1 Purpose
3.18.2 Formatting Object Summary
3.18.3 Formatting Object's Formal Specification
3.18.4 To Resolve
3.19 Block-level-box Flow Object
3.19.1 Purpose
3.19.2 Formatting Object Summary
3.19.3 Formatting Object's Formal Specification
3.19.4 To Resolve
3.20 Page-number Flow Object
3.20.1 Purpose
3.20.2 Formatting Object Summary
3.20.3 Formatting Object's Formal Specification
3.20.4 To Resolve
3.21 Link Formatting Object
3.21.1 Purpose
3.21.2 Formatting Object Summary
3.21.3 Formatting Object's Formal Specification
3.22 Link-end-locator Formatting Object
3.22.1 Purpose
3.22.2 Formatting Object Summary
3.22.3 Formatting Object's Formal Specification
3.23 Defined Terms
3.24 Alphabetical Summary of Properties

Appendices

A. DTD for XSL Stylesheets
B. References
B.1 Normative References
B.2 Other References
C. Examples (Non-Normative)
D. Design Principles (Non-Normative)
E. Acknowledgements (Non-Normative)

1. Overview

XSL is a language for expressing stylesheets. Each stylesheet describes rules for presenting a class of XML source documents. There are two parts to the presentation process. First, the result tree is constructed from the source tree. Second, the result tree is interpreted to produce formatted output on a display, on paper, in speech or onto other media.

The first part, constructing the result tree, 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, the source tree can be filtered and reordered, and arbitrary structure can be added.

The second part, formatting, is achieved by using the formatting vocabulary specified in this document to construct the result tree. Formally, this vocabulary is an XML namespace. Each element type in the vocabulary corresponds to a formatting object class. A formatting object class represents a particular kind of formatting behavior. For example, the block formatting object class represents the breaking of the content of a paragraph into lines. Each attribute in the vocabulary corresponds to a formatting property. A formatting object class has a specific set of formatting properties which provide finer control over the behavior of the formatting object class; for example, controlling indenting of lines, spacing between lines, and spacing before and after the collection of lines. A formatting object can have content, and its formatting behavior is applied to its content.

XSL does not require result trees to use the formatting vocabulary and thus can be used for general XML transformations. For example, XSL can be used to transform XML to "well-formed" HTML, that is, XML that uses the element types and attributes defined by HTML.

When the result tree uses the formatting vocabulary, a conforming XSL implementation must be able to interpret the result tree according to the semantics of the formatting vocabulary as defined in this document; it may also be able to externalize the result tree as XML, but it is not required to be able to do so.

2. Tree Construction

2.1 Overview

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 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 Section 2.5.1: Conflict Resolution for Template Rules.

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

An XSL stylesheet contains an xsl:stylesheet document element. This element may contain xsl:template elements specifying template rules, which will be described later in this document.

The following is an example of a simple XSL stylesheet that constructs a result tree for a sequence of para elements containing emphasis elements. The result-ns="fo" attribute indicates that a tree using the formatting object vocabulary is being constructed. The rule for the root node specifies the use of a page sequence formatted with any font with serifs. The para elements become block formatting objects which are set in 10 point type with a 12 point space before each block.

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/TR/WD-xsl"
  xmlns:fo="http://www.w3.org/TR/WD-xsl/FO"
  result-ns="fo">
  <xsl:template match="/">
    <fo:page-sequence font-family="serif">
       <xsl:process-children/>
    </fo:page-sequence>
  </xsl:template>
  
  <xsl:template match="para">
    <fo:block font-size="10pt" space-before="12pt">
      <xsl:process-children/>
    </fo:block>
  </xsl:template>
</xsl:stylesheet>

The xsl:stylesheet element can also contain elements importing other XSL stylesheets, elements defining macros, elements defining global constants, and elements identifying source attributes as individual element identifiers.

2.2 Stylesheet Structure

A stylesheet is represented by an xsl:stylesheet element in an XML document.

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

Issue (versioning): Should there be some way for a stylesheet to indicate which version of XSL it conforms to? Can this be done through the URI of the XSL namespace?

The xsl:stylesheet element has an optional result-ns attribute; the value must be a namespace prefix. If this attribute is specified, all result elements must belong to the namespace identified by this prefix. If there is a namespace declared as the default namespace, then an empty string may be used as the value to specify that all result elements belong to that namespace. If the result-ns attribute specifies the XSL Formatting Objects namespace, then in addition to constructing the result XML tree, the XSL processor must interpret it according to the semantics defined in this document. The XSL Formatting Objects namespace has the URI http://www.w3.org/TR/WD-xsl/FO. The examples in this document use the fo: prefix for this namespace.

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

  1. xsl:import

  2. xsl:include

  3. xsl:id

  4. xsl:strip-space

  5. xsl:preserve-space

  6. xsl:define-macro

  7. xsl:define-attribute-set

  8. xsl:define-constant

  9. xsl:template

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/TR/WD-xsl">
  <xsl:import href="..."/>

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

  <xsl:id attribute="..."/>

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

  <xsl:define-macro name="...">
   ...
  </xsl:define-macro>

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

  <xsl:define-constant name="..." value="..."/>

  <xsl:template match="...">
    ...
  </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.

Issue (media-rule): Should we provide the functionality of CSS's @media rule and if so how?

2.3 Processing Model

Ed. Note: This needs expanding and polishing.

A node is processed to create a result tree fragment. The result tree is constructed by processing the root node. 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. A template typically contains instructions that select an additional sequence of source nodes for processing. A sequence of source nodes is processed by appending the result tree structure created by processing each of the members of the sequence in order. 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.

2.4 Data Model

XSL 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 XSL. This section describes how XSL models an XML document as a tree. This model is conceptual only and does not mandate any particular implementation.

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

The tree contains nodes and character data. There are three kinds of node:

Issue (node-types): We need to support at least processing instructions and comments, possibly other node types as well. Support requires having patterns that match/select them, being able to get at their contents, and being able to create them. How should this work?

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

2.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 (see [W3C XML Names]); the URI will be null if the element type name has no prefix and there is no default namespace in scope.

An element node also has a namespace prefix map that specifies the namespace URI for each namespace prefix that is in scope for the element. The semantics of a document type may treat parts of attribute values or data content as namespace prefixes. The namespace prefix map ensures that the semantics can be preserved when the tree is written out as XML. When writing an element node out as XML, an XSL processor must add sufficient namespace-declaring attributes to the start-tag to ensure that all prefixes in the element node's namespace prefix map are correctly declared.

The children of an element node are the element nodes and characters 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 character children, the element node children, and the descendants of the element node children.

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.

2.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. Since XSL must also work with XML documents that do not have a DTD, stylesheets may specify which attributes in the source document should be treated as IDs. The xsl:id element has a required attribute attribute, which gives the name of an attribute in the source document that should be treated as specifying the element's ID. A stylesheet may contain more than one xsl:id element, for cases where the source document uses several attributes as IDs. An xsl:id element also has an optional element attribute which specifies the name of an element type; when the element attribute is specified, then the xsl:id element specifies that the attribute attribute of element elements are treated as IDs. xsl:id elements may only occur in the stylesheet body (not within a rule). The following causes XSL to treat all name attributes in the source document as IDs.

<xsl:id attribute="name"/>

It is an error if, as a consequence of the use of xsl:id, there is more than one element with the same ID in the source tree. An XSL processor may signal the error; if it does not signal the error, it must recover by treating only the first (in document order) of the elements as having that ID.

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

2.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, 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 [W3C 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 [W3C XML]. An attribute value whose value is of zero length is not treated specially.

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

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

2.4.4 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;. 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 [W3C XML].

2.4.5 Whitespace Stripping

After the tree has been constructed, but before it is otherwise processed by XSL, some whitespace characters 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 character object is preserved if any of the following apply:

  • The element type of the parent of the character is in the set of whitespace-preserving element types.

  • It is part of a chunk that contains at least one non-whitespace character. As in XML, a whitespace character is #x20, #x9, #xD or #xA. A chunk of characters is a maximal sequence of sibling characters without any intervening elements.

  • An ancestor element of the character has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.

Otherwise the character object 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:

  • If the xsl:stylesheet element specifies a default-space attribute with a value of strip, then the set is initially empty. Otherwise the set initially contains all element types that occur in the document.

  • The xsl:strip-space element causes an element type to be removed from the set of whitespace-preserving element types. The element attribute gives the name of the element type.

  • The xsl:preserve-space element causes an element type to be added to the set whitespace-preserving element types. The element attribute gives the name of the element type.

Issue (declare-multiple-elements): Should the value of the element attribute of xsl:strip-space, xsl:preserve-space and xsl:id be a list of element type names (and thus be renamed to elements)? If so, should the attribute attribute of xsl:id also be a list of attribute names?

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

The xsl:stylesheet element can include an indent-result attribute with values yes or no. If the stylesheet specifies indent-result="yes", then the XSL 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 XSL 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.

2.5 Template Rules

A template rule is specified with the xsl:template element. The match attribute identifies the source node or nodes to which the rule applies. The content of the xsl:template element is the template.

For example, an XML document might contain:

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

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

<xsl:template match="emph">
  <fo:sequence font-weight="bold">
    <xsl:process-children/>
  </fo:sequence>
</xsl:template>

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

2.5.1 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 are less specific (as defined in Section 2.6.11: Specificity) than the most specific matching template rule or rules are eliminated from consideration.

  3. 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 rule is specified by the priority attribute on the rule. The value of this must be an integer (positive or negative). The default priority is 0. The integer must not be greater than 2147483647 nor less than -2147483648.

It is an error if this leaves more than one matching template rule. An XSL 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.

2.5.2 Built-in Template Rule

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:process-children/>
</xsl:template>

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

2.6 Patterns

A pattern is a string which is matched against an element in the source document. The most common pattern specifies the element type name of a matching element. For example, the pattern emph matches an element whose type is emph. More complex patterns specify the element types of ancestors of a matching element. For example, the pattern olist/item matches an element whose type is item with a parent element of type olist. Each element type in the list of ancestors may be followed by a list of "qualifiers" separated by commas. For example,

list[attribute(ordered)="yes")]/item[first-of-type()]

matches an element whose type is item, which is the first amongst its siblings of this type, and which has a parent of type list with an ordered attribute equal to yes. This section describes the syntax and semantics of patterns in detail.

A pattern that is matched against an element is known as a match pattern. Patterns in xsl:template are match patterns.

A pattern can also be used to select a list of nodes; a pattern that is used for this is known as a select pattern. In a select pattern, there is a current node which provides a context for the selection. The pattern selects the list of the source nodes that match the pattern. Nodes in the selected list are in document order. Patterns in xsl:process, xsl:for-each and xsl:value-of are select patterns.

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

Issue (pattern-text-content): Should patterns be able to match elements based on their textual content? If XSL is not to discriminate between DTDs that use attributes and those that use elements, then it needs at least a qualifier that matches an element whose pcdata content is exactly some specified string.
Issue (pattern-text-target): At the moment, the only kind of node that can match a pattern is an element. Should it be possible to have a pattern that matches text? What would this mean for the processing model?
Issue (pattern-pi-target): Should it be possible to have a pattern that matches a processing instruction?
Issue (regex): Should XSL support regular expressions for matching against any or all of pcdata content, attribute values, attribute names, element type names?

2.6.1 Alternative Patterns

A pattern may consist of a set of patterns representing ancestry separated by the | character. This indicates that an element matching any one of the ancestry patterns matches the entire pattern. Each ancestry pattern may itself have the capability of a full pattern except for the | operator.

Alternation


[1] Pattern ::= OrPattern
[2] OrPattern ::= AncestryPattern ('|' AncestryPattern)*

This example creates an fo:sequence for either emph or strong elements:

<xsl:template match="emph | strong">
  <fo:sequence font-weight="bold">
    <xsl:process-children/>
  </fo:sequence>
</xsl:template>

2.6.2 Matching on Element Ancestry

Element ancestry can be represented within the pattern by using the parent operator (/). This operator is based on the familiar directory navigation metaphor. Two patterns separated by the parent operator match an element if the right-hand side matches the element and the left-hand side matches the parent of the element.

Ancestry


[3] AncestryPattern ::= NodePatterns
      | (Anchor (AncestryOp NodePatterns)?)
      | (RootPattern NodePatterns?)
[4] NodePatterns ::= (ElementPatterns (AncestryOp AttributePattern)?)
      | AttributePattern
[5] ElementPatterns ::= ElementPattern (AncestryOp ElementPattern)*
[6] AncestryOp ::= '/' | '//'
[7] ElementPattern ::= ElementTypePattern ElementQualification?

For example, the following pattern matches title source elements that have a section element as a parent and a chapter element as a grandparent:

<xsl:template match="chapter/section/title">
  ...
</xsl:template>

While the parent operator specifies a parent-child relationship, the ancestor operator (//) specifies an ancestor-descendant relationship. Two patterns separated by the ancestor operator match an element if the right-hand side matches the element and the element has at least one ancestor that the left-hand side matches. Thus zero or more levels of hierarchy may intervene between the element matching the pattern specified on the left-hand side of the ancestor operator and the element matching the pattern specified on the right-hand side.

This example applies to changed elements which have a para element as an ancestor.

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

2.6.3 Anchors

The first component of an AncestryPattern can be an Anchor. An Anchor is a pattern that only a specific element in the source tree matches (if any elements at all match). The Anchor is said to address the specific element that matches it.

There are two kinds of anchor, relative and absolute. A relative anchor addresses an element relative to the current node. An absolute anchor addresses an element independently of any current node. A match pattern must not contain a RelativeAnchor; all anchors in a match pattern must be absolute. A select pattern may contain both kinds of anchor.

Anchors


[8] Anchor ::= AbsoluteAnchor
      | RelativeAnchor
[9] AbsoluteAnchor ::= IdAnchor
[10] RelativeAnchor ::= CurrentNodeAnchor
      | (ParentAnchor ('/' ParentAnchor)*)
      | AncestorAnchor
[11] CurrentNodeAnchor ::= '.'
[12] ParentAnchor ::= '..'

A CurrentNodeAnchor addresses the current node.

A select pattern is implicitly anchored to the current node: if an AncestryPattern in the Pattern does not start with an Anchor or a RootPattern, it is treated as if it were ./AncestryPattern. For example, a select pattern of foo will be treated as ./foo and will thus select the foo children of the current node.

A ParentAnchor addresses the parent of the current node.

2.6.3.1 Ancestor Anchors

Ancestor Anchors


[13] AncestorAnchor ::= 'ancestor' '(' Pattern ')'

An AncestorAnchor addresses the nearest ancestor of the current node that matches the specified pattern. The pattern in a AncestorAnchor is a match pattern.

2.6.3.2 Id Anchors

An IdAnchor addresses the element whose ID (see Section 2.4.2.1: Unique IDs) is the specified NCName.

Id Anchors


[14] IdAnchor ::= 'id' '(' NCName ')'

2.6.4 Matching the Root Node

A RootPattern matches the root node (see Section 2.4.1: Root Node).

Root Patterns


[15] RootPattern ::= '/'

2.6.5 Matching on Element Types

The simplest pattern consists of just an element type name. This matches any element of that type.

<xsl:template match="first-name">
  ...
</xsl:template>

The * pattern is a wildcard that matches a single element of any type. When used within an ancestry chain, the wildcard matches exactly one level of hierarchy.

Element Type Pattern


[16] ElementTypePattern ::= OneElementTypePattern
      | AnyElementTypePattern
[17] OneElementTypePattern ::= ElementTypeName
[18] ElementTypeName ::= QName
[19] AnyElementTypePattern ::= '*'

The following pattern matches any element that is an immediate child of a data-samples element.

<xsl:template match="data-samples/*">
  ...
</xsl:template>

When determining whether a source element matches an ElementTypeName, the expanded element type names are compared (see Section 2.4.2: Element Nodes).

Issue (pattern-namespace-wildcards): Should patterns of the form foo:* or *:foo be allowed? If so, should * match any element or any element without a namespace URI?

2.6.6 Qualifiers

An element within the pattern hierarchy may have qualifiers applied to it, which further constrain which elements match the term. These qualifiers may constrain the element to have certain attributes or sub-elements or may constrain its position with respect to its siblings. The qualifiers are specified in square brackets ([]) following the element type name or wildcard symbol. A pattern matches only if all of the qualifiers are satisfied.

Qualifiers


[20] ElementQualification ::= '[' Qualifiers? ']'
[21] Qualifiers ::= Qualifier (',' Qualifier)*
[22] Qualifier ::= ChildQualifier
      | AttributeQualifier
      | PositionalQualifier

This example matches author elements within book elements where the book contains at least one excerpt sub-element and the author has a degree attribute:

<xsl:template match="book[excerpt]/author[attribute(degree)]">
  ...
</xsl:template>
Issue (sibling-qual): Should there be qualifiers that constrain an element to have an immediately preceding or following sibling of a particular type?

2.6.7 Matching on Children

An element can be constrained to have a child element of a particular type by specifying the name of that type as a qualifier.

Child Qualifier


[23] ChildQualifier ::= ElementTypeName

This example has a pattern that matches author elements within book elements which also have excerpt children (the author and excerpt elements are siblings).

<xsl:template match="book[excerpt]/author">
  ...
</xsl:template>
NOTE: There is no requirement that each child qualifier is matched by a distinct element. Thus foo[bar,bar] is matched by <foo><bar/></foo>.

2.6.8 Matching on Attributes

Attributes on the source element or any of its ancestor elements can also be used to determine whether a particular rule applies to an element. An attribute qualifier constrains an element either to have a specific attribute with a specific value, or to have a specific attribute with any value.

Attribute Qualifier


[24] AttributeQualifier ::= AttributePattern ('=' AttributeValue)?
[25] AttributePattern ::= 'attribute' '(' QName ')'
[26] AttributeValue ::= '"' [^"]* '"'
      | "'" [^']* "'"

When matching attribute names, the expanded names are compared (see Section 2.4.3: Attribute Nodes).

Issue (attribute-qual-case): Do we need to be able to match attributes in a case insensitive way?

The following example matches an item element that has for its parent a list element which has a compact attribute:

<xsl:template match="list[attribute(compact)]/item">
  ...
</xsl:template>

The following example matches an item element that has for its parent a list element whose liststyle attribute has the value enum:

<xsl:template match="list[attribute(liststyle)='enum']/item">
  ...
</xsl:template>

It is also possible to select attribute nodes. Within a select pattern, an AncestryPattern can end with an AttributePattern. This will select the attribute node with the specified name for each element in the node list selected by the pattern preceding AttributePattern. Within a match pattern, an AncestryPattern must not end with an AttributePattern.

Issue (class-attribute): Should there be a way of specifying that an attribute serves as a class attribute and then pattern syntax that treats class attributes specially?

2.6.9 Matching on Position

Positional qualifiers may be used to further constrain the pattern to match on the element's position or uniqueness among its siblings.

XSL defines the following positional qualifiers:

  • first-of-type(). The element must be the first sibling of its type.

  • not-first-of-type(). The element must not be the first sibling of its type.

  • last-of-type(). The element must be the last sibling of its type.

  • not-last-of-type(). The element must not be the last sibling of its type.

  • first-of-any(). The element must be the first sibling element of any type.

  • not-first-of-any(). The element must not be the first sibling element of any type.

  • last-of-any(). The element must be the last sibling element of any type.

  • not-last-of-any(). The element must not be the last sibling element of any type.

  • only-of-type(). The element must have no element siblings of the same type.

  • not-only-of-type(). The element must have one or more element siblings of the same type.

  • only-of-any(). The element must have no element siblings at all.

  • not-only-of-any(). The element must have one or more element siblings.

Positional Qualifier


[27] PositionalQualifier ::= Position '(' ')'
[28] Position ::= 'first-of-type' | 'not-first-of-type'
      | 'first-of-any' | 'not-first-of-any'
      | 'last-of-type' | 'not-last-of-type'
      | 'last-of-any' | 'not-last-of-any'
      | 'only-of-type' | 'not-only-of-type'
      | 'only-of-any' | 'not-only-of-any'

The following pattern matches the first item in a list:

<xsl:template match="list/item[first-of-type()]">
  ...
</xsl:template>

The following rule is used for appendix elements when there is only one appendix:

<xsl:template match="backmatter/appendix[only-of-type()]">
  ...
</xsl:template>

2.6.10 Whitespace in Patterns

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

Pattern Lexical Structure


[29] PatternToken ::= '/' | '//' | '(' | ')' | '|' | '[' | ']' | ',' | '=' | '.' | '..' | '*'
      | 'attribute' | 'id' | 'ancestor'
      | NCName
      | QName
      | AttributeValue
      | Position
[30] PatternWhitespace ::= S

2.6.11 Specificity

When a source element is matched against multiple patterns, it is possible for it to match more than one distinct pattern. In this situation, XSL defines which pattern or patterns are the most specific.

A pattern that starts with an IdAnchor is more specific than a pattern that does not. If two patterns both start with an IdAnchor or both do not start with an IdAnchor, then the one with the more components is the more specific, where a component is either a Qualifier or a OneElementTypePattern.

For example, the following patterns are in decreasing order of specificity:

  1. id(employee-of-the-month)

  2. employee[attribute(type)='contract',attribute(country)='USA']

  3. employee[attribute(type)='contract']

  4. employee

  5. *

When a pattern contains alternatives separated by |, each alternative is treated separately for specificity purposes. A rule that contains a pattern with two alternatives is equivalent to two rules with the same content each specifying one of the alternatives as its patterns. For example

<xsl:template match="EMPH|B" priority="1">
  <fo:sequence font-weight="bold"><xsl:process-children/></fo:sequence>
</xsl:template>

is equivalent to

<xsl:template match="EMPH" priority="1">
  <fo:sequence font-weight="bold"><xsl:process-children/></fo:sequence>
</xsl:template>
<xsl:template match="B" priority="1">
  <fo:sequence font-weight="bold"><xsl:process-children/></fo:sequence>
</xsl:template>

2.7 Templates

2.7.1 Overview

When the rule that is to be applied to the source element has been identified, the rule's template is instantiated. A template can contain literal result elements, character data and instructions for creating fragments of the result tree. Instructions are represented by elements in the XSL namespace.

Instructions can select descendant elements for processing. There are two such instructions, the xsl:process-children instruction and the xsl:process instruction; the xsl:process-children instruction processes the immediate children of the source element, while the xsl:process instruction processes elements selected by a specified pattern.

<xsl:template match="chapter/title">
  <fo:rule-graphic/>
  <fo:block space-before="2pt">
    <xsl:text>Chapter </xsl:text>
    <xsl:number/>
    <xsl:text>: </xsl:text>
    <xsl:process-children/>
  </fo:block>
  <fo:rule-graphic/>
</xsl:template>

Note that xsl:process-children selects any character children of the source element as well as the element children. The result in this case is the sequence of results of processing the individual character children and element children in sequence.

Issue (instruction-next-match): Should we add an instruction with the functionality of next-match in DSSSL?
Issue (instruction-error): Should there be an instruction that generates an error, like the error procedure in DSSSL?
Issue (instruction-sort): There needs to be an instruction that can do sorting. How should this work?
Issue (instruction-result-number): There needs to be instruction that allows result elements to be numbered. How should this work?
Issue (modes): How should the functionality of DSSSL modes be provided? Should nested template rules be used for this? Is there a way of getting source elements to appear in multiple places in the output that can be implemented in a single pass?
Issue (identity-transform): There needs to be a way to do the identity transformation (creating a result tree identical to the source tree). How should this be done?

2.7.2 Literal Result Elements

In a template an element in the stylesheet that does not belong to the XSL namespace is instantiated to create an element node of the same type; the created element node will have the attributes that were specified on the element in the template tree.

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 ({}).

The namespace prefix map of the result element node is the namespace prefix map of the element node in the stylesheet after the removal of any prefixes that map to the XSL namespace URI.

Since an XSL processor acts on elements belonging to the XSL namespace, the problem arises of how to create elements belonging to the XSL namespace. A namespace whose URI is http://www.w3.org/TR/WD-xsl followed by one or more occurrences of /quote is called a quoted namespace. Quoted namespaces are treated specially: before a result tree is written out as XML all quoted namespace URIs in expanded names and in namespace prefix maps are unquoted by removing the final /quote.

2.7.3 Named Attribute Sets

The xsl:define-attribute-set element defines a named set of attributes. The name attribute specifies the name of the attribute set. The content of the xsl:define-attribute-set element is an xsl:attribute-set element that specifies the attributes. A literal result element or an xsl:attribute-set element can specify an attribute set name as the value of the xsl:use attribute.

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

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

<xsl:template match="chapter/heading">
  <fo:block xsl:use="title-style" quadding="start">
    <xsl:process-children/>
  </fo:block>
</xsl:template>

If the xsl:use attribute is specified on an element that also specifies a value for an attribute that is also part of the attribute set named by xsl:use, the attribute in the named attribute set is not used.

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

An xsl:use attribute may specify a list of attribute set names separated by whitespace. These attribute sets will be merged treating the list as being in order of increasing importance.

2.7.4 Literal Text in Templates

A template can also contain PCDATA. Each data character in a template remaining after whitespace has been stripped as specified in Section 2.4.5: Whitespace Stripping will create a data character in the result tree.

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

2.7.5 Processing with xsl:process-children

Ed. Note: There is no WG consensus on the name xsl:process-children.

Ed. Note: When we add to select patterns the ability to select characters as well as elements, the functionality of xsl:process-children will be available from xsl:process.

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

<xsl:template match="chapter">
  <fo:block>
    <xsl:process-children/>
  </fo:block>
</xsl:template>

The xsl:process-children instruction processes all of the children of the current node, including characters. However, characters that have been stripped as specified in Section 2.4.5: Whitespace Stripping will not be processed.

Processing a character in the source tree adds the character to the result tree. Note that this works at the tree level. Thus, markup of &lt; in content will be represented by a character < in the source tree which will, with the built-in template rules, turn into a < character in the result tree, which would be represented by the markup &lt; (or an equivalent character reference) when the result tree is externalized as an XML document.

2.7.6 Processing with xsl:process

Ed. Note: There is no WG consensus on the name xsl:process.

Issue (process-name): What should xsl:process be called?

The xsl:process element processes elements selected by a pattern. The pattern of an xsl:process element is a select pattern and so is implicitly anchored to the current node. The following example processes all of the author children of the author-group:

<xsl:template match="author-group">
  <fo:sequence>
    <xsl:process select="author"/>
  </fo:sequence>
</xsl:template>

The xsl:process element processes all elements which match the specified pattern. Character data content is not matched by an xsl:process element. The pattern must not contain an AttributePattern except as part of an AttributeQualifier

The pattern controls the depth at which matches occur. The following example processes all of the first-names of the authors that are direct children of author-group:

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

The // operator can be used in the pattern to allow the matches to occur at arbitrary depths.

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

<xsl:template match="book">
  <fo:block>
    <xsl:process select=".//heading"/>
  </fo:block>
</xsl:template>

An AncestorAnchor in the pattern allows the processing of elements that are not descendants of the current node. This example finds an employee's department and then processes the group children of the department.

<xsl:template match="employee">
  <fo:block>
    Employee <xsl:process select="name"/> belongs to group
    <xsl:process select="ancestor(department)/group"/>
  </fo:block>
</xsl:template>

This example assumes that a department element contains group and employee elements (at some level). When processing the employee elements, the AncestorAnchor in the pattern allows navigation upward to the department element in order to extract the information about the group to which the employee belongs.

An IdAnchor allows processing of elements with a specific ID. For example, this template rule applies to elements with the ID cfo; the second xsl:process element processes the name child of the element with ID ceo:

<xsl:template match="id(cfo)">
  <xsl:process select="name"/> reports to <xsl:process select="id(ceo)/name"/>
</xsl:template>

Multiple xsl:process 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:process select="sales/domestic"/>
  </TABLE>
  <TABLE>
    <xsl:process 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:process select=".//div"/>
</xsl:template>

will process both the outer div and inner div elements.

Use of Anchors in patterns in xsl:process can lead to infinite loops. It is an error if, during the invocation of a rule for an element, that same rule is invoked again for that element. An XSL 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.

Issue (select-function): What mechanisms should be provided for selecting elements for processing? For example, how can elements specified indirectly be handled? Suppose there's an xref element with a ref attribute that specifies the ID of a div element. The template for xref needs to select title child of the div element referenced by the ref attribute. Should it be possible to select elements in other XML documents?

2.7.7 Direct Processing

When the result has a known regular structure, it is useful to be able to specify directly the template for selected elements. The xsl:for-each element contains a template which is instantiated for each element selected by the pattern specified by the select attribute.

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:process select="name"/>
          </TH>
          <xsl:for-each select="order">
        <TD>
          <xsl:process-children/>
        </TD>
          </xsl:for-each>
        </TR>
      </xsl:for-each>
    </TBODY>
      </TABLE>
    </BODY>
  </HTML>
</xsl:template>

As with xsl:process the pattern is a select pattern and so is implicitly anchored to the current node. The select attribute is required. The pattern must not contain an AttributePattern except as part of an AttributeQualifier.

2.7.8 Numbering in the Source Tree

The xsl:number element does numbering based on the position of the current node in the source tree.

The xsl:number element can have the following attributes:

  • The level attribute specifies what levels of the source tree should be considered; it has the values single, multi or any. The default is single.

  • The count attribute is a match pattern that specifies what elements should be counted at those levels. The count attribute defaults to the element type name of the current node.

  • The from attribute is a match pattern that specifies where counting starts from.

In addition the xsl:number element has the attributes specified in Section 2.7.9: 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:

  • When level="single", it goes up to the nearest ancestor (including the current node as its own ancestor) that matches the count pattern, and constructs a list of length one containing one plus the number of preceding siblings of that ancestor that match the count pattern. If there is no such ancestor, it constructs an empty list. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern.

  • When level="multi", it constructs a list of all ancestors of the current node in document order followed by the element itself; it then selects from the list those elements that match the count pattern; it then maps each element of the list to one plus the number of preceding siblings of that element that match the count pattern. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern.

  • When level="any", it constructs a list of length one containing one plus number of elements at any level of the document that start before this node and that match the count pattern. If the from attribute is specified, then only elements after the first element before this element that match the from pattern are considered.

The list of numbers is then converted into a string using the attributes specified in Section 2.7.9: 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.

The following would number the items in an ordered list:

<xsl:template match="ol/item">
  <fo:block>
    <xsl:number/><xsl:text>. </xsl:text><xsl:process-children/>
  </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:process-children/>
  </fo:block>
</xsl:template>

<xsl:template match="appendix//title">
  <fo:block>
     <xsl:number level="multi"
                 count="appendix|section|subsection"
                 format="A.1. "/>
     <xsl:process-children/>
  </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:process-children/>
  </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:process-children/>
 </fo:block>
</xsl:template>

2.7.9 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. The alphanumeric tokens (format tokens) specify the format to be used for each number in the list; the non-alphanumeric tokens (separator tokens) specify the separators used to join numbers in the list. Alphanumeric means any character that has a Unicode category of Nd, Nl, No, Lu, Ll, Lt, Lm or Lo. If the first token is a separator token, then the constructed string will start with that token; if the last token is a separator token, then the constructed string will end with that token. 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. The format token specifies the string to be used to represent the number 1. If there are more than n numbers, then the n-th number will be separated from the following number by the separator token following the n-th format token; if there is no such separator token, then the last separator token will be used; if there are no separator tokens, then . will be used.

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:

  • Any token where the last character has a decimal digit value of 1 (as specified in the Unicode 2.0 character property database), and the Unicode value of preceding characters is one less than the Unicode value of the last character. This generates a decimal representation of the number where each number is at least as long as the format token. Thus a format token 1 generates the sequence 1 2 ... 10 11 12 ..., and a format token 01 generates the sequence 01 02 ... 09 10 11 12 ... 99 100 101.

  • A format token A generates the sequence A B C ... Z AA AB AC....

  • A format token a generates the sequence a b c ... z aa ab ac....

  • A format token i generates the sequence i ii iii iv v vi vii vii ix x ....

  • A format token I generates the sequence I II III IV V VI VII VII IX X ....

  • Any other format token indicates a numbering sequence that starts with that token. If an implementation does not support a numbering system that starts with that token, it must use a format token of 1.

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:

  • format="&#x30A2;" specifies Katakana numbering

  • format="&#x30A4;" specifies Katakana numbering in the "iroha" order

  • format="&#x0E51;" specifies numbering with Thai digits

  • format="&#x05D0;" letter-value="other" specifies "traditional" Hebrew numbering

  • format="&#x10D0;" letter-value="other" specifies Georgian numbering

  • format="&#x03B1;" letter-value="other" specifies "classical" Greek numbering

  • format="&#x0430;" letter-value="other" specifies Old Slavic numbering

2.7.10 Conditionals within a Template

There are two instructions in XSL 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.

2.7.10.1 Conditional Processing with xsl:if

The xsl:if element has a single attribute, test which specifies a select pattern. The content is a template. If the pattern selects a non-empty list of elements, 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:process-children/>
  <xsl:if test=".[not-last-of-type()]">, </xsl:if>
</xsl:template>
2.7.10.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 select pattern; the test is treated as true if the pattern selects a non-empty list of elements. 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:choose>
        <xsl:when test='ancestor(orderedlist/orderedlist)'>
          <xsl:number format="i"/>
        </xsl:when>
        <xsl:when test='ancestor(orderedlist)'>
          <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:process-children/>
    </fo:list-item-body>
  </fo:list-item>
</xsl:template>

2.7.11 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 string constant. The xsl:value-of element does this with a string expression that is specified as the value of the expr attribute. String expressions can also be used inside attribute values of literal result elements by enclosing the string expression in curly brace ({}).

2.7.11.1 String Expressions

String Expressions


[31] StringExpr ::= Pattern
      | ConstantRef
      | MacroArgRef

The value of a string expression that is a pattern is the character content of the first node selected by the pattern. If the first node is an attribute node, the value is the attribute value. If the first node is an element node, the value is computed by concatenating all characters that are descendants of the element node in the order in which they occur in the document. The pattern is a select pattern and so is implicitly anchored to the current node.

Issue (resolve-expr): Do we need a resolve(pattern) 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?
2.7.11.2 Using String Expressions with xsl:value-of

The xsl:value-of element is replaced by the value of the string expression specified by the expr attribute. The expr attribute is required.

For example, the following creates an HTML paragraph from a person element with first-name and surname attributes.

<xsl:template match="person">
  <P>
   <xsl:value-of expr="attribute(first-name)"/>
   <xsl:text> </xsl:text>
   <xsl:value-of expr="attribute(surname)"/>
  </P>
</xsl:template>

For example, the following creates an HTML paragraph from a person element with first-name and surname children elements.

<xsl:template match="person">
  <P>
   <xsl:value-of expr="first-name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of expr="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 an ancestor element of the procedure. It also assumes that if more than one ancestor has a security attribute then the security level is determined by the closest such ancestor of the procedure.

<xsl:template match="procedure">
  <fo:block>
    <xsl:value-of expr="ancestor(*[attribute(security)])/attribute(security)"/>
  </fo:block>
  <xsl:process-children/>
</xsl:template>
Issue (inherited-attribute): Unless an element counts as one of its own ancestors, using ancestor(*[attribute(security)])/attribute(security) won't work to get the inherited value of an attribute. We could either say ancestor always includes the current node; alternatively we could provide a variant of ancestor that does include the current node; alternatively we could provide a select pattern of the form inherited-attribute(security).
2.7.11.3 Attribute Value Templates

In an attribute value that is interpreted as an attribute value template, such as an attribute of a literal result element, string expressions can be used by surrounding the string expression with curly braces ({}). The attribute value template is instantiated by replacing the string expression together with surrounding curly braces by the value of the string expression.

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 the width attribute of the size child of the photograph element:

<xsl:define-constant name="image-dir" value="/images"/>

<xsl:template match="photograph">
<IMG SRC="{constant(image-dir)}/{href}" WIDTH="{size/attribute(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 XSL processor may signal the error or recover by treating the right curly brace as if it had been doubled. A right curly brace inside an AttributeValue 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({attribute(ref)})/title}">

is not allowed.

2.7.12 String Constants

Global string constants may be defined using a define-constant element. The name attribute specifies the name of the constant, and the value attribute specified the value.

A stylesheet must not contain more than one definition of a constant with the same name and same importance. A definition of a constant will not be used if there is another definition of a constant with the same name and higher importance.

String constants are referenced using a ConstantRef string expression.

String Constant References


[32] ConstantRef ::= 'constant' '(' NCName ')'

<xsl:define-constant name="para-font-size" value="12pt"/>

<xsl:template match="para">
 <fo:block font-size="{constant(para-font-size)}">
   <xsl:process-children/>
 </fo:block>
</xsl:template>
Issue (local-constants): Should there be a way to define local constants?

The value attribute is interpreted as an attribute value template. If the value of a constant definition x references a constant 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 constant definitions because of dependency cycles.

2.7.13 Macros

Issue (macro-name): Should macros be called something else?

Parts of templates can also be factored out of similar rules into macros for reuse. Macros allow authors to create aggregate result fragments and refer to the composite as if it were a single object. In this example, a macro is defined for a boxed paragraph with the word "Warning!" preceding the contents. The macro is referenced from a rule for warning elements.

<xsl:define-macro name="warning-para">
  <fo:box>
    <fo:block>
      <xsl:text>Warning! </xsl:text>
      <xsl:contents/>
    </fo:block>
  </fo:box>
</xsl:define-macro>

<xsl:template match="warning">
  <xsl:invoke macro="warning-para">
    <xsl:process-children/>
  </xsl-invoke>
</xsl:template>

Macros are defined using the define-macro element. The name attribute specifies the name of the macro being defined. The content of the define-macro element is a template, called the body of the macro. A macro is invoked using the xsl:invoke element; the content of xsl:invoke is a template. The name of the macro to be invoked is given by the macro attribute. Invoking a macro first instantiates the content of xsl:invoke. It then instantiates the body of the invoked macro passing it the result tree fragment created by the instantiation of the content of xsl:invoke; this fragment can be inserted in the body of the macro using the xsl:contents element.

Macros allow named arguments to be declared with the xsl:macro-arg element; the name attribute specifies the argument name, and the optional default attribute specifies the default value for the argument. Within the body of a macro, macro arguments are referenced using a MacroArgRef string expression. It is an error to refer to a macro argument that has not been declared. An XSL processor may signal the error; if it does not signal the error, it must recover by using an empty string. Arguments are supplied to a macro invocation using the code xsl:arg element; the name attribute specifies the argument name, and the value attribute specifies the argument value. It is an error to supply an argument to a macro invocation if the macro did not declare an argument of that name. An XSL processor may signal the error; if it does not signal the error, it must recover by ignoring the argument. The value attribute of xsl:arg and the default attribute of xsl:macro-arg are interpreted as attribute value templates; they can contain string expressions in curly braces as with literal result elements.

Macro Argument References


[33] MacroArgRef ::= 'arg' '(' NCName ')'

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

<xsl:define-macro name="numbered-block">
  <xsl:macro-arg name="format" default="1. "/>
  <xsl:number format="{arg(format)}"/>
  <fo:block/>
    <xsl:contents/>
  </fo:block>
</xsl:define-macro>

<xsl:template match="appendix/title">
  <xsl:invoke name="numbered-block">
    <xsl:arg name="format" value="A. "/>
    <xsl:process-children/>
  </xsl:invoke>
</xsl:template>

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

Issue (macro-arg-syntax): The proposal used the same element for declaring macro arguments and for invoking them. Should these be separate elements and if so what should they be called?

2.8 Style Rules

This section will describe a facility similar to style rules in the XSL submisson.

Issue (style-rules): How should style rules work?

2.9 Combining Stylesheets

XSL provides two mechanisms to combine stylesheets:

2.9.1 Stylesheet Import

An XSL 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 Section 2.4.2.2: Base URI).

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
  <xsl:import href="article.xsl"/>
  <xsl:import href="bigfont.xsl"/>
  <xsl:define-attribute-set name="note-style">
    <xsl:attribute-set font-posture="italic"/>
  </xsl:define-attribute-set>
</xsl:stylesheet>

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

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

Issue (stylesheet-partition): Should there be an XSL defined element that can be used to divide a stylesheet into parts, each of which is treated as if it were separately imported for precedence purposes?
Issue (import-source): Provide a way for a stylesheet to import a stylesheet that is embedded in the document.
Issue (import-media): Should we provide media-dependent imports as in CSS?

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?

2.9.2 Stylesheet Inclusion

An XSL stylesheet may include another XSL 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 Section 2.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?

2.9.3 Embedding Stylesheets

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

  • the XSL stylesheet may be textually embedded in a non-XML resource, or
  • the xsl:stylesheet element may occur in an XML document other than as the document element.

In the second case, the possibility arises of documents with inline style, that is documents that specify their own style. XSL 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:

  • the mechanism allows a part of a resource to be specified as the stylesheet, for example by using a URI with a fragment identifier, and
  • the mechanism can itself can be embedded in the document, for example as a processing instruction.

It is not in the scope of XSL 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/TR/WD-xsl" id="style1">
<xsl:import href="doc.xsl"/>
<xsl:template match="id(foo)">
 <fo:block font-weight="bold"><xsl:process-children/></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.

2.10 Extensibility

This section will describe an extensibility mechanism for the tree construction process.

Issue (construct-extensibility): Should there be some extensibility mechanism for the tree construction process? If so, how should it work? Should it be language independent?

3. Formatting Objects

This section describes the formatting vocabulary.

3.1 Introduction

The approach that we have taken in constructing this draft was to evaluate the requirements for print and online documents and established a target set of capabilities. This set of capabilities reflect the long-term goals of XSL

In this draft we concentrated on documenting a subset of the formatting capability that addressed basic WP-level pagination. We expect to cover more sophisticated pagination and support for layout-driven documents in later drafts.

3.2 Notations Used in this Section

The following typographic styles are used to identify different terms in this document:

property-name

The name of a property or attribute. Always all lowercase and hyphenated between words.

property-value

The value assigned to a property. Always all lowercase and hyphenated between words.

This has varying forms dependent on the value type:

a ___-specifier

See defined types for the definitions of character-specifier, color-specifier, length-specifier, name-specifier, writing-mode-specifier.

keyword

The name of a value for enumerated types.

0.0pt

A measure (length-specifier) is always qualified with units.

0.0

A numeric value (integer and fraction).

1

An integer value.

()|[]{}...

Delimiters & operators, code fragments.

( choice-1 | choice-2 | ... )

A choice-list. Choose one of the values or options listed. These may be mixed (such as a choice between none and a length-specifier.

formatting-object-name

The name of a formatting object. Always all lowercase and hyphenated between words.

Format