NOTE-XSL.html
· Submitted to W3C on 27 August 1997 ·
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
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.
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:
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:
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:
XSL incorporates the subset of DSSSL flow object classes and characteristics that was specified in DSSSL-O.
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).
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.
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.
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" ?>
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.
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.
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:
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.
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>
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>
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.
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>
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:
importance
attribute on the rule that contains
it; this allows the CSS !important
feature to be supported
id
attributes
class
attributes
element
or
target-element
elements that have a type
attribute
any
element,
an element
element without a type
attribute, or
a target-element
element without a type
attribute
priority
attribute on the rule that contains
it
only
qualifiers
position
qualifiers
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.
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.
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.
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.
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>
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>
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>
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>
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:
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.
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.
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.
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.
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.
XSL will provide a mechanism to allow the specification of new flow object classes and characteristics for the new classes, by defining:
The ECMAScript standard provides the basis for the XSL scripting language. ECMAScript is the standardized specification of JavaScript.
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.
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.
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.
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>
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>
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>
<!-- 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' >
We are grateful to Jon Bosak and Håkon Wium Lie for their comments and feedback.