The main difficulty in working with a new and evolving technology such as XML is keeping up with the many changes being made to the specifications. For example, XSL is now being split into three different specifications: XSLT, XPath, and XSL Formatting Objects (XSL FO). XPath originated from XSL; therefore, as you saw earlier in this chapter, XSL uses essentially the same syntax as XPath. Because we've discussed XPath in detail in Chapter 6, we won't repeat the discussion here. The formatting object specification (the fo namespace) defines a set of formatting semantics developed as an XML vocabulary for working with documents such as PDFs.
XSLT uses several of the elements that we used with XSL in the same manner. For example, the following elements have not changed: apply-templates, attribute, element, comment, copy, for-each, if, choose, when, and otherwise. The pi element used in XSL is called processing-instruction in XSLT.
The following elements that exist in XSL do not exist in XSLT: script, cdata, entity-ref, and eval. If you are converting an XSL document into an XSLT document and these elements are used in the XSL document, you will have to write script that will replace these elements. This is what the Microsoft XSL to XSLT Converter did for the eval element. We'll discuss this converter in the next section.
The stylesheet element still exists in XSLT, but the attributes have been changed. The attributes for the stylesheet element are now: extension-element-prefixes, xmlns:xsl, and version. The extension-element-prefixes attribute is used to designate an extended namespace. The xmlns:xsl namespace must be http://www.w3.org/1999/XSL/Transform. You can include other namespaces.
The following table lists XSLT elements that are not part of XSL:
XSLT Elements
Name and Syntax | Description |
---|---|
<xsl:include href = uri/> | The XSLT resource located by the href attribute value is parsed as an XML document, and the children of the xsl:stylesheet element in this document will replace the xsl:include element in the including document. This element is supported in the Internet Explorer 5 DOM. |
<xsl:import href = uri/> | Imports another XSLT style sheet. Importing a style sheet is the same as including it except that definitions and template rules in the importing style sheet take precedence over template rules and definitions in the imported style sheet. |
<xsl:call-template name = Name/> | A template element with a name attribute specifies a named template. An xsl:call-template element invokes a template by name; it has a required name attribute that identifies the template to be invoked. Unlike xsl:apply-templates, xsl:call-template does not change the current node or the current node list. |
<xsl:text disable-output-escaping = "yes" | "no" /> | Creates a text node with the string- value of the content of the text element in the result tree. Adjacent text nodes in the result tree are automatically merged. A template can also contain text nodes. Each text node in a template remains after white space has been stripped. The value of the disable-output-escaping attribute can be either yes or no. |
<xsl:number level = "single" | "multiple"|"any" count = pattern from = pattern value = number-expression format = { string } lang = { nmtoken } letter-value = { "alphabetic" | "traditional" } grouping-separator = { char } grouping-size = { number } /> | Insert a formatted number into the result tree. The number to be inserted may be specified by an expression. |
<xsl:sort select = "string" lang = "nmtoken" datatype = {"text"|"number"} order = {"ascending"|"descending"} case-order = {"upper-first"|"lower-first"} /> | The XPath expression in select indicates the node on which the sort should be based. The sort element is supported in Internet Explorer 5, but only with the select and order attributes. |
<xsl:variable name = qualified-name select = " XPath expression" /> | Sets a variable for use within an XSLT style sheet. The name attribute is the name of the variable to be used within variable references. To reference the value of the variable, use the $variable-name syntax. This element is supported in the Internet Explorer 5 DOM. |
<xsl:param name = qualified-name select = "XPath expression" /> | Declares a parameter for use within an XSLT style sheet. To reference the value of the parameter, use the $parameter-name syntax. This element is supported in Internet Explorer 5 DOM. |
<xsl:copy-of-select select = " XPath expression" /> | Inserts a result tree fragment or node-set into the result tree. This element is supported by the Internet Explorer 5 DOM. |
<xsl:with-param name = " qualified-name" select = " XPath expression" /> | Passes a parameter to a template. This element is supported by the Internet Explorer 5 DOM. |
<xsl:key name = qualified-name match = pattern use = node-set-expression /> | The key element is used to declare keys. This element provides information about the keys of the node that matches the pattern given in the match attribute. |
<xsl:decimal-format name = qualified-name decimal-separator = char grouping-separator = char infinity = string minus-sign = char NaN = string percent = char per-mille = char zero-digit = char digit = char pattern-separator = char /> | Declares a decimal-format, which controls the interpretation of a format pattern used by the format-number function. If there is a name attribute, the element declares a named decimal-format; otherwise, it declares the default decimal-format. |
<xsl:message terminate ="yes"|"no"/> | Sends a message in a way that is dependent on the XSLT processor. The content of the message instruction is a template. You can instantiate the message by instantiating the content to create an XML fragment. This XML fragment is the content of the message. An XSLT processor might implement the message element by popping up an alert box or by writing to a log file. If the terminate attribute has the value yes, then the XSLT processor should terminate processing after sending the message. |
<xsl:fallback /> | Normally, instantiating an xsl:fallback element does nothing. However, when an XSLT processor performs fallback for an instruction element, if the instruction element has one or more xsl:fallback children, then the content of each of the xsl:fallback children must be instantiated in sequence; otherwise, an error must be signaled. |
<xsl:output method = "xml"|"html"|"text" version = nmtoken encoding = string omit-xml-declaration = "yes"|"no" standalone = "yes"|"no" indent = "yes"|"no" media-type = string /> | Allows style sheet authors to specify how they want the result tree to be output. This element is allowed only as a top-level element, and it is supported by the Internet Explorer 5 DOM. |
As mentioned previously, we need to update the XSL style sheets to make them compliant to the W3C XSLT specification. Specifically, we'll need to change XSL and related namespaces. A new official XSLT namespace is available: http://www.wc.org/1999/XSL/Transform. The 2.6 and higher versions of the XML parser can recognize both the new namespace and the existing namespace http://www.w3.org/TR/WD-xsl. Since <xsl:eval>and <xsl:script> blocks are not supported in XSLT, they have to be converted to an XSLT-conformant mechanism. We'll also need to add JScript implementations of XTLRuntime functions where necessary, since the XTLRuntime object extends the W3C standard. What's more, we will also have to replace all the operators with their XML equivalents. For example, $lt$ will need to be replaced with <, $gt$ will have to be replaced with >, and so forth. The operators that have no XML equivalent, such as ieq, will require you to write special functions. Although this sounds like it can be a lot of work, Microsoft actually provides a converter called XSL to XSLT Converter. The converter is zipped into a file named Xsltconv.exe. The file can be downloaded at Microsoft's Web site. The zip file contains three files: Xsl-xslt-converter.xslt, Readme-xslt.txt, and Convert.js. You can run the Convert.js program from the DOS prompt. The format is as follows:
PathToConvert.js/convert.js PathToXSLFile/ XSLFileName [XSLTFileName] |
The parameter is optional. The program will perform the required conversion from an XSL file to an XSLT file. The version that was used at the time this book was being written had a few minor quirks, such as raising an error if there were any comments in the XSL document. If you convert the XSL document discussed in "The for-each and apply-templates elements" section of this chapter to an XSLT document, you will find some minor changes as described below. You can also find the XSLT document on the companion CD.
The stylesheet element has been changed to the following:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:local="#local-functions" xmlns:xql="#xql-functions" xmlns:auto-ns1="http://www.w3.org/TR/WD-xsl"> <!-- [XSL-XSLT] Updated namespace, added the required version attribute, and added namespaces necessary for script extensions. --> |
Since Internet Explorer 5 was released prior to the current standard, there was no way to know what the final namespace would be in the standard. Thus, the namespace we have been using with the Internet Explorer 5 XSL documents is different from the W3C namespace.
When working with Internet Explorer 5, you can use the Internet Explorer 5 namespace in your XSL document (<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> ); but when you use this namespace, your XSL documents will not work with other applications that recognize XSLT. On the other hand, if you use XSLT documents with the namespace from the W3C standard, these documents will not currently work in Internet Explorer 5.
You can also see the msxsl and local namespaces in the stylesheet element above. These namespaces will be used to define a set of default functions that will replace all the functions in the Microsoft XSL documents that are not part of the standard. In this case, we are not using any of these functions.
The next two additions from the converter are as follows:
<!-- [XSL-XSLT] Explicitly apply the default (and only) indent-result behavior --> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" /> <!-- [XSL-XSLT] Simulate lack of built-in templates --> <xsl:template match="@*|/|node()" /> |
The XSLT document has an output element that can be used to define how the information should be output. This element has been added to the document. Values for this element have also been added, as well as a default template that will select all nodes in the tree.
These are the only changes that were made to the original document. When we discussed XSL above, we used the XPath syntax. As mentioned previously, the XPath syntax was also the same as the XSL syntax. Therefore, nothing needed to be changed since XSLT uses XPath. Thus, for a simple XSL document you will only need to make minor changes. This means that you can currently write XSL documents that work with Internet Explorer 5, and they will only require minor changes when you convert them to XSLT documents.
If you are using more complex XSL documents, such as documents referencing the Internet Explorer 5 XTLRuntime extended methods, you will find that you have to make major modifications to your document. If you try to convert the XSL document we made to test the XTLRuntime object using the conversion program, you will find that there are major changes. This is because this entire XSL document uses the XTLRuntime object, which contains functions that are not part of the W3C standard. One of the conversions looks as follows:
nodeName: <!-- [XSL-XSLT] Converted xsl:node-name to xsl:value-of --><xsl:value-of select="name()" /> Absolute Child Number: <!-- [XSL-XSLT] Converted xsl:eval to xsl:value-of --> <xsl:value-of select="local:eval_1_2_2_2_2_2_4(.)" /> |
In XSLT, the nodeName function is no longer used; instead, we use the name function as the criteria for the select attribute of the value element. The second change looks very weird, but it's actually very simple. The value for the select attribute of the value-of element is local:eval_1_2_2_2_2_2_4(.). The local prefix defines the namespace, which points to a location at the bottom of the generated XSLT document. The base eval_1_2_2_2_2_2_4 is a Java function that is defined in the local namespace. The parameter that is being passed into the function is the dot (.), or the current element. The eval_1_2_2_2_2_2_4 function looks as follows:
function eval_1_2_2_2_2_2_4(_contextNodeList) { var __this = _contextNodeList.item(0); return absoluteChildNumber(__this); } |
The function takes the first element from the node and returns the absoluteChildNumber using another Java function, as shown below:
function absoluteChildNumber(pNode) { var n = 1; while (pNode == pNode.nextSibling) n++; return n; } |
Notice that the eval_1_2_2_2_2_2_4 function takes a NodeList object, while the absoluteChildNumber takes a node object. The absoluteChildNumber function uses the DOM object to get the correct number. Any application that uses a DOM object as specified in the W3C DOM standard, and also is capable of reading XSLT documents, will be able to use these Java script functions. Thus, these are generic XSLT documents.
You can use XSLT with Internet Explorer 5 today, but you will have to do a little work either on the server or on the client. You can use Microsoft's implementation of DOM to transform an XML document using an XSLT document. We will do that in the section "Using the XML DOM to Work with XSLT and XSL" later in this chapter. First we'll take a look at the XPath and XSLT Functions.
The XPath functions can be used in XSLT documents. We have already seen the name function being used as a parameter for the select attribute of the value-of element. The XPath functions can be divided into four groups: Boolean, string, node-set, and number functions.
The Boolean functions can be used with comparison operators in filter patterns and return strings or numbers. They are as follows:
Boolean Functions
Name | Description |
---|---|
boolean (XPathObject) | Converts the argument to a Boolean. A number is true if it's not positive, negative zero, or NaN. A node-set is true if it's non-empty. A string is true if its length is non-zero. |
false () | Returns false. |
true () | Returns true. |
lang (string) | Used to determine what language should be used for characters; not currently implemented in the Internet Explorer 5 DOM. |
The string functions are used to convert XPath objects to strings and to manipulate strings. They are shown in the following table:
String Functions
Name | Description |
---|---|
concat (string, string, [string]) | Concatenates strings. Can be passed to any number of string parameters. |
contains (string1, string2) | Returns true if the first argument contains the second argument. Returns false otherwise. |
normalize-space (string) | Returns the argument with all the white space normalized. |
starts-with (string1, string2) | Returns true if the first argument starts with the second. Returns false otherwise. |
substring (string1, number1, number2) | Returns the substring of the first argument starting at the second argument with length number2. If number2 is omitted, the function will continue to the end of the string. |
substring-after (string1, string2) | Returns the substring of the first argument that follows the first occurrence of the second argument in the first argument. |
substring-before (string1, string2) | Returns the substring of the first argument that precedes the first occurrence of the second argument in the first argument. |
string (object) | Converts an object to a string. |
string-length (string) | Returns the number of characters in a string. |
translate (string1, string2, string3) | Returns the first argument with occurrences of characters the second argument replaced by the character at the corresponding position in the third argument. |
The XPath node-set functions are used for filtering and selecting node-sets. The following functions are node-set functions:
Node-set Functions
Name | Description |
---|---|
count (node-set) | Returns the number of nodes in the node-set. |
id (object) | Selects an item by its unique ID. The object is an XPath object. Returns a node-set consisting of node/nodes with ID/IDs corresponding to the parameter passed after it is converted to a string. |
last () | Returns the number of nodes in the node-set. |
local-name (node-set) | Returns the local part of the expanded name. |
name (node-set) | Returns the expanded name as a string. |
namespace-uri (node-set) | Returns the namespace URI of the expanded-name of the node-set. |
postion () | Returns the index number of the node. The first node returns a position of 1. |
The number functions can be used with comparison operators and can return strings or numbers. They are shown in the following table:
Number Functions
Name | Description |
---|---|
number (object) | Converts its argument to a number. This function is not supported in the Internet Explorer 5 DOM. |
ceiling (number) | Returns the smallest (closest to negative infinity) number that is not less than the argument and that is an integer. This function is not supported in the Internet Explorer 5 DOM. |
floor (number) | Returns the largest (closest to positive infinity) number that is not greater than the argument and that is an integer. This function is not supported in the Internet Explorer 5 DOM. |
round (number) | Returns the number that is closest to the argument and that is an integer. If there are two such numbers, the one that is closest to positive infinity is returned. This function is not supported in the Internet Explorer 5 DOM. |
sum (node-set) | Returns the sum for each node in the argument node-set. The nodes are first converted to number values before summing. This function is not supported in the Internet Explorer 5 DOM. |
There are numerous XSLT functions that give information about nodes in a collection. The Microsoft XML parser 2.0 only supports the node-set function.
XSLT Functions
Name | Description |
---|---|
current () | Returns the current context node. |
document (object, node-set) | Allows access to XML documents other than the main source document. This function is not supported in the Internet Explorer 5 DOM. |
element-available (string) | Returns true if the expanded-name is the name of an instruction. If the expanded-name has a namespace URI equal to the XSLT namespace URI, then it refers to an element defined by XSLT. Otherwise, it refers to an extension element. If the expanded-name has a null namespace URI, the element-available function will return false. It can be used with the choose and if elements. This function is not supported in the Internet Explorer 5 DOM. |
format-number (number, string, string) | Converts its first argument to a string using the format pattern string specified by the second argument and the decimal-format named by the third argument, or the default decimal-format, if there is no third argument. The format pattern string is in the syntax specified by the JDK 1.1 DecimalFormat class.* This function is not supported in the Internet Explorer 5 DOM. |
generate-id (node-set) | Returns a string that uniquely identifies the node in the argument node-set that is first in document order. This function is not supported in the Internet Explorer 5 DOM. |
key (string, object) | Selects items by a key and returns all the nodes with the specified key. |
system-property (string) | Returns an object representing the value of the system property identified by the name. If there is no such system property, the empty string should be returned. |
unparsed-entity-uri (string) | Returns the URI of the unparsed entity with the specified name in the same document as the context node. This function is not supported in the Internet Explorer 5 DOM. |
function-available (string) | Returns true if and only if the expanded-name is the name of a function in the function library. It can be used with the choose and if elements. This function is not supported in the Internet Explorer 5 DOM. |
* See http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html for information on the class DecimalFormat.