[Archive copy mirrored from the URL: http://www.w3.org/TR/NOTE-XSL-970910.html; see this canonical version of the document.]

W3C

NOTE-XSL.html

A Proposal for XSL

· Submitted to W3C on 27 August 1997 ·

This version:
http://www.w3.org/TR/NOTE-XSL.html
Latest version:
http://www.w3.org/TR/NOTE-XSL.html
Authors:
Sharon Adler, Inso Corporation
Anders Berglund, Inso Corporation
James Clark
Istvan Cseri, Microsoft Corporation
Paul Grosso, ArborText
Jonathan Marsh, Microsoft Corporation
Gavin Nicol, Inso Corporation
Jean Paoli, Microsoft Corporation
David Schach, Microsoft Corporation
Henry S. Thompson, University of Edinburgh
Chris Wilson, Microsoft Corporation



Status of this Document

This document is a NOTE made available by the World Wide Web Consortium for discussion only. This indicates no endorsement of its content, nor that the Consortium has, is, or will be allocating any resources to the issues addressed by the NOTE. A list of current NOTEs can be found at: http://www.w3.org/TR/.

This document is part of a complete submission to the W3C. The full submission has been acknowledged by W3C and is available at http://www.w3.org/Submission/1997/13/Overview.html

Note: since working drafts are subject to frequent change, you are advised to reference the above URL, rather than the URLs for working drafts themselves.


August 21, 1997

1. Introduction

1.1. Status

This is a working document. It is not meant to represent a completed proposal for XSL. Details of the flow objects and their characteristics need to be specified in detail; for now refer to the DSSSL standard and the HTML and CSS specifications.

1.2. Purpose

This is a proposal for XSL (Extensible Style Language) that is the deliverable for Phase III of the SGML, XML, and Structured Document Interchange Activity of the W3C. The charter for this activity specifies the use of ISO/IEC 10179 Document Style Semantics and Specification Language ( DSSSL) for the stylesheet language component. XSL is based on DSSSL.

XSL is a stylesheet language designed for the Web community. It provides functionality beyond CSS (e.g. element reordering). We expect that CSS will be used to display simply-structured XML documents and XSL will be used where more powerful formatting capabilities are required or for formatting highly structured information such as XML structured data or XML documents that contain structrued data.

Web authors create content at three different levels of sophistication:

  • markup: relies solely on a declarative syntax
  • script: additionally uses code “snippets” for more complex behaviors
  • program: uses a full programming language

XSL is intended to be accessible to the “markup” level user by providing a declarative solution to most data description and rendering requirements. Less common tasks are accommodated through a graceful escape to a familiar scripting environment. This approach is familiar to the Web publishing community as it is modeled after the HTML/JavaScript environment.

The powerful capabilities provided by XSL allow:

  • formatting of source elements based on ancestry/descendency, position, and uniqueness
  • the creation of formatting constructs including generated text and graphics
  • the definition of reusable formatting macros
  • writing-direction independent stylesheets
  • extensible set of formatting objects

1.3. Relationship to DSSSL

XSL is based on DSSSL and is compatible with the fundamental design principles and processing model of this standard. However, the development of XSL has identified usability issues with the current DSSSL standard which has led XSL to diverge in various ways.

Therefore, in parallel with the development of the XSL specification, a proposal for an amendment to DSSSL will be developed so that with the amendment it would be a superset of XSL. The amended standard would be compatible with current DSSSL but would have three kinds of additions:

  • an alternative syntax compatible with the XSL syntax;
  • extensions to the flow object tree construction language to support the features of XSL not in DSSSL; these features would be available both with the current syntax and the alternative syntax;
  • new flow object classes and characteristics to support formatting functionality necessary for the Web.

XSL incorporates the subset of DSSSL flow object classes and characteristics that was specified in DSSSL-O.

1.4. Relationship to HTML and CSS

XSL supports all of the functionality of CSS so that an accurate mechanical translation from CSS to XSL is possible. In order to provide this level of compatibility, cascading styles, specificity, and flow object and characteristic mapping need to be addressed by XSL. For the purposes of this document, CSS is defined by the W3C recommendation Cascading stylesheets, level 1 and W3C working drafts CSS Printing Extensions and Positioning HTML with Cascading Stylesheets.

There are two levels of support for CSS styles and the CSS formatting model. To provide HTML authors a migration path and for HTML/CSS object model compatibility, XSL provides a set of HTML/CSS core flow objects with HTML attributes and CSS properties as characteristics. For DSSSL core flow objects, CSS properties are mapped via flow object macros and script code to the appropriate flow objects and characteristics.

CSS functionality is described throughout this document, notably in section 3.2 (Patterns), section 3.2.4 (ID and CLASS Attributes), section 3.2.6 (Conflicts), section 4 (Styles), and section 6.2 (HTML/CSS Core Flow Objects).

1.5. Design Principles

The following design principles have been used to guide the development of the XSL format described in this document, ordered from most important to least important.

  1. XSL should be straightforwardly usable over the Internet.
  2. XSL should be expressed in XML syntax.
  3. XSL should provide a declarative language to do all common formatting tasks.
  4. XSL should provide an “escape” into a scripting language to accommodate more sophisticated formatting tasks and to allow for extensibility and completeness.
  5. XSL will be a subset of DSSSL with the proposed amendment.
  6. A mechanical mapping of a CSS stylesheet into an XSL stylesheet should be possible.
  7. XSL should be informed by user experience with the FOSI stylesheet language.
  8. The number of optional features in XSL should be kept to a minimum.
  9. XSL stylesheets should be human-legible and reasonably clear.
  10. The XSL design should be prepared quickly.
  11. XSL stylesheets shall be easy to create.
  12. Terseness in XSL markup is of minimal importance.

2. Stylesheet Structure

2.1. Overview

XSL enables formatting information to be associated with elements in the source document to produce formatted output. The formatted output is created by formatting a tree of flow objects. A flow object has a class, which represents a kind of formatting task. A flow object also has a set of named characteristics, which further specify the formatting. A core set of flow object classes is outlined later in this document.

The association of elements in the source tree to flow objects is through construction rules. The construction rules contain a pattern to identify specific elements in the source tree, and an action to specify a resulting sub-tree of flow objects. The stylesheet processor recursively processes source elements to produce a complete flow object tree.

In addition to construction rules XSL also supports style rules which allow the merging of characteristics. While only one construction rule can be invoked for a particular source element, all applicable style rules are invoked, allowing per-characteristic merging as in CSS.

An XSL stylesheet describes this formatting process through a small set of XML elements. An XSL stylesheet contains an XSL document element. This element can contain rule elements representing construction rules, and style-rule elements representing style merging rules. These elements will be described later in this document.

This example contains a root rule which creates the top-level HTML and BODY flow objects, a rule which creates a DIV with certain style characteristics for each orders element in the source, and a style-rule which applies the “bold” style to all customer elements.

<xsl>
  <rule>
    <root/>

    <HTML>
      <BODY>
        <children/>
      </BODY>
    </HTML>
  </rule>
  
  <rule>
    <target-element type="orders"/>

    <DIV font-size="14pt" font-family="serif">
      <children/>
    </DIV>
  </rule>

  <style-rule>
    <target-element type="customer"/>

    <apply font-weight="bold"/>
  </style-rule>
</xsl>

Note: This example uses HTML/CSS core flow objects.

The xsl element can also contain import elements to import other XSL stylesheets, define-macro elements representing flow object macro definitions, define-script elements representing common functions and definitions, and id and class elements representing the identification of source attributes as individual element identifiers or as class element identifiers. These elements are also described later in this document.

2.2. Referring to a Stylesheet from XML

The XML WG is defining mechanisms to associate XML documents with stylesheets. Until this work has been completed, it is recommended that XSL implementations use the xml-stylesheet processing instruction proposal. For example, this line would be included in the XML source file:

<?xml-stylesheet href="article.xsl" type="text/xsl" ?>

2.3. Import

An XSL stylesheet may import other XSL stylesheets, by using an import element with an href attribute:

<import href="article.xsl"/>

Using an import element is exactly equivalent to textually including the resource located by the value of the href attribute.

3. Rules

3.1. Overview

A rule is specified with the rule element. The rule element contains a pattern that identifies the source element to which this rule applies. The rule also contains an action that specifies the flow objects to construct.

For example, an XML document contains the following:

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

The following XSL rule contains a pattern which identifies elements of type emph and an action which produces a SPAN flow object with the characteristic font-weight="bold".

<rule>
  <!-- pattern -->
  <target-element type="emph"/>
  
  <!-- action -->
  <SPAN font-weight="bold">
    <children/>
  </SPAN>
</rule>

Note: this example uses HTML/CSS core flow objects.

As detailed later in this document, the children element recursively processes the children of the source element.

A rule may have multiple patterns associated with a single action. This example constructs a SPAN for either emph or strong element patterns:

<rule>
  <target-element type="emph"/>
  <target-element type="strong"/>
  <SPAN font-weight="bold">
    <children/>
  </SPAN>
</rule>

Note: this example uses HTML/CSS core flow objects.

3.2. Patterns

3.2.1. Elements

The pattern part of a construction rule must contain a target-element element which indicates the source element to which the rule applies. The pattern also allows identifying applicable elements by their context within the source, including:

  1. element ancestry;
  2. element descendants;
  3. wildcards in the ancestry/descendant hierarchy (arbitrary ancestors/descendants);
  4. attributes on an element;
  5. position of an element relative to its siblings;
  6. uniqueness of an element relative to its siblings.

Element ancestry can be represented within the pattern by mirroring the hierarchy found in the source document. The element element has identical attributes to the target-element, but implies that the source element named by its type attribute is part of the context of the applicable element in the source rather than the element to which this rule will be applied. The containment hierarchy of the element elements in the pattern indicate their contextual relationship to the target-element element in the source.

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

<element type="chapter">
  <element type="section">
    <target-element type="title"/>
  </element>
</element>

Children of the applicable source document element can be specified in a similar fashion. The following pattern matches table source elements that have a title child:

<target-element type="table">
  <element type="title"/>
</target-element>

Multiple element elements can be placed inside a target-element element. This indicates only that all these elements must be present, not in any particular order. The following pattern matches employee elements that contain both an exempt element, and an high-paid element:

<target-element type="employee">
  <element type="exempt"/>
  <element type="high-paid"/>
</target-element>

The root of the source document tree can be identified within the special root pattern <root/>.

<rule>
  <root/>
  <HTML>
    <BODY>
      <children/>
    </BODY>
  </HTML>
</rule>

Note: this example uses HTML/CSS core flow objects.

3.2.2. Wildcards

Ancestry or descendancy beyond an unbroken sequence of immediate parents or immediate children can also be specified as part of the context for determining whether a rule applies to a given source element. Wildcards can be specified within the pattern with the any element. The any element matches zero or more elements within the source element hierarchy.

This example applies to a para element that has a appendix ancestor, and also has a changed descendant.

<element type="appendix">
  <any>
    <target-element type="para">
      <any>
        <element type="changed"/>
      </any>
    </target-element>
  </any>
</element>

Both target-element and element elements can be used as wildcards by omitting the type attribute. In this case, these elements match exactly one element in the source element hierarchy. The following pattern matches elements that have a grandparent of type data-samples, regardless of the type of the target element or the parent element.

<element type="data-samples">
  <element>
    <target-element/>
  </element>
</element>

3.2.3. Attributes

Attributes on the source element or any of its ancestor or descendant elements can also be used to determine whether a particular construction rule applies. The attribute element is included in an element or target-element element to test the value of a source attribute.

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

<element type="list">
  <attribute name="liststyle" value="enum"/>
  <target-element type="item"/>
</element>

Simple presence or absence of an attribute can also be tested. When the has-value attribute has the value yes, a source element matches the pattern when the attribute in question has been given a value in the source (either by an explicit assignment or by receiving a default value). When the has-value attribute has the value no, a source element matches the pattern when the default value of the source attribute is #IMPLIED and the source attribute has no explicit assignment. If the value attribute has been assigned, the has-value attribute is ignored.

The following example matches an item element that has for its parent a list element whose compact attribute has some value (as opposed to being left unassigned and implied):

<element type="list">
  <attribute name="compact" has-value="yes"/>
  <target-element type="item"/>
</element>

Multiple attribute elements can be applied to a single target-element or element element.

<target-element type="reference">
  <attribute type="href" has-value="yes"/>
  <attribute type="used-as" value="direct-quote"/>
</target-element>

3.2.4. ID and CLASS Attributes

Like CSS, XSL gives special treatment to two categories of attribute, id attributes and class attributes.

A source element attribute is in the id category if it was declared as an ID in the source DTD. XSL must work with XML documents that do not have a DTD; therefore XSL also allows stylesheets to specify source element attributes that should be in the id category. This is done using an id element, with an attribute attribute specifying the name of the attribute that should be in the id category. The following would put a name attribute on any element in the id category.

<id attribute="name"/>

A target-element or element element can specify an id attribute. This will match a source element that has an attribute in the id category with the same value.

In a stylesheet a class element is used to declare the name of an attribute that should be in the class category. For example, the following would put a family attribute on any element in the class category:

<class attribute="family"/>

An element or target-element element can specify a class attribute. This will match a source element that has an attribute in the class category with the same value.

3.2.5. Qualifiers

There are two qualifiers, position and only, each expressed as an attribute on the element and target-element elements.

The position qualifier specifies the position of an element among its siblings. The values of the position qualifier are:

  • first-of-type. The element must be the first sibling of its type.
  • last-of-type. The element must be the last sibling of its type.
  • first-of-any. The element must be the first sibling of any type.
  • last-of-any. The element must be the last sibling of any type.

The only qualifier specifies whether the source element has any siblings or not. Its values are:

  • of-type. The element must have no element siblings of the same type.
  • of-any. The element must have no element siblings at all.

The following pattern matches the first item in a list:

<element type="list">
  <target-element type="item" position="first-of-type"/>
</element>

The following pattern matches the only item in a list:

<element type="list">
  <target-element type="item" only="of-type"/>
</element>

3.2.6. Conflicts

It is possible for a source element to match patterns in several different rules. XSL has an algorithm for determining which rules should be invoked in this situation. It also allows the stylesheet to override this by specifying importance and priority attributes on the rule and style-rule elements.

When an element matches more than one pattern, then the most specific pattern will be used. The precedence order for establishing the most specific pattern is:

  1. the pattern with the highest importance; the importance of a pattern is the value of the importance attribute on the rule that contains it; this allows the CSS !important feature to be supported
  2. the pattern with the greater number of id attributes
  3. the pattern with the greater number of class attributes
  4. the pattern with the greater number of element or target-element elements that have a type attribute
  5. the pattern with fewer wildcards; a wildcard is an any element, an element element without a type attribute, or a target-element element without a type attribute
  6. the pattern with the higher specified priority; the priority of a pattern is the priority of the rule that contains it; the priority of a pattern is the value of the priority attribute on the rule that contains it
  7. the pattern with the greater number of only qualifiers
  8. the pattern with the greater number of position qualifiers
  9. the pattern with the greater number of attribute specifications

When determining which of two matching patterns is the more specific, the above criteria are applied in order until one of the criteria identifies exactly one of the patterns as most specific.

For construction rules, it is an error if, for any source element, there is not a unique matching pattern that is more specific than all other matching patterns.

3.3. Actions

3.3.1. Overview

When the rule that is to be applied to the source element has been identified, the action part of the rule is invoked. The structure of the elements comprising the action represents the structure of flow objects to create.

Flow object elements may be combined with literal text (which generates character flow objects) and programmatically generated text (eval element) to create a flow object sub-tree.

<rule>
  <!-- pattern -->
  <target-element type="chapter"/>

  <!-- action -->
  <sequence>
    <horizontal-rule/>
    <paragraph space-before="2pt">
      Chapter
      <eval>formatNumber(element.childNumber(),'001')</eval>
      :
      <children/>
    </paragraph>
    <horizontal-rule/>
  </sequence>
</rule>

Note: this example uses DSSSL core flow objects.

3.3.2. Characteristics as Attributes

The characteristics of the flow objects are applied as attributes of the element representing the flow object. For the HTML core flow objects, CSS properties can be directly applied as attributes without the use of the HTML STYLE attribute, as in this example:

<rule>
  <target-element type="para"/>
  <DIV font-family="Courier"
       font-size="12pt"
       font-style="normal"
       text-align="justify"
       margin-top="10pt"
       margin-bottom="6pt">
    <children/>
  </DIV>
</rule>

Note: this example uses HTML/CSS core flow objects.

All attributes of flow object elements are of type string.

3.3.3. Selection within an Action

Selection within an action controls which source elements are processed after a rule fires. There are two elements used, the children element and the select element. The children element processes the immediate children of the source element while the select element processes either the children or the descendants of the source element, and provides powerful filtering through the use of patterns.

This example creates a display-group for a chapter element and then processes its immediate children.

<rule>
  <target-element type="chapter"/>
  <display-group>
    <children/>
  </display-group>
</rule>

Note: this example uses DSSSL core flow objects.

The above example could also be written using the select element with the from attribute set to children.

<rule>
  <target-element type="chapter"/>
  <display-group>
    <select from="children"/>
  </display-group>
</rule>

Note: this example uses DSSSL core flow objects.

The values of the from attribute are:

  • children. The children of the element are processed, the default.
  • descendants. The descendants of the element are processed.

The select element, by default, processes the immediate children of the source element. To process all of the descendants of the source element the from attribute can be set to descendants. This example processes all of the heading elements contained in the book element.

<rule>
  <target-element type="book"/>
  <paragraph>
    <select from="descendants">
      <target-element type="heading"/>
    </select>
  </paragraph>
</rule>

Note: this example uses DSSSL core flow objects.

Filters can be added to the select element to further control which elements are processed. Only elements that match the filter pattern are processed. The filter pattern uses the same syntax as the pattern part of the rule. In this example, after creating a paragraph for the employee element, the exempt children are selected for processing.

<rule>
  <target-element type="employee"/>
  <paragraph>
    <select>
      <target-element type="exempt"/>
    </select>
  </paragraph>
</rule>

Note: this example uses DSSSL core flow objects.

Multiple children or select elements can be used within a single action to do simple reordering. The following example creates two tables. The first table is filled with domestic sales while the second table is filled with foreign sales.

<rule>
  <target-element type="product"/>
  
  <display-group>
    <table>
      <select from="descendants">
        <element type="sales">
          <target-element type="domestic"/>
        </element>
      </select>
    </table>
    <table>
      <select from="descendants">
        <element type="sales">
          <target-element type="foreign"/>
        </element>
      </select>
    </table>
  </display-group>
</rule>

Note: this example uses DSSSL core flow objects.

By default, the children element and the select element process children of the element matched by the rule's pattern. The ancestor attribute is used to process children relative to an element higher up in the document. This example finds an employee's department and then processes the group children of the department.

<rule>
  <target-element type="employee"/>
  <paragraph>
    <select ancestor="department"/>
      <target-element type="group"/>
    </select>
  </paragraph>
</rule>

Note: this example uses DSSSL core flow objects.

3.3.4. Flow Object Macros

Actions can also be factored out of similar rules into macros for reuse. Macros allow authors to create aggregate flow objects and refer to the composite as if it were a single flow 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.

<define-macro name="warning-para">
  <box>
    <paragraph>
      Warning!
      <contents/>
    </paragraph>
  </box>
</define-macro>

<rule>
  <target-element type="warning"/>
  <warning-para font-size="14pt">
    <children/>
  </warning-para>
</rule>

Note: this example uses DSSSL core flow objects.

The contents element in the macro refers to the contents of the macro reference (in this case the children element).

Macros allow arguments and argument defaults to be specified with the arg element. Defaults can be assigned to the arguments. The arguments can be accessed inside the macro with the expression syntax (“=” + argument name). This example defines a macro for a list-item with arguments controlling the indent and the string to use as a marker (i.e. bullet).

<define-macro name="list-item">
  <arg name="marker" default=""/>
  <arg name="indent" default="0.25in"/>
  <paragraph
      first-line-start-indent="=-indent"
      start-indent="=indent">
    <line-field field-width="=indent">
      <eval>marker</eval>
    </line-field>
    <contents/>
  </paragraph>
</define-macro>

<rule>
  <target-element type="item"/>
  <list-item marker="+">
    <children/>
  </list-item>
</rule>

Note: this example uses DSSSL core flow objects.

For users that wish to create stylesheets that are valid with respect to a single, fixed DTD for all XSL stylesheets, there is an alternative syntax for macro invocation.

<rule>
  <target-element type="item"/>
  <invoke macro="list-item">
    <arg name="marker" value="+">
    <children/>
  </invoke>
</rule>

3.4. Default Construction Rule

There is a built-in default construction rule to allow recursive processing to continue in the absence of a successful pattern match. The author is free to override the default rule by specifying his own default rule.

<rule>
  <target-element/>
  <children/>
</rule>

4. Styles

An XML element can be associated with flow object characteristics through style rules. Style rules, like construction rules, consist of a pattern and an action. The pattern selects the element from the source document while the action specifies flow object characteristics.

Here is an example of a simple style rule that makes all emph elements bold:

<style-rule>
  <target-element type="emph"/>
  <apply font-weight="bold"/>
</style-rule>

An important distinction between style rules and construction rules is that style rules do not create flow objects.

Style rules support the CSS feature that more than one stylesheet rule can contribute properties (characteristics) to an element's presentation. For example, the following CSS rules would make the font-weight of strong elements inside of h1 elements “bold” as well as making their color “red”.

h1 {font-weight:bold; color:blue}
h1 strong {color:red}

The above CSS could be written in XSL as:

<style-rule>
  <target-element type="h1"/>
  <apply font-weight="bold" color="blue"/>
</style-rule>

<style-rule>
  <element type="h1">
    <any>
      <target-element type="strong"/>
    </any>
  </element>

  <apply color="red"/>
</style-rule>

4.1. Named Styles

A style object contains a set of characteristics. The definition of a style object creates a named style. A flow object element can specify a style name as the value of the use attribute. A style rule can use an element with the style name instead of apply as its action. This allows augmenting a named style with characteristics from the style rule.

The following example creates a style named “title-style” and uses it in a style rule and in a construction rule.

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

<style-rule>
  <target-element type="title"/>
  <title-style quadding="center"/>
</style-rule>

<rule>
  <element type="chapter">
    <target-element type="heading"/>
  </element>
  <paragraph use="title-style" quadding="start">
    <children/>
  </paragraph>
</rule>

Note: this example uses DSSSL core flow objects.

For users that wish to create XSL that is valid with respect to a single, fixed DTD for all XSL stylesheets, there is an alternative syntax for using named styles.

<style-rule>
  <target-element type="title"/>
  <apply use="title-style" quadding="center"/>
</style-rule>

4.2. Inline Style

For the rare cases where it is inconvenient to fully define the formatting style in the stylesheet, XSL provides two mechanisms for source document overrides of style characteristics:

  • Adding formatting attributes to an element instance and a style attribute that references these in the rule for that element type in the stylesheet.
  • Adding an id attribute on a particular element instance and adding a rule at the beginning of the instance with a pattern matching the value of this id.

Inherited characteristics can be specified on a particular instance of an element type in the source document. They are qualified by the xsl namespace. (The viability of this solution depends on the XML namespace proposal submitted to the W3C).

<para xsl::font-weight="bold">

Note: This example illustrates source document markup, not XSL stylesheet markup.

The stylesheet rule for the element type may include a use attribute on a flow object element with a value #source to apply any attributes on the source element in the xml namespace whose name matches an inherited DSSSL characteristic.

<rule>
  <target-element type="para"/>
  <DIV use="#source">
    <children/>
  </DIV>
</rule>

Note: this example uses HTML/CSS core flow objects.

In this case, the characteristics specified on the instance will override any characteristics specified in the stylesheet.

A document instance may contain XSL rules at the beginning. These rules may have patterns identifying elements with specific ids.

<rule>
  <target-element id="myoverride"/>
  <DIV font-weight="bold">
    <children/>
  </DIV>
</rule>
...
<para id="myoverride">

Note: this example uses HTML/CSS core flow objects.

5. Modes

Sometimes source elements need to be displayed in several different places. For example, a title element may need to be displayed in a table of contents as well as in the body. In each place the source element may need to be formatted differently.

This can be achieved in XSL using a mode. An element may be processed with respect to a named mode. A rule can be associated with a named mode using the mode attribute on a rule. Such a rule can only be invoked when an element is being processed using the rule's mode. The children and select elements can change to a named mode by specifying a mode attribute.

<rule>
  <root/>
  <HTML>
    <BODY>
      <DIV name="table-of-contents">
       <children mode="toc-mode"/>
     </DIV>
     <children/>
    </BODY>
  </HTML>
</rule>

<rule>
  <target-element type="title"/>
  <DIV font-size="14pt" font-weight="bold">
    <children/>
  </DIV>
</rule>

<rule mode="toc-mode">
  <target-element type="title"/>
  <DIV font-size="12pt">
     <children/>
  </DIV>
</rule>

Note: this example uses HTML/CSS core flow objects.

6. Flow Objects

6.1. DSSSL Core Flow Objects

DSSSL flow objects support a powerful and extensible formatting model. The model is internationalized so that a single stylesheet can be used to format documents in natural languages with different writing directions. The following are the subset of DSSSL flow objects that are proposed for use in XSL. Refer to the DSSSL standard for more information on these flow objects and their characteristics.

  • scroll—used for online display
  • paragraph, paragraph-break—used for paragraphs
  • character—used for text
  • line-field—used for lists
  • external-graphic—used for including graphic images
  • horizontal-rule, vertical-rule—used for horizontal rules (note that the DSSSL “rule” flow object will be split into these two rules to eliminate the name conflict). (like HR in HTML) and vertical rules
  • score—used for underlining and scoring
  • embedded-text—used for bi-directional text
  • box—used for borders
  • flow objects for tables
    • table
    • table-part
    • table-column
    • table-row
    • table-cell
    • table-border
  • sequence—used for specifying inherited characteristics
  • display-group—used for controlling the positioning of groups of displayed flow objects
  • simple-page-sequence—used for simple page layout
  • link—used for hypertext links

6.2. HTML/CSS Core Flow Objects

To reduce the initial barriers to adoption, a core set of HTML flow objects is recommended in addition to the core DSSSL flow objects. The HTML/CSS formatting model is smewhat different from the DSSSL model, and the inclusion of the HTML/CSS flow objects will make it possible to use XSL with HTML and CSS. It simplifies the targeting of HTML as the output format, and retains consistency of the object model and dynamic behaviors.

The characteristics on the flow objects consist of the sum of the CSS property set plus the original HTML attributes where the functionality is not provided by the former. Refer to the HTML 3.2 and CSS specifications for more information.

  • SCRIPT
  • PRE
  • HTML
    • TITLE
    • META
    • BASE
  • BODY
  • DIV
  • BR
  • SPAN
  • TABLE
    • CAPTION
    • COL
    • COLGROUP
    • THEAD
    • TBODY
    • TFOOT
    • TR
    • TD
  • A
  • FORM
    • INPUT
    • SELECT
    • TEXTAREA
  • HR
  • IMG
    • MAP
    • AREA
  • OBJECT
    • PARAM
    • FRAMESET

The following example shows a rule for simple lists using the HTML/CSS core flow objects. The first rule provides margins and indenting for the entire list; the second provides margins for individual list items. A negative indent and fixed width SPAN on a list item allow the item number to be generated and placed to the left of each item.

<rule>
  <target-element type="list"/>
  <DIV margin-left="36pt" margin-top="12pt">
    <children/>
  </DIV>
</rule>

<rule>
  <element type="list">
    <attribute name="type" value="enum"/>
    <target-element type="item"/>
  </element>
  <DIV margin-top="4pt"
       margin-bottom="4pt"
       text-indent="-24pt">
    <SPAN width="24pt" height="12pt">
      <eval>
        formatNumber(childNumber(element),"1") + "."
      </eval>
    </SPAN>
    <children/>
  </DIV>
</rule>

Note: this example uses HTML/CSS core flow objects.

6.3. Extensibility

XSL will provide a mechanism to allow the specification of new flow object classes and characteristics for the new classes, by defining:

  • interfaces for flow object classes and characteristics, and
  • a mechanism in an XSL stylesheet for binding a name of flow object class or characteristic to code that implements these interfaces.

7. Scripting Language

7.1. ECMAScript

The ECMAScript standard provides the basis for the XSL scripting language. ECMAScript is the standardized specification of JavaScript.

7.2. Limited Side-effects

The ECMAScript language supports side-effects. However, unrestricted use of side-effects in XSL would create serious implementation problems for progressive rendering and for handling large documents. In XSL it is an error for code in a construction rule to change a global variable, or any object reachable from a global variable. It is also an error for code to change any object reachable from an object specified as the value of an inherited characteristic.

Enforcing these restrictions would be difficult for XSL implementations that use existing JavaScript implementations; therefore this is not required of XSL implementations. However, the results of applying a stylesheet causing side effects is unpredictable in systems that do not enforce the restrictions.

7.3. Units

The scripting language extends ECMAScript by providing a quantity data type which represents lengths and quantities that are derived from lengths, such as areas and volumes. The base unit is the SI meter. The name for this unit is m.

The following derived units are defined:

  • cm (0.01m),
  • mm (0.001m),
  • in (0.0254m),
  • pc (1/6in), and
  • pt (1/12pc).
<paragraph space-before="=0.5in - 3pt"
           start-indent="=childNumber(element) * 12pt">
  <children/>
</paragraph>

Note: this example uses DSSSL core flow objects.

Device-dependent quantities such as pixels are handled in XSL by using the DSSSL length-spec concept.

7.4. Built-in Functions

A set of built-in functions will be included. These will be a subset of those included in the DSSSL standard.

Since DSSSL names containing hyphens are not valid ECMAScript names, we have to convert them to an internal-caps equivalent. This applies to function names as well as characteristics and other symbolic names when they appear in script.

7.5. Scripting in XSL

The scripting language can be used in XSL in a number of different ways:

At the top-level (outside of any construction rules), variable declarations and function definitions may be specified within a define-script element.

<define-script>
  var defaultFontSize = "12pt";

  function hierarchicalIndent(elementType, element)
  {
    return length(hierarchicalNumberRecursive(
                  elementType, element)) * 12pt;
  }
</define-script>

Note: the DSSSL hierarchicalNumberRecursive function returns an array representing the child numbers of the requested element type at each hierarchical level. Formatting this list produces a numbering system such as the one used in the titles and sub-titles of this document.

If the value of an attribute specifying a characteristic (i.e. within the action) starts with =, then the remainder of the attribute is treated as an ECMAScript expression.

<rule>
  <element type="list">
    <target-element type="item">
  </element>
  <DIV font-size="=defaultFontSize"
       margin-left='=1in + hierarchicalIndent(element, "item")'>
    <children/>
  </DIV>
</rule>

Note: this example uses HTML/CSS core flow objects.

Within an action, an eval element containing an ECMAScript expression may be used to compute generated text. The value returned by the expression is converted to a string and then to a sequence of character flow objects. Alternatively the eval can also contain a sequence of ECMAScript statements. The value returned by a return statement is converted to a string and then to a sequence of character flow objects.

<rule>
  <target-element type="title">
  <DIV>
    <eval>
      formatNumberList(
        hierarchicalNumberRecursive("title", element),
        "", ".")
    </eval>
    <children/>
  </DIV>
</rule>

Note: this example uses HTML/CSS core flow objects.

A select element can filter an arbitrary node list specified by script within the from attribute. This example finds the nearest department ancestor, and returns the manager children of that element.

<select from='=ancestor("department",element)'>
  <target-element type="manager"/>
</select>

Appendix A: Translated selections from the recommended CSS stylesheet for HTML 2.0.

This example shows the use of CSS-compatible style-rules to implement the functionality of the Sample Stylesheet for HTML 2.0 found in Appendix A of Cascading Style Sheets, Level 1. DSSSL core flow objects are used.

<xsl>
  <rule>
    <target-element type="BODY"/>
    <scroll
        font-family-name="iso-serif"
        space-before="1in"
        left-margin="1in"
        space-after="1in"
        right-margin="1in"
        line-spacing="=12pt * 1.1"
        background-color="white"
        color="black">
      <children/>
    </scroll>
  </rule>

  <rule>
    <target-element type="H1"/>
    <target-element type="H2"/>
    <target-element type="H3"/>
    <target-element type="H4"/>
    <target-element type="H5"/>
    <target-element type="H6"/>
    <target-element type="P"/>
    <target-element type="ADDRESS"/>
    <target-element type="BLOCKQUOTE"/>
    <target-element type="PRE"/>
    
    <paragraph>
      <children/>
    </paragraph>
  </rule>

  <rule>
    <target-element type="HR"/>
    <horizontal-rule/>
  </rule>

  <rule>
    <target-element type="B"/>
    <target-element type="STRONG"/>
    <target-element type="I"/>
    <target-element type="EM"/>
    <target-element type="CITE"/>
    <target-element type="VAR"/>
    <target-element type="TT"/>
    <target-element type="CODE"/>
    <target-element type="KBD"/>
    <target-element type="SAMP"/>
    <target-element type="SPAN"/>

    <sequence>
      <children/>
    </sequence>
  </rule>

  <rule>
    <target-element type="IMG"/>
    <external-graphic href='=element.href'/>
  </rule>

  <style-rule>
    <target-element type="H1"/>

    <apply space-before="1em"
           space-after="1em"
           quadding="center"
           font-weight="bold"
           font-size="24pt"/>
  </style-rule>

  <style-rule>
    <target-element type="H2"/>
    
    <apply space-before="1em"
           space-after="1em"
           font-weight="bold"
           font-size="18pt"/>
  </style-rule>

  <style-rule>
    <target-element type="H3"/>
    
    <apply space-before="1em"
           space-after="1em"
           font-posture="italic"
           font-size="14pt"/>
  </style-rule>

  <style-rule>
    <target-element type="H4"/>
    
    <apply space-before="1em"
           space-after="1em"
           font-weight="bold"/>
  </style-rule>

  <style-rule>
    <target-element type="H5"/>
    
    <apply space-before="1em"
           font-posture="italic"/>
  </style-rule>

  <style-rule>
    <target-element type="B"/>
    <target-element type="STRONG"/>

    <apply font-weight="bold"/>
  </style-rule>

  <style-rule>
    <target-element type="I"/>
    <target-element type="CITE"/>
    <target-element type="EM"/>
    <target-element type="VAR"/>

    <apply font-posture="italic"/>
  </style-rule>

  <rule>
    <target-element type="PRE"/>
    <target-element type="TT"/>
    <target-element type="CODE"/>
    <target-element type="KBD"/>
    <target-element type="SAMP"/>

    <apply font-family-name="iso-monospace"/>
  </rule>

  <style-rule>
    <target-element type="ADDRESS"/>

    <apply font-posture="italic"
           start-indent="3em"/>
  </style-rule>

  <style-rule>
    <target-element type="BLOCKQUOTE"/>

    <apply font-posture="italic"
           start-indent="3em"
           end-indent="3em"/>
  </style-rule>

Appendix B: Example Stylesheet with Scripting

The following stylesheet is an XSL translation of selections from Jon Bosak's DSSSL stylesheet for reading HTML. It shows the combination of declarative constructs with script to accomplish the formatting of lists. This example uses DSSSL core flow objects.

<xsl>
  <define-script>

    var bfSize = 10pt;
    var paraSep = bfSize/2.0;
    var blockSep = paraSep*2.0;
    var bodyStartIndent = 6pc;
    var lineSpacingFactor = 1.1;

    function inlist(element) 
    {
      return
        haveAncestor(element, "OL") |
        haveAncestor(element, "UL") |
        haveAncestor(element, "DIR") |
        haveAncestor(element, "MENU") |
        haveAncestor(element, "DL");
    }

    function olstep(element)
    {
      var x = length(hierarchicalNumberRecursive(element, "OL")) % 4;
      if (x == 1) return 1.2*bfSize;
      if (x == 2) return 1.2*bfSize;
      if (x == 3) return 1.6*bfSize;
      if (x == 0) return 1.4*bfSize;
    }
  </define-script>

  <define-style name="p-style"
    font-size="=bfSize"
    line-spacing="=bfSize * lineSpacingFactor"/>

  <rule>
    <target-element type="OL"/>

    <display-group
        space-before="=inlist(element) ? paraSep : blockSep"
        space-after="=inlist(element) ? paraSep : blockSep"
        start-indent="=inlist(element) ? inheritedStartIndent(element) : bodyStartIndent" >
      <children/>
    </display-group>
  </rule>

  <rule>
    <element type="OL">
      <target-element type="LI"/>
    </element>

    <paragraph use="p-style"
        space-before='=attributeString(ancestor("OL"), "compact") ? 0 : paraSep'
        start-indent="=inheritedStartIndent(element) + olstep(element)"
        first-line-start-indent="=-olstep(element)" >
      <line-field field-width="=olstep(element)">
        (
        <eval>
          var child = childNumber(element);
          var x = hierarchicalNumberRecursive("OL") % 4;
          if (x == 1) return formatNumber(child, "1");
          if (x == 2) return formatNumber(child, "a");
          if (x == 3) return formatNumber(child, "i");
          if (x == 0) return formatNumber(child, "a");
        </eval>
        )
      </line-field>
      <children/>
    </paragraph>
  </rule>

  <rule>
    <element type="OL">
      <element type="LI">
        <target-element type="P"/>
      </element>
    </element>

    <paragraph use="p-style"
        start-indent="=inheritedStartIndent(element) + olstep(element)"
        first-line-start-indent="=-olstep(element)" >
      <children/>
    </paragraph>
  </rule>

</xsl>

Appendix C: A DTD for XSL Rules

<!-- This DTD is for exegesis only.  It assumes that the
action parameter entity has been defined as an or-group
of flow object elements. The style parameter entity is
used to represent an or-group of the apply element
and styles defined with define-style. -->

<!ENTITY % pattern "(root | (target-element | element | any)*)">

<!ELEMENT rule (%pattern;, %action;) >

<!ELEMENT style-rule (%pattern;, %style)>

<!ELEMENT root  EMPTY>

<!ATTLIST (rule | style-rule)
        priority   NUMBER     #IMPLIED
        importance NUMBER     #IMPLIED
        mode       NAME       #IMPLIED>

<!ELEMENT target-element
        (attribute*, (element+ | any)?)    -(target-element)>

<!ELEMENT element
        (attribute*, (target-element | element | any)?) >

<!ELEMENT any  EMPTY >

<!ATTLIST (target-element | element)
        type      NAME        #IMPLIED
        id        NAME        #IMPLIED
        class     NAME        #IMPLIED
        only    (of-type|of-any)  #IMPLIED
        position  (first-of-type|last-of-type|first-of-any|last-of-any)  #IMPLIED
>

<!ELEMENT attribute EMPTY >

<!ATTLIST attribute
        name     NAME        #REQUIRED
        value   CDATA      #IMPLIED
        has-value (yes|no)    'yes'
>

Appendix D: Acknowledgements

We are grateful to Jon Bosak and Håkon Wium Lie for their comments and feedback.