Magazine |
| | Community |
| | Workshop |
| | Tools & Samples |
| | Training |
| | Site Info |
|
|
||||||||
|
September 11, 1997
Submitted to the W3C on August 27, 1997
Download this document in Microsoft Word (.DOC) format (zipped, 19.4K).
This document is a NOTE made available by the World Wide Web Consortium (W3C) 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 the W3C.
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.
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 structured 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 DSSSL 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 with 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 that identifies elements of type emph and an action that 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 that 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 attributes, 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:
The only qualifier specifies whether the source element has any siblings or not. Its values are:
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:
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:
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 who 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 who 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 that 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:
<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.
© 1998 Microsoft Corporation. All rights reserved. Terms of use.
Did you find this article useful? Gripes? Compliments? Suggestions for other articles? Write us!
© 1998 Microsoft Corporation. All rights reserved. Terms of use.