[This local archive copy (text only) mirrored from the canonical site: http://www.microsoft.com/xml/xsl/tutorial/tutorial.htm, 980127; links may not have complete integrity, so use the canonical document at this URL if possible.]
January 7, 1998
XSL is a stylesheet language designed to be used with XML data and documents. A few words about XML will help make the need for XSL clear.
XML allows data or content to be marked up using tags invented by the author. The tag names can then provide author-specified information about the content within the tags. For instance, if I wanted to add "change-date" information to an HTML document, I would have to put it in a paragraph, table cell, or some other element that HTML has already provided:
3 October 1997
However, when someone else (or some program) looks at the document, all they see is the paragraph or table cell with some text in it. Even if one could recognize the string '3 October 1997' as a date, one would have no idea what that date represents. Is that date a birth date? a creation date? an expiration date? In fact, the line above really only indicates that the string of characters '3 October 1997' should be displayed as a paragraph.
In an XML document, I can mark up the date with tags that better describe what that date is:
Now when someone looks at my document, they can better tell the meaning of the string within the tags: it represents a "change date".
Such descriptive mark-up, or "semantic" mark-up, is a key goal of XML. With XML, Web authors can now mark up their content or data "semantically," according to the meaning of the data. Consequently, they can better communicate the relevance of their content or data.
Once the "change-date" has been "semantically" marked up, however, it no longer conveys any information about how the content is to be displayed. Should the date be presented as a paragraph or a table cell? Is it a data point in a graph? Should it be displayed at all? Unlike HTML, which defines the display behavior for each of its elements, XML says absolutely nothing about how the data is to be displayed.
This is where XSL comes in. XSL allows the author to apply formatting operations to XML elements. XSL is a language in which the author can indicate that the 'change-date' element should be displayed as a paragraph, in blue, and in italic. XSL is not the only way to display XML data. However, it provides you with a simple declarative solution. Also, because XSL syntax is XML itself, you don't have to learn a whole new syntax to begin writing XSL stylesheets.
Question: What is the difference between a "tag" and an "element"? Answer: In XML (and HTML), "tags" are used to define an "element." An element is comprised of 1) a "start tag" (such as <change-date>) which describes the contents of the element, 2) the contents of the element (such as the text "3 October 1997"), and 3) an "end tag" (such as </change-date>) which closes the element. Often, HTML authors refer to "elements" as "tags," but it is important to understand that a "tag" is only a part of the whole "element."
Question: What is the difference between CSS and XSL? Answer: CSS is a stylesheet language that may also be used with XML. But with CSS, the basic structure of the document cannot be dramatically altered. CSS essentially maps each XML element into a single display object with certain display characteristics (or properties). XSL, in comparison, allows a single XML source element to be mapped into a more complex hierarchy of display objects. For instance, XSL can add a legal disclaimer to the end of a document, generate a table of contents, and calculate and display chapter and section numbers. In addition, XSL is made extensible through script, flow object macros (not yet implemented) and extensible flow object types (not yet implemented).
The XSL processor uses an XSL stylesheet to transform XML data into an HTML document. From the command line, the XSL processor is given an XML data file followed by an XSL stylesheet. It then takes those two files and uses them to produce an HTML file:
The content of the newly created HTML file comes from the XML data source; the display structure of the newly created HTML file comes from the XSL stylesheet. In processing the two files, the XSL processor examines the XSL stylesheet to discover which display structure applies to which XML source elements. As a result, the XSL processor creates a display structure that is driven by the content of the XML data source, and yet can be wholly independent of that source's structure.
The syntax for XSL is based on XML, and the display structures you will construct with XSL will consist of many familiar HTML flow objects. Learning XSL, therefore, does not require learning a new language. You can build on your existing knowledge of XML and HTML, enabling you to become fluent in XSL quite quickly.
Question: Is HTML the only output format? Answer: XSL is designed to apply style independently of the output format. Thus, a single stylesheet could be used to generate HTML, RTF, raw text, etc. In the Microsoft XSL Processor Technology Preview Release, we only support the generation of HTML output.
Note: The Microsoft XSL Processor is based on the Proposal for XSL submitted to the W3C (see http://www.w3.org/TR/NOTE-XSL.html ). Areas not implemented in this release include children patterns, flow object macros, named styles, the DSSSL flow objects, class and id definitions, importance and priority attributes, units in ECMAScript, and the importing of stylesheets.
The basic building block of XSL is the construction rule. A construction rule describes how a particular element is to be transformed into displayable output. The construction rule consists of two parts: a pattern identifying a type of XML source element and an action describing what to do with elements that match this pattern.
The graphic below represents the role of the construction rule in the process which transforms XML data into an HTML document. Notice how the pattern identifies a single source element at a time and the action transforms that single source element into a display structure within the HTML document. An important concept behind XSL is that it uses rules to create display structures from individual source elements.
The following stylesheet is an example of an XSL stylesheet's basic structure. The stylesheet in this particular example has a single construction rule which displays the contents of a <change-date> element as a blue, italic paragraph:
Note: The above example uses CSS properties on its flow objects. CSS properties may be applied directly as attributes. See the Flow Objects lesson for more information.
The pattern in the above case (<target-element type="change-date">) "targets" (applies to) <change-date> elements.
The action in the above case (<P color="blue" font-style="italic"><children/></P>) indicates that the contents of the <change-date> element should be placed within a <P> element and that the <P> element should have the attribute style="color:blue;font-style:italic".
Now let's see what happens when you process an XML document using an XSL stylesheet.
Processing the following XML document
using the XSL stylesheet above, the <change-date> element will result in the following HTML code:
3 October 1997
The XML source document drives the transformation process. The XSL processor goes through the source document element by element and, for each one, looks through the stylesheet for an applicable rule. This is essentially a "recursive" process.
Recursion is a common programming technique that allows complex tasks to be broken down into manageable pieces. In XSL, the "manageable piece" is the construction rule, which defines how a single element is transformed into a piece of formatted output. Because of recursion, the XSL processor is able to construct complex final output from a few simple rules.
Question: Do XSL construction rules cascade like CSS rules? Answer: No. Since CSS is not changing the structure of the document, it is easy to describe how these properties can be merged, or "cascaded," into a single set of property values. XSL construction rules define a new structure for the output, so there is no easy way to merge structures and still get predictable results. Thus only one construction rule is processed per source element. The best rule is selected among applicable rules using an arbitration process. Although only one construction rule can be processed per element, style properties can still be merged using style rules. See the lessons on Rule Arbitration and Style Rules for more information.
The construction rule contains at least one <target-element> element. This <target-element> element identifies the elements from the XML source document to which the construction rule applies. The most basic form of a pattern matches XML source elements of a certain type without regard to the context of those elements:
The above <target-element> element matches <title> elements in the XML source document. In the following example, the above pattern is combined with an action dictating that all elements that match the pattern are to be displayed in a italic span.
Often it is important to describe the element's context as well as its type. For the following XML document
we may want the <title> to be formatted differently depending on its position within the document. For instance, section titles should probably be formatted differently from new-item titles.
Ancestor relationships can be identified through the <element> element. If we include the parent of the target element in the pattern, we can distinguish between the title of the <section> element and the title of the <new-item> element. We can then apply distinct formatting characteristics to <title> elements in these different contexts. According to the following XSL stylesheet, the section title is to be formatted as a blue, italic paragraph, while the new-item title is to be formatted as a bold span.
The <element> element used in the above stylesheet describes a parent relationship in the source context that must be present for the pattern to match.
While there can only be one <target-element> element in a pattern (after all, the pattern identifies a single type of XML source element), there may be multiple <element> elements, representing multiple levels of ancestors. The following pattern is valid XSL (although it would be unusual to create a pattern even this extensive):
Note: Currently, XSL only provides for parent-child relationships. Sibling relationships are not defined. This means that each <element> element may only have a single <element> or <target-element> child.
Patterns can also include attributes, wildcards, and other pattern qualifiers. We will learn more about these and the pattern's other features in later lessons.
When a pattern identifies (or matches) a type of XML source element, the action portion of the rule is used to create the formatted output. The action describes what the output structure should be, what formatting properties to apply, and how to process the children of the source element.
The following rule includes a basic action that places the contents of the target elements into <DIV> elements. <DIV> represents a specific kind of formatting operation or formatted output. In this case, <DIV> represents the functionality of the HTML <DIV> element.
Now let's step through how the XSL processor would apply the above rule to the following XML source.
First, note that the pattern will match any element because an element type is not specified (see Wildcards ).
Second, the action (<DIV><children/><DIV>) will be applied to each matching element. The <children/> element informs the processor to "insert the results of processing the target element's children here" (in this case, within the <DIV> element). Beginning with the <document> element, the <children/> action outputs the "result of processing" the <chapter> element. Of course, in order to determine what this result will be, the processor must first process the <chapter> element according to the appropriate rule (in this case, the same one).
Here is where the recursive process really takes off. For, "the result of processing" the <chapter> element is "the result of processing" the <title> element followed by "the result of processing" the <topic> element.
Likewise, the result of processing the <title> element is "the result of processing" the text "XSL Overview." And, as you might now expect, the result of processing the <topic> element is "the result of processing" the text "Overview of XSL and its extensibility."
This process concludes with the processing of the text, which returns the text itself.
The XSL processor does quite a bit of work during the recursive process. And because it works so hard, we don't have to. In the above example, the recursive process allows us to write one rule and have our entire document processed. Even if this document contained many more chapters, thanks to the recursive process, we could still process the document using the same simple rule.
Let's now look at the final result of this process. The following code is the HTML created by the processor after it has completed the recursive process.
The above example may seem trivial, but what we have just done is transformed XML that is semantically marked up into a structure based on display characteristics. By just changing the type of output objects and their style properties, we can generate very complex output using the same simple set of rules. In addition, as our documents get more complex, the same simple rules remain adequate to process them.
The action does not directly create HTML, but it does create an intermediate structure consisting of flow objects, each describing a specific formatting task to apply to the content. The following rule contains three flow objects (<DIV>, <HR>, <P>):
The End
As you would expect, the above example will result in the creation of an HTML document with <DIV>, <HR>, and <P> elements. XSL's inclusion of the HTML/CSS flow objects (see DHTML Reference ) is designed to make it obvious what the final output will be (since we are familiar with the specific formatting tasks that HTML provides). However, it is important to note that although the flow objects can look like HTML elements, there are some subtle, yet critical, syntactic differences:
Affects: AREA, BASE, BASEFONT, BGSOUND, BR, COL, COLGROUP, FRAME, HR, IMG, INPUT, ISINDEX, LINK, META, PARAM, WBR.
Affects: DD, DT, LI, OPTION, P, TD, TH, THEAD, TR.
Affects: AREA (NOHREF, NOTAB), DIR (COMPACT), DIV (NOWRAP), DL (COMPACT), FRAME (NORESIZE), HR (NOSHADE), IMG (CONTROLS), INPUT (CHECKED, NOTAB), MENU (COMPACT), OBJECT (DECLARE, NOTAB, SHAPES), OL (COMPACT), OPTION (SELECTED), TABLE (NOWRAP), TD (NOWRAP), TH (NOWRAP), TR (NOWRAP), UL (COMPACT).
This convention ensures that all HTML tags and attributes can be passed through to the output and remain unchanged. Ignoring this convention with attributes risks conflicts in a few cases between HTML attributes and CSS properties of the same name (see below).
Attributes corresponding to CSS properties are listed below. The values of these attributes are detailed in the CSS specification and documentation (see Cascading Style Sheets in Internet Explorer 4.0).
Note: Described within the Proposal for XSL is an alternate set of flow objects that enable more powerful document processing. These flow objects are useful for processing complex documents that require high quality print formatting, multiple writing directions, etc. These objects are a subset of those available in the DSSSL stylesheet language. The DSSSL objects offer more flexible output options, including easier mapping to other output formats like RTF. The Microsoft XSL Processor does not currently support the DSSSL flow objects.
The XSL processor begins processing by looking for a special root rule in the stylesheet with which it can process the top-level element in the document.
The root rule is identified by the special predefined pattern <root/>. The following code is an example of a basic root rule.
The root rule's action determines the top-level flow objects to create. As you've probably already noticed, the above rule would create the basic structure of an HTML document. A construction rule targeting the top-level element would mimic the functionality of the root rule. However, because the root rule is used for special purposes like the one in the above example, it is often convenient to have a <root/> pattern in the rule to allow the rule to stand out.
Question: Are root rules always as simple as the above example? Answer: No. Root rules can contain rather large actions. The above example could be expanded to include a <HEAD> element containing a <TITLE> element, as well as, any generated "front-matter" and "rear-matter" within the body. Often, the root rule defines nearly the entire page, with other rules just formatting certain XML source data for display within that page.
It might be useful at this point to take a look at the root rule in the sample.xsl and alternate.xsl stylesheets. Notice how the rather complex root rule in alternate.xsl describes the basic display structure of the entire document.
If no other rule applies to an element, a built-in rule kicks in. This prevents unknown elements (ones with no appropriate XSL rule) from halting the recursive process. A default rule targets all source elements and applies no formatting to them:
You don't have to include this default rule in your stylesheet (after all, it's built in). However, you may want to specify your own default rule which defines special processing for elements not handled elsewhere.
Here's one that not only displays in the color blue all unhandled elements, but allows you to run the mouse over the now blue contents of an unhandled element and view its tag name. I often use this during the development of a stylesheet to show me the source elements for which I still need to create rules.
Just as there is a built-in default rule, there is also a built-in root rule. If no root rule is specified, the following built-in one will be used.
When generating an entire HTML document (not just a fragment), you will want to override the default root rule with something like this:
A nice effect of XSL providing built-in default and root rules is that you are always assured of getting output even if your stylesheet is not complete or, even, completely empty.
When an element matches more than one pattern, the most specific pattern will be used. For instance, a stylesheet may contain the following rules:
If you look closely at the above rules, you'll notice that they each target <stock> elements. The question now is which of the two rules is most specific, and, therefore, the most appropriate to apply. Intuitively, the first pattern seems to describe a more specific pattern than the second, for describing an element as a <stock> element within a <watch-list> element seems more precise than simply describing the same element as a <stock> element. So we might expect that the first pattern should take precedence and its corresponding action applied.
Most of the time the decisions made by the XSL processor will match your intuition, as would have been the case with the previous example. However, in tricky situations it may be useful to know how the XSL processor chooses one particular rule over another.
The XSL processor first determines which rules actually apply to a specific element. If there is more than one, it analyzes the patterns in those rules to see which is the most specific. The processor's analysis of each pattern's "specificity" is based on a pre-determined set of criteria.
The XSL processor goes through these steps (in this order) when comparing the "specificity" of the patterns:
Note: The features described in steps 1, 2, 3, and 6 have yet to be implemented.
Hint: In general, the more descriptive a pattern is (the more ancestors, attributes, qualifiers it has), the more specific the rule is judged to be.
Note that arbitration rules do not always guarantee that a single choice will be made. For instance, two identical patterns cannot be narrowed down to one by the arbitration process. In the case of two rules having identical patterns, the rule closest to the end of the XSL document takes precedence.
Patterns can contain wildcards in their ancestor relationships. The pattern in the following rule matches every child of the <list> element, regardless of its element type.
It is important to point out that the above rule only applies to immediate children of the <list> element. A separate wildcard, <any>, matches zero or more elements in an ancestor context. The following example will match <title> elements that appear arbitrarily deep within the <rear-matter> element.
The following examples show more allowed uses of wildcards.
In addition to <element> and <target-element> elements, the pattern can include <attribute> elements. These <attribute> elements can refer to either the target element or to its ancestors.
The following XML document contains two <list> elements with specified attributes.
In displaying the above document, we may want to format the <list dingbat="step"> element differently from the <list dingbat="number"> element. For instance, let's say we wanted to create the following output:
In order to arrive at the above output, we will need to format each <list> element differently. We can do this if we distinguish between the two <list> elements by adding an <attribute> element to the pattern. With <attribute>, we can specify the attribute values that must be present for the pattern to match:
Once we have distinguished between the two <list> elements, we can then identify <item> elements contained by <list> elements of a certain type:
At this point, we can now write a stylesheet that will display our data the way we want it displayed:
As shown in the examples, <attribute> elements can be placed within any <element> or <target-element> elements. In addition to this, multiple <attribute> elements can be specified for each <element> or <target-element> element.
Once you begin writing XSL stylesheets, you will find it is often useful to know if an attribute has an assigned value without knowing the specific value of that attribute. To do so, instead of using value, use has-value. The possible values for has-value are "yes" or "no":
There will be times when you will want to define special processing for the first or last elements in a group. XSL provides this functionality with the position qualifier. For instance, the last paragraph of a magazine article often terminates with a little square character or some other dingbat:
In the above rule, the position attribute is used to isolate the last paragraph. Note that even if someone changed the source document (added more paragraphs), the above rule would still apply the desired formatting to the final paragraph. For another example of how the position qualifier can be used to dynamically format an XML document, let's look at the following XML data:
Through the use of the position qualifier, three separate rules could be created to apply different formatting to the first, last, and remaining items of a group. In the example below, the first <stock> element is formatted as a <DIV> element containing an <HR> (horizontal rule) element followed by the symbol and price. The middle stocks of the group have no horizontal rule, and the last stock contains the symbol and price followed by the horizontal rule.
Processing the <investments> element using the above XSL stylesheet, will result in an HTML document that displays the following in your browser:
Of course, you could enhance your "stocks" style sheet by further formatting the <symbol> and <price> elements.
If also inclined, you could display the first child of the <investments> element differently than the rest with the position="first-of-any" attribute:
Applying the above rule to the <investments> element would cause the first <stock> element's contents to be displayed in the color blue.
The values of the position qualifier are
The "-of-type" values indicate the element's position relative to sibling elements of the same type, and the "-of-any" values indicate the element's position relative to any sibling elements, regardless of their type.
In addition to position, a pattern may detect whether an element is an only child. This is often useful when applying special formatting for both the first and last items in a group. For instance, there might exist only one item in the group, meaning the item is both first and last. According to the following rule, when there is only one "stock" in the "stocks" group, horizontal rules are added both before and after the children.
The values of the only qualifier are:
As with the position qualifiers, the "of-type" value indicates uniqueness relative to sibling elements of the same type, and the "of-any" value indicates uniqueness relative to any sibling elements, regardless of their type.
For convenience, a rule may contain multiple patterns. If any one pattern matches, the action is applied. This saves some typing for similar rules.
Hint: The last element in the <rule> is always assumed to be the action.
One aspect of XSL that makes it so powerful is its ability to filter and reorder elements. The <select-elements> element enables this functionality allowing you to select which elements you would like to have processed.
The <select-elements> element is part of the action, its purpose being to replace the <children/> element with a more specific directive.
Through the same methods available within the pattern for the rule, the "filter pattern" within the <select-elements> element allows you to specify the context of the exact children you wish to process. For instance, within the following <select-elements> element is the <target-element/> wildcard which signals the selection of all types of elements (this <select-elements> element is therefore equivalent to the <children/> element):
Hint: The <select-elements> element does contain a pattern, but this pattern is strictly for filtering children and must not be confused with the pattern for the rule.
Although it is possible to mimic the <children/> element using the <select-elements> element, most of the time you will want to use the <select-elements> element to filter out certain children and apply formatting to certain others. Making the pattern within the <select-elements> element more specific allows only certain children to be processed. The element below, for example, processes only <stock> children; no other children are processed at this time.
In the above example, it should be noted that the <stock> element must be an immediate child of the element targeted by the rule. In order to search arbitrarily deep within the source element, you must request this behavior with the from attribute:
The from attribute may have the value "descendants" (search through my children, grandchildren, etc.) or the value "children" (search through my immediate children only). The default value is "children".
Hint: Remember, the <select-elements> element is replacing the <children/> element, and though it contains its own pattern, it is part of the action.
Source elements can be extracted and reordered using multiple <select-elements> elements. For example, with XSL we can extract certain data from the following XML document
and present a particular "view" of that data. The stylesheet below extracts just the stock price and ticker symbol and formats them into a table.
$
This XSL stylesheet will result in the following HTML document:
$ 130
$ 95
Notice how far the flow object structure in the above HTML diverges from the structure of the XML source document. Also, notice how the information shown below (what you would see on your browser) is only a subset of the information available in the XML source document.
MSFT
|
$ 130 |
INTC
|
$ 95 |
There will be occasions when you will want to suppress or hide certain data contained within the source document. XSL provides this functionality.
Hiding is accomplished by simply not creating corresponding output for the element. In order to not create output, all you must do is suppress the processing of children. Leaving the <children/> element out of the action does just that.
In the above example, when <top-secret> elements are found and processed, the contents of the <SPAN> element is output instead of the contents of the <top-secret> element. Remember, without the <children/> or <select-elements> element, the recursive process does not take place. Therefore, the contents of the target elements (in this case, the contents of the <top-secret> elements) are not processed.
To remove something without a trace, the <empty/> element may be used, indicating the intentional lack of flow object output.
CSS (Cascading Style Sheets) allows several rules to simultaneously apply to a particular source element. When this occurs, the style properties are merged or "cascaded" into a single set of properties. XSL supports this sort of merging, as well, but not by construction rules.
Attempting to merge construction rules poses some difficulties. If one rule specifies a table cell and another specifies a paragraph, how can we merge these two rules and still arrive at a predictable outcome? XSL gets around such difficulties by including another type of rule: the style rule.
The <style-rule> element, like the <rule> element, contains a pattern and an action. The syntax of the pattern is the same as it is for construction rules, but the action consists only of the <apply> element. It is within the <apply> element that style properties are defined. Since no output structure is created, the properties can be merged.
In their operation, XSL style rules are nearly identical to CSS rules. Take, for instance, the following two CSS rules:
If we were to apply them to the following XML source element
the contents of the <price> element would be displayed with the properties font-weight:bold, font-style:italic, and color:red.
Likewise, if we were to apply the following two XSL style rules
to the same source element, the same properties would be applied as in the CSS example above.
Style rules cause a set of style properties to be merged, but cannot specify output structure. In order for an XML source element to be displayed, a construction rule containing a flow object must apply to the element. Once a construction rule is found to match a source element, style properties from any style rule that also targets that type of element are merged and passed into the construction rule and applied to the flow object.
The following code is an example of two style rules working in combination with a construction rule.
Applying the above stylesheet to the <stock> element from the previous examples would result in the following HTML code:
Note: Style rules follow the arbitration rules of XSL. The arbitration order is based on the "specificity" defined for CSS and thus supports the familiar cascading order of CSS.
Script can be used to augment the core functionality of XSL in the same manner that script is used to augment an HTML document. XSL specifies ECMAScript as the standard scripting language. Our implementation uses Microsoft JScript, which is ECMAScript and JavaScript compliant.
Scripting within XSL allows you to extend the capability of the language. Within an XSL stylesheet, you can write scripts that will execute during processing time or pass through to be run during browser run-time. Using both types of scripts, you can dynamically create HTML documents that, in turn, are dynamic themselves. For instance, you could write a script intended to execute during processing time that provides a unique ID value for each HTML element in the output document. You could then write a script intended to execute during browser run-time that changes the value of a certain HTML element's color attribute whenever the user runs the mouse over the contents of that element.
In addition to the standard JScript helper functions (see JScript Reference ), XSL includes a set of Built-in Functions and access to the XML Object Model. Each of these features will be explained in detail throughout the ensuing sections.
The easiest way to use scripting within XSL is in the calculation of flow object attribute values. Simply placing "=" as the first character of an attribute value tells the XSL processor that the attribute value should be calculated as a JScript expression. The following code represents the use of JScript to calculate an attribute value (in this case, to calculate a particular font size).
Once the above rule is processed, the resulting HTML flow object will be as follows:
Besides simple numeric expressions, attributes can also involve expressions containing functions and globally defined constants (see Defining Functions and Global Constants):
Often the expression contains values from the source document. In these cases, a simple object model provides access to the currently selected source element (referred to from script as "this"). Each element has a set of properties and methods that can be called to navigate to ancestors or children, peek into attribute values, or examine a chosen element's content. See XML Object Model for a list of the available properties and methods.
In order to fully understand how the object model can be used to discover certain information about the source element, let's take a look at an XML element with an attribute (<album>), that contains another XML element with an attribute (< photograph>):
The rule below targets <photograph> elements, setting the <IMG> flow object's src attribute to the value of the <photograph> element's image-url attribute and the <IMG> flow object's width attribute to the value of the <album> element's width attribute.
Within XSL, JScript can be used to generate text in the output. This gives XSL the ability to number items such as paragraphs or list items, calculate totals, do numeric conversions, or re-format content at the text level.
To insert the result of an expression into the formatted output, enclose the expression to be evaluated inside <eval>. In the following example, the childNumber function determines an element's number in relation to its siblings, and the formatNumber function returns that number as a string. That string is then inserted into the formatted output.
Processing the XML source element below
using the XSL stylesheet discussed above, results in the following output:
Globally defined constants, user defined functions, built-in functions, and the XML Object Model are all available within <eval>, but multiline functions are not. Also, all <eval> elements should evaluate to a string.
Similar to the HTML <SCRIPT> element, the XSL <define-script> element contains functions and global constants. In general, the XSL stylesheet contains one <define-script> element, usually at the beginning of the stylesheet.
The following example involves a <define-script> element in which the function chartBarWidth is defined.
Global variables are discouraged (and are actually not allowed in the official XSL spec) because they can cause "side-effects". For instance, XSL provides no guarantees that the stylesheet will be run only once, or in a particular order, or even in its entirety. If one rule sets a global variable and another rule uses this value, unexpected results can occur.
Global variables can, however, be used safely as constants. You may define these constants in the <define-script> section, set their initial values, and refer to them throughout your stylesheet. Just don't change them later!
The XSL stylesheet below contains both a <define-script> element in which three global constants are defined and a rule referring to those constants:
There will be times when your HTML documents will require dynamic behavior. XSL allows you to institute such dynamic behavior through the <SCRIPT> flow object. The <SCRIPT> flow object is treated as any other flow object - the contents are passed through to the output as text. These scripts can then be executed by the browser. The following XSL rule generates a <SCRIPT> element in the HTML document that allows the user to highlight an element by clicking on the output from that element.
If we were to process the following XML document
using the above rule, the XML data would appear in your browser as it does below (Try clicking on some of the items in the list.):
It is important to understand that when you write scripts within a <SCRIPT> flow object, you are writing scripts that will be executed at browser run-time. This makes such scripts different than those in a <define-script> element. Scripts within a <define-script> element are executed during processing and are used to dynamically create an HTML document rather than make that HTML document dynamic itself.
The following XSL stylesheet incorporates both a <define-script> element and a <SCRIPT> flow object. During processing, the initialState function in the <define-script> element generates the initial state of "white" or "yellow" for each item. During browser run-time, the hiLite function in the <SCRIPT> flow object allows the user to then click on an item to change its color.
If you were to apply the above stylesheet to the XML document from the previous example, the following would be displayed in the browser:
Let's now take a look at the HTML document behind the above output:
Notice how the <SCRIPT> flow object gets passed through to the new HTML document. Also, notice how the function calls associated with the function defined in the <define-script> element have been replaced by strings.
Besides the standard JavaScript functions, XSL makes available the following built-in functions:
The source element upon which a rule operates can be referred to from script as this. Within the context of an element, this may be omitted, and the properties and methods may be called directly. A read-only subset of the full XML Object Model is available for navigation of the source tree.
Hint: Notice how the result of the expression was concatenated with the string 'pt' to produce the value for the property font-size. Because all attribute values are strings, such string concatenation is necessary.
Lesson #20: Evaluating Expressions
Lesson #21: Defining Functions and Global Constants
Hint: You probably couldn't help but notice that the function in the above example is marked as character data. All scripts that you will write in XSL should be treated as character data to ensure that they will be passed through to the output document as you intend.
Lesson #22: Creating Dynamic HTML
Hint: Notice that the onclick attribute is the subject of both the XSL script and describes display-time behavior. Like the contents of the <SCRIPT> flow object, XSL treats event attributes such as onclick as text. Consequently, XSL allows the values of event attributes to be calculated with the "=" syntax and the results of such calculations to be output to the HTML document.
Lesson #23: Built-in Functions
childNumber
elementType
The element type of the desired ancestor.
element
The element from which to search for ancestors.
ancestorChildNumber
element
The element for which the number is desired.
path
elementType
The element type of the desired ancestor.
element
The element from which to search for ancestors.
hierarchicalNumberRecursive
element
The element representing one end of the path, the other end of the path is the document root.
formatNumber
elementType
The element type of the ancestor elements to be considered by this function.
element
The element representing one end of the path; the other end of the path is the document root.
formatNumberList
n
The number to format.
format
A value specifying the desired format for the number:
list
The array of numbers to format. Usually generated by the path function or the hierarchicalNumberRecursive function.
format
Specifies the format to use for each number as described in formatNumber. It shall be either a single string specifying the format to use for all numbers or an array of strings with the same number of members as list each specifying the specific format to use for each number.
separator
A string to be inserted as the separator between each formatted number. The separator shall contain either a single string or an array of strings with one fewer members than list.
Lesson #24: XML Object Model
parent
getAttribute()
children
attributeName
The name of the attribute to retrieve.
text
length
item()
this.children.item(elementType)
this.children.item(elementType, index)
elementType
The name of the element(s) to retrieve.
index
The index of the element to retrieve.