Changes with XSLT 2.0


XSLT 2.0 is still a candidate recommendation as I write this, but it should remain constant as it moves to a proposed recommendation and finally to a recommendation. XSLT 2.0 is an evolutionary step from XSLT 1.0. There are no major syntax breaking changes. Instead, it refines the existing model, and improves its clarity and flexibility. The major visible changes within XSLT 2.0 include:

  • q Support for XPath 2.0 functions

  • q Addition of XHTML as an output format

  • q Easier methods for grouping data

  • q Capability to create multiple output documents

  • q Capability to create user-defined functions

XSLT 2.0 and XPath 2.0 have been progressing simultaneously through the W3C. The benefit of this is that the functionality of XPath 2.0 is available for use by XSLT 2.0, and the two groups aren't creating similar but incompatible functionality. The greatest benefit is the availability of the XPath functions.

These add a number of necessary capabilities including string, date, and numeric processing. Some of the more useful functions include:

  • q round, round-half-to-even-Round rounds the number argument to the nearest number; round-half-to-even performs the banker's round that rounds 1.5 and 2.5 to 2.

  • q concat, string-join-Concat combines multiple strings to create a new string; String-join takes an additional parameter for the separator to use between each.

  • q lower-case, upper-case-Changes the case of the supplied string.

  • q substring, replace-Substring finds one string within another; replace changes one string based on a supplied pattern.

  • q year-from-date, month-from-date, day-from-date-Extracts the component from the supplied date.

One output format that was missing from XSLT 1.0 was XHTML. Although you could generate XHTML by setting the output format to HTML and ensuring the generated output was XHTML, it was not the same. XSLT 2.0 adds direct support for output=“XHTML”. You can also use the doctype-public and doctype-system to add the appropriate declaration in your XHTML. For example, to declare your document as XHTML 1.0 Transitional, you use the following output statement:

      <xsl:output method="xhtml"        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"        doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" version="1.0"        indent="yes" encoding="UTF-16"/> 

One common form of report involves data grouped based on some categorization (see Figure 8-4). With XSLT 1.0, creating this type of structure was difficult. XSLT 2.0 adds the for-each-group element (see Listing 8-16).

image from book
Figure 8-4

Listing 8-16: Using the for-each-group element

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="2.0"        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"        xmlns:xs="http://www.w3.org/2001/XMLSchema"        xmlns:fn="http://www.w3.org/2005/xpath-functions"        xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"        exclude-result-prefixes="xs fn xdt">        <xsl:output method="xhtml"          doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"          doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" version="1.0"          indent="yes" encoding="UTF-8"/>        <xsl:template match="/">          <html>            <body>              <table>                <tbody>                  <tr>                   <th>Country</th>                   <th>Company</th>                  </tr>                   <xsl:for-each-group select="customers/customer"                    group-by="address/country">                    <xsl:sort select="address/country" data-type="text"/>                    <tr>                      <td colspan="2" bgcolor="#E0E0E0">                        <xsl:value-of select="address/country"/>                      </td>                    </tr>                    <xsl:for-each select="current-group()">                      <xsl:sort select="company" data-type="text" />                      <tr>                        <td> </td>                        <td>                          <xsl:value-of select="company"/>                        </td>                      </tr>                    </xsl:for-each>                  </xsl:for-each-group>                </tbody>              </table>            </body>          </html>        </xsl:template>       </xsl:stylesheet> 
image from book

The for-each-group element takes a select attribute, as did the for-each element. In addition, it has a group-by attribute. This identifies the expression based on the select attribute that is used to group the output. Within the for-each-group element, the current-group() function returns the items in the current group.

XSLT 1.0 was limited to a single output document for each stylesheet. XSLT 2.0 adds the capability to export multiple documents using the result-document element. It requires you identify the URI for the new document and a format. In essence, it duplicates the output node, but for each output document. Listing 8-17 shows how to use the result-document element.

Listing 8-17: Outputting multiple documents

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="2.0"        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"          xmlns:xs="http://www.w3.org/2001/XMLSchema"          xmlns:fn="http://www.w3.org/2005/xpath-functions"          xmlns:xdt="http://www.w3.org/2005/xpath-datatypes">          <xsl:output method="text"/>          <xsl:output method="text" encoding="UTF-16" name="textFormat"/>          <xsl:template match="/">          <xsl:for-each-group select="//customer" group-by="address/country">            <xsl:sort select="address/country" data-type="text"/>            <xsl:variable name="uri" select="concat(address/country, '.txt')"/>            <xsl:result-document href="{$uri}" format="textFormat">              <xsl:for-each select="current-group()">                <xsl:value-of select="company"/>                <xsl:text>&#x0D;</xsl:text>              </xsl:for-each>            </xsl:result-document>          </xsl:for-each-group>          </xsl:template>      </xsl:stylesheet> 
image from book

This stylesheet uses the customers.xml file to generate one text file per country, listing the companies in each country. The primary document is actually empty, although you could also create it as part of the processing. The result-document element takes-at a minimum-the href of the file to create and a named output format. In the preceding example, the href is of the form country.txt. The format attribute points at the named output to create a UTF-16 encoded text file. Within each result-document element, the elements in the current group are written to the file.

Finally, the addition of custom functions takes over many of the abuses of call-template. User-defined functions in XSLT enable encapsulation, just as they do in other programming languages. Each function can have multiple parameters and a return value. Listing 8-18 shows a sample user-defined function.

Listing 8-18: User-defined functions in XSLT 2.0

image from book
            <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="2.0"          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"          xmlns:xs="http://www.w3.org/2001/XMLSchema"          xmlns:fn="http://www.w3.org/2005/xpath-functions"          xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"          xmlns:ex="some-URI">          <xsl:output method="xml" version="1.0"          encoding="UTF-8" indent="yes"          exclude-result-prefixes="fn xs xdt ex"/>          <xsl:template match="/">          <contacts>            <xsl:apply-templates select="customers/customer/contact"/>          </contacts>          </xsl:template>          <xsl:template match="contact">          <contact>            <xsl:value-of select="ex:name-case(name)"/>          </contact>          </xsl:template>          <xsl:function name="ex:name-case" as="xs:string">          <xsl:param name="value" as="xs:string"/>          <xsl:sequence select="if(contains($value, ' '))                              then concat(substring-before($value, ' '),                                          ' ',                                          upper-case(substring-after($value, ' ')))                              else $value"/>          </xsl:function>      </xsl:stylesheet> 
image from book

To avoid any possible collision with existing functions, you define a new namespace for the user-defined function. This namespace is used in both the call to the function and in the definition. The function element requires a name and, optionally, the data type of the return value. Within the definition of the function, you can include as many parameters as necessary. They must be the first child elements within the function. As with the function, you can also include the type of the parameters. The sequence element generates the return value. The resulting XML displays the last name of each contact in uppercase.

      <?xml version="1.0" encoding="UTF-8"?>      <contacts>        <contact>Maria ANDERS</contact>        <contact>Ana TRUJILLO</contact>        <contact>Antonio MORENO</contact>        <contact>Thomas HARDY</contact>        <contact>Christina BERGLUND</contact>        <contact>Hanna MOOS</contact>        <contact>Frédérique CITEAUX</contact>      ...      </contacts> 

Although XSLT 2.0 is not yet a W3C standard, it soon will be. If your XSLT processor supports XSLT 2.0, there really is no excuse not to take advantage of all the new functionality for your stylesheets.




Professional XML
Professional XML (Programmer to Programmer)
ISBN: 0471777773
EAN: 2147483647
Year: 2004
Pages: 215

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net