4.2 A gentle introduction to 2.0
Many of the XSLT examples in this book use the latest XSLT 2.0 features. Some (but not all) of the examples can be rewritten in 1.0 without too much trouble. Otherwise , if your XSLT processor does not yet support 2.0, check if it can use an EXSLT element ( 4.4.1 ) or a proprietary extension with the same or similar semantics.
Compared to the canceled XSLT 1.1, the list of new features and incompatible changes is much longer in 2.0. Below are some highlights.
The concept of nodesets is replaced by a more general concept of sequences . A nodeset, as the name implies, is a set of nodes, and each node must belong to one of the few types that directly follow from the structure of XML (element node, attribute node, etc.). Contrastingly, a sequence may combine arbitrary values and allows for automatic control over their types; for example, you can create a sequence of integer numbers and let the processor ensure type conformance for you.
This change has had a profound impact on the entire language; all instructions that previously operated on nodesets now are generalized to sequences. Moreover, new attributes have been added to many instructions that make working with sequences (including nodesets) more convenient . For instance, to list the values of all child elements, separated by commas, in 1.0 you had to write
<xsl:for-each select= "*"> <xsl:value-of select= "."/> <xsl:if test= "position() != last()"> <xsl:text>, </xsl:text> </xsl:if> </xsl:for-each>
In 2.0, you can simply write
<xsl:value-of select= "*" separator= "," />
XSLT 2.0 makes it possible to specify and check data types of variables , parameters, functions, and templates. To this end, it borrows a library of data types from XSDL (XML Schema). For example, here's how you declare an integer variable in 2.0:
<xsl:variable name= "i" as= "xs:integer" select= "42"/>
And here is a variable that may contain a sequence of attribute nodes:
<xsl:variable name= "a" as= "attribute()*"/>
Note that the integer variable declaration above refers to an XSDL data type and therefore uses the xs : namespace prefix that must resolve to the namespace URI of http://www.w3.org/2001/XMLSchema . In the second example, attribute() is a node type native to XSLT, so no namespace prefix is necessary; the * at the end of the type specification makes this a sequence rather than a single attribute value.
Another powerful concept is grouping . Although there's nothing really new here, as you could emulate this feature with the 1.0 facilities, the new syntax allows for very elegant constructs. You can group nodes (or other members of a sequenceremember, it is generalized!) by
the common value of an arbitrary XPath expression (e.g., group all nodes with the same child or attribute, or group sequence members that return equal values as arguments to some function); or
arbitrary properties of neighbors in the sequence (e.g., group all adjacent nodes sharing some property, or group all nodes starting from a heading node until the next heading ).
This feature makes it possible to "deepen" an XML tree, adding hierarchy to a flat structure (see also 2.3.2 ). The powerful new xsl:for-each-group instruction can be used, for example, to enclose into section s groups of elements that start with a heading :
<xsl:for-each-group select= "*" group-starting-with= "heading"> <section> <xsl:copy-of select= "." /> </section> </xsl:for-each-group>
The new XPath 2.0 is chock full of goodies , especially in comparison to 1.0. Like XSLT 2.0, the new XPath supports schema-derived types and sequences. It also provides a lot of newand sorely missing in 1.0functions that work with strings, numbers, dates, URIs, qualified names , nodes, and nodesets. Lowercasing a string, matching a regexp, resolving a relative URI, converting a date, finding the node with the highest numeric value in a nodesetall of this is now possible without clumsy workarounds or nonportable extension functions.
Moreover, XPath even encroaches on the domain of XSLT proper, offering its own variants of some XSLT constructs. These variants are not only less verbose but often look more natural from the "traditional programming languages" viewpoint. For example, instead of the old
<xsl:attribute name= "valign" > <xsl:choose> <xsl:when test= "$level > 2">top </xsl:when> <xsl:otherwise> bottom </xsl:otherwise> </xsl:choose> </xsl:attribute>
you can now write simply
<xsl:attribute name= "valign" > <xsl:value-of select= " if $level > 2 then 'top' else 'bottom'" /> </xsl:attribute>
Also, in XPath 2.0 you can explicitly check if some or every member of a sequence satisfies a condition (in 1.0 the some quantifier was always assumed).
Despite the 1.1 setback, extensibility is in 2.0 too. There's no xsl:script anymore, but you can link up extension functions if your processor supports this (we'll use this feature a lot in Chapter 5). Perhaps more importantly, you can now define new functions written in XSLT  and use them in your XPath expressions (this feature will be used even more; Example 4.1 on page 167 is a simple illustration).
 Strange but true: A language intended to be functional did not support user -defined functions until version 2.0.
The ability to create multiple output documents is also present, as it was in 1.1. The instruction that creates a new output document is called xsl:result-document . You can provide several xsl:output instructions, each storing a named collection of output parameters; different xsl:result-document instructions may refer to different xsl:output specifications, thus implementing a content/presentation separation of sorts: Now "presentation" (governed by xsl:output parameters) is removed from "content" (created by an xsl:result-document ). This feature is used in 5.5.2 (page 238).
There is much more that is new in XSLT and XPath 2.0;  this section covers only what I think are the most important new features for a practical XSLT programmer. Minor nifty things include the xsl:next-match instruction, which allows firing more than one template rule for the same context in the same mode; the function-available() function to check whether your processor supports a particular function; the unparsed-text () function that reads an arbitrary text resource (file or URL) and returns it as a string without parsing (see 126.96.36.199 for a use case); and more.
 For a complete list of changes, see www.w3.org/TR/xslt20/#changes.
Fortunately, you don't have to learn all this at once. Most of your 1.0 stylesheets will work with a 2.0 processor without problems, and those that use 1.1 features or custom extensions ( 4.4.3 ) will likely require only minimal changes.