XSLT Syntax


Because XSLT is itself an XML syntax, it defines a number of elements that provide the processing. In addition to these elements, a number of functions are defined for working with the source and result trees. Finally, XSLT makes use of XPath functions (XPath 2.0 in XSLT 2.0) for computation, context, and other work. Therefore, knowledge of XPath (see Chapter 10) helps with XSLT.

Required Items

The root node for an XSLT stylesheet is, appropriately enough, stylesheet. It uses the http://www.w3.org/1999/XSL/Transform namespace. Alternatively, the specification defines transform as a valid synonym for stylesheet. Therefore, you may see either term as the root node in an XSLT stylesheet. Either stylesheet or transform has a single required attribute, version. Currently, 1.0 and 2.0 (for XSLT 2.0, obviously) are the only valid values for this attribute. In addition to this attribute, the stylesheet element may also contain references to other namespaces.

Top-level Elements

Typically, after the root node, a number of optional top-level elements provide additional information, either about the document(s) to be processed, or for the output. The valid top-level elements include:

  • q import, include

  • q strip-space, preserve-space

  • q decimal-format

  • q output

  • q key

  • q variable

  • q param

  • q template

Including Additional Stylesheets with include and import

The import node imports one stylesheet into another. If this node exists, it must be the first element after the root node. The import element enables the modularization of your stylesheets. For example, you could have a stylesheet specific for processing address elements or other common elements. Rather than duplicate this functionality throughout multiple XSLT stylesheets, you could import it when needed. If an element exists in both the parent and the imported stylesheets, the element in the parent stylesheet takes precedence. During processing, lower precedent templates are ignored in favor of higher ones.

The include node is similar in functionality to the import node, with one exception. The included stylesheet has the same precedence as the parent. This can lead to errors if both stylesheets include the same definition. Therefore, you should be careful when including other stylesheets to ensure that there are no duplicate templates, parameters, variables, and so on.

The import and include elements take a single attribute-href-that points at the imported or included stylesheet URL.

Controlling Whitespace and Formatting with strip-space, preserve-space, and decimal-format

The strip-space element lists a number of elements that have whitespace removed during processing. Alternatively, the preserve-space element defines child elements that maintain their whitespace when processed. Note: This does not affect all nodes, only those text nodes that only contain whitespace. For example, look at the following source fragment and stylesheet:

      <?xml version="1.0" encoding="UTF-8"?>      <customers>        <customer >          <company>   </company>          <address>            <street>Obere Str. 57</street>            <city>Berlin</city>            <zip>12209</zip>            <country>    </country>          </address>          <contact>            <name>Maria Anders</name>            <title>Sales Representative</title>            <phone>030-0074321</phone>            <fax>030-0076545</fax>          </contact>          </customer>       </customers>      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">         <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>         <xsl:strip-space elements="country"/>         <xsl:preserve-space elements="company"/>         <xsl:template match="/">         <xsl:apply-templates select="customers/customer[@id='ALFKI']"/>          </xsl:template>         <xsl:template match="customer">          <cust>            <ctry>              <xsl:attribute name="length">                <xsl:value-of select="string-length(address/country)"/>               </xsl:attribute>              <xsl:value-of select="address/country"/>           </ctry>           <name>             <xsl:attribute name="length">               <xsl:value-of select="string-length(company)"/>              </xsl:attribute>              <xsl:value-of select="company"/>            </name>            <contact>              <xsl:value-of select="contact/name"/>            </contact>          </cust>          </xsl:template>      </xsl:stylesheet> 

The resulting output is:

      <cust>         <ctry length="0"></ctry>         <name length="3">   </name>         <contact>Maria Anders</contact>      </cust> 

Both the strip-space and preserve-space elements take a single attribute called elements. This attribute is either asterisk (*) for all elements or a space-delimited list of the elements to which the rule applies. In the above sample, the whitespace of the country name was stripped, leaving the new element 0 characters long. The preserve-space on the company, on the other hand, left the spaces in, and the size was still three.

The decimal-format element defines the symbols to be used when formatting numbers in the stylesheet. These rules are then applied using the format-number function (covered later in the chapter). A typical use for this element is to create a number of named formats. For example, for US currency you use a comma (,) for grouping thousands and a period (.) as a decimal separator. Meanwhile, European currency would use a period (.) for grouping thousands, and a comma (,) for decimal separator. In addition, you use the decimal-format element to change the value displayed when the input value is not a number, infinity, or a negative.

Controlling Output with output and key

The output element defines the format of the result document. This includes defining the output format and any parameters that describe that format.

Open table as spreadsheet

Attribute

Value

Description

cdata-section-elements

string

This attribute lists the elements that are CDATA wrapped in the output document. Use spaces to delimit multiple elements. This is useful if you are producing HTML output that may include XML content.

doctype-public

string

This attribute defines the public identifier to be used in the document type declaration.

doctype-system

string

This attribute defines the system identifier to be used in the document type declaration.

encoding

string

This attribute is needed only if the output format has an encoding attribute, such as for XML. This inserts the encoding attribute into the output document.

indent

yes/no

If this value is yes, the output document is indented to match the hierarchy. This is useful if the XML is intended for human access, although it does increase the size of the document slightly.

media-type

string

This attribute defines the MIME type of the resulting output. For example, if you are outputting Atom: and this is XML, the correct MIME type is application/atom+xml.

method

One of: xml, html, text or named type. XSLT 2.0 adds XHTML as a valid value.

Defines the output format, defaults to XML, with one exception. If the root node is <html>, the output format is HTML.

To create XHTML output with XSLT 1.0, you can use either the XML output format and include the XHTML namespace and elements, or use the HTML output format and ensure you follow the XHTML rules (always close elements, and so on). This is rarely used, but you can also target any output format by using a qualified name for the method.

omit-xml-declaration

yes/no

If this value is yes, the XML declaration is not included in the target document. Typically, you set this to no for text or HTML output.

standalone

yes/no

If this value is yes, the standalone attribute is added to the XML declaration.

version

string

This character is needed only if the output format has a version, such as for XML. This inserts the version attribute into the output document.

The key element creates a named key that is used when searching the source document. Just as each element in an XML document can be identified by a unique identifier, often id, the key element identifies the attribute or child element that provides the unique identifier for each element. This key pattern can then be used later in the XSLT to retrieve individual items.

For example, look at the following XML source document:

      <customers>        <customer >         <company>Alfreds Futterkiste</company>          <address>            <street>Obere Str. 57</street>            <city>Berlin</city>            <zip>12209</zip>            <country>Germany</country>          </address>          <contact>            <name>Maria Anders</name>            <title>Sales Representative</title>            <phone>030-0074321</phone>            <fax>030-0076545</fax>          </contact>          </customer>          <customer >          <company>Ana Trujillo Emparedados y helados</company>          <address>            <street>Avda. de la Constitución 2222</street>            <city>México D.F.</city>            <zip>05021</zip>            <country>Mexico</country>          </address>          <contact>            <name>Ana Trujillo</name>            <title>Owner</title>            <phone>(5) 555-4729</phone>            <fax>(5) 555-3745</fax>          </contact>          </customer>      </customers> 

You define a key pattern for the customer node using the XSLT in Listing 8-2:

Listing 8-2: Using the Key element and function

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>          <xsl:key name="cust" match="customer" use="@id"/>          <xsl:template match="/">          <result>            <xsl:for-each select="key('cust','ANATR')">              <company>                 <xsl:value-of select="company"/>              </company>            </xsl:for-each>          </result>        </xsl:template>       </xsl:stylesheet> 
image from book

The created key, named cust searches the id attribute of customer nodes to locate the desired elements. This key element is different from the key function used later in the stylesheet. In the for-each element, the key function uses the named key to search for a customer with the id ANATR. Alternatively, because only a single item can match each key, you use the select attribute of apply-templates to retrieve the selected company as shown in the following code.

      <xsl:template match="/">        <result>          <xsl:apply-templates select="key('cust', 'TORTU')" />          </result>      </xsl:template>      <xsl:template match="customer">          <company><xsl:value-of select="company" /></company>      </xsl:template> 

Templates

The core of XSLT is in the templates. These provide examples of how the different source elements should be processed when creating the result document. Listing 8-3 shows an XSLT template.

Listing 8-3: XSLT template

image from book
      <xsl:template match="customer">        <cust>          <xsl:attribute name="id">            <xsl:value-of select="generate-id(contact/name)" />          </xsl:attribute>          <xsl:attribute name="company">            <xsl:value-of select="company" />          </xsl:attribute>          <xsl:apply-templates select="contact" />          </cust>      </xsl:template> 
image from book

Each template is composed of the template element and either a match and/or name attribute. The match attribute is more common and identifies an XPath pattern in the source document to which the template will apply. The name attribute is used only in cases where the call-template (covered later in the chapter) is used. In the preceding sample, the template applies to customer elements in the source document. This doesn't mean that it affects all customer elements, however. The caller can select the customer nodes to which the template applies.

The content of the template defines the output of the template. In the preceding template, whenever a customer node is processed, the result document has a <cust> node with a number of attributes.

Retrieving Values

The template element does not work alone in producing the result nodes. A number of additional XSLT elements work inside the template to extract values from the source document and produce the result. These include the following:

  • q value-of-Used to extract a single value based on an XPath statement. This is one of the "work horse" XSLT elements.

  • q element-Used to create a new element in the result document. Although you can create new elements in the result document simply by including them in the XSLT, element is useful to create a result element based on a value in the source document or a calculation.

  • q attribute-Used to create a new attribute in the result document. Just like element, this is most useful to create an attribute dynamically.

  • q text-Used to add text to the result document. Again, this is most useful when creating new text based on the source document, probably with some intermediate processing.

  • q copy-Used to copy an element from the source document into the result document. This element does not copy any child elements or attributes. This element is commonly used when the result document is similar in structure or naming to the source document.

  • q copy-of-Used to copy an element and its child elements and attributes from the source document into the result document.

The value-of element extracts a value from the source document, based on an XPath expression and the current context. This element is possibly the most frequently used XSLT element. It has a single required attribute, select, that is the XPath expression, and one optional attribute, disable-output-escaping. The disable-output-escaping attribute is set to either yes or no. If yes, characters that are significant in XML (such as < or >) will be included in the output. If no, these characters are escaped to &lt; and &gt;. If excluded, the default is no. The following element extracts the value of any child element named company, escaping characters as needed.

      <xsl:value-of select="company" disable-output-escaping="no" /> 

The element and attribute elements create the appropriate nodes in the result tree. Although you can create elements in the result document by including them in the XSLT, these elements make it easier to create these nodes, especially if the desired node is based on the source document. Both of these elements take a single required attribute, name, and an optional namespace attribute. The name is the newly created element or attribute, and namespace defines the namespace URI for the element or attribute.

The following XSLT fragment creates a new element based on the value of the category element in the source document. As the name attribute is generated dynamically, the attribute element is also used to create the name.

      <xsl:template match="category">        <xsl:element name="department" >          <xsl:attribute name="id">            <xsl:value-of select="text()" />          </xsl:attribute>                </xsl:element>      </xsl:template>      <!-- This would generate: (assuming the current node has           a child element called category.          <department />      --> 

The text element is used to add text nodes to the result document. Although you can add text by including the new text in the XSLT, the text element enables the creation of dynamic content based either on XPath functions or the source document. For example, the following line adds the Unicode character for carriage return (character 13 or hexadecimal 0D) to the result document.

      <xsl:text>&#x0D;</xsl:text> 

The copy and copy-of elements work to copy the current node to the result document. The difference between the two is that copy-of includes child elements and attributes, whereas copy only reproduces the current node. These two elements are useful when parts of the source and result documents match.

Calling templates

When you have created the templates for your stylesheet, the next step is to call them. With XSLT, two elements are used to call templates: apply-templates and call-template.

The apply-templates element executes templates based on the current context and passes control over to the other template. This is the common method of using templates in your stylesheets. The code that follows shows a parent template using apply-templates to execute another template. The line <xsl:apply-templates select= “contact”/> performs an XPath selection based on the current context. The parent template calls the contact template for each instance of a child contact node. That is, the contact template is executed for each node in the node-set defined by customer[current]/contact.

      <xsl:template match="customer">        <cust>         <xsl:apply-templates select="contact" />          <xsl:value-of select="company" />          </cust>      </xsl:template>      <xsl:template match="contact" name="contact">          <xsl:attribute name="name"><xsl:value-of select="name" /></xsl:attribute>      </xsl:template> 

If you exclude the select attribute for the apply-templates, all child templates are called in the order that they appear in the source document. This is a useful shorthand method when transforming a large block of a source document. The apply-templates element also supports sorting the data before the new template is executed (see the following sections).

Call-template, on the other hand, executes a single named template based on the current context. It is equivalent to calling a function and passing the current node. After the template completes, "flow" is passed back to the calling template. The parent template in Listing 8-4 uses call-template to format the price.

Listing 8-4: Using call-template

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">        <xsl:output method="text" encoding="UTF-16"/>        <xsl:template match="/">        <xsl:apply-templates select="//product" />          </xsl:template>          <xsl:template match="product">          <xsl:value-of select="name" />: <xsl:call-template name="price" />          <xsl:text>&#x0D;</xsl:text>          </xsl:template>          <xsl:template name="price">          <xsl:value-of select="format-number(price, '#.00')" />          </xsl:template>      </xsl:stylesheet> 
image from book

The call-template element is frequently used with conditional logic and/or parameters (see the following sections). For example, you could use it to provide a localized version of a value from the source document.

Multiple Templates for a Single Element

In addition to the match and name attributes, a template can also include mode and priority attributes. The priority attribute is used in cases where multiple templates apply to a single source element. Templates with a higher priority have precedence and are used; at no time should multiple templates act on the same node-set. The priority value must be a number. By default, most templates have a priority of 0.5.

The mode attribute is used to override the limitation on a single template acting on an element from the source document. The mode defines a particular action for a template. Other modes may also apply to the same element, but act in a slightly different way. The code in Listing 8-5 shows two templates acting on the same element using the mode attribute to identify both the template and the template call.

Listing 8-5: Use of the mode attribute

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>        <xsl:template match="/">          <modes>            <xsl:apply-templates select="//customer[@id='ANATR']" mode="block" />            <xsl:apply-templates select="//customer[@id='ANATR']" mode="attributes" />          </modes>          </xsl:template>          <xsl:template match="customer" mode="attributes">          <attributesMode>            <xsl:attribute name="company">              <xsl:value-of select="company" /></xsl:attribute>            <xsl:attribute name="contact">              <xsl:value-of select="contact/name" /></xsl:attribute>            <xsl:attribute name="phone">              <xsl:value-of select="contact/phone" /></xsl:attribute>          </attributesMode>           </xsl:template>          <xsl:template match="customer" mode="block">          <blockMode>            <xsl:value-of select="company"/>:            <xsl:value-of select="contact/name" />            (<xsl:value-of select="contact/phone" />)</blockMode>          </xsl:template>      </xsl:stylesheet> 
image from book

Two templates apply to the customer node in the source document. To identify the two, each is given a mode attribute. When the template is called using the apply-templates element, the desired mode is identified. Therefore, despite the attribute's mode element being first in the stylesheet, the block mode is executed first. The resulting document appears as follows:

      <?xml version="1.0" encoding="UTF-8"?>      <modes>        <blockMode>Ana Trujillo Emparedados y helados: Ana Trujillo ((5)      555-4729)</blockMode>        <attributesMode company="Ana Trujillo Emparedados y helados"          contact="Ana Trujillo" phone="(5) 555-4729"/>      </modes> 

Modes provide a handle that can be used by conditional logic to process a given element in different ways. For example, one mode might format dates, currency, and phone numbers for European customers, and another one might do so for U.S. customers.

Conditional Processing

Most programming languages provide some means of conditional logic in the form of if…else, switch or similar statements. XSLT is no exception: it provides both simple and complex branching using the if and choose/when/otherwise blocks.

The if element is used to provide a single simple test in processing. It takes a single attribute, test, that is an expression. If the expression evaluates to true, the content of the if element is processed. Listing 8-6 shows the use of the if element.

Listing 8-6: Using the if element

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">         <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>         <xsl:template match="/">         <xsl:apply-templates select="customers/customer"/>          </xsl:template>          <xsl:template match="customer">          <company>            <name><xsl:value-of select="company" /></name>            <xsl:if test="address/country='USA'">              <contact><xsl:value-of select="contact/phone" /></contact>            </xsl:if>          </company>          </xsl:template>      </xsl:stylesheet> 
image from book

The test of the if element tests whether the country of the current customer is USA and if so, outputs the phone number. The test attribute can use XPath functions as well as node expressions. If the test requires the use of lesser-than (<) or greater-than (>), you should encode the characters. Therefore, a test to determine if the price of a product is less than $20.00 in the products.xml file looks like this:

      <xsl:if test="price <= 20">        <xsl:attribute name="bgcolor">#E0E0E0</xsl:attribute>      </xsl:if> 

The attribute is created if the price is less-than or equal to 20.

You cannot add an else clause. If you need multiple tests, use the choose element. The choose element is similar to switch statements used by many other languages (or select case in Visual Basic). You define a number of tests, and the first one that evaluates to true is executed. If none of the tests are true, the otherwise element, if present, is used. (See Listing 8-7.)

Listing 8-7: Using the choose, when, and otherwise elements

image from book
      <xsl:choose>        <xsl:when test="price <= 20">          <xsl:attribute name="bgcolor">#e0e0e0</xsl:attribute>        </xsl:when>        <xsl:when test="price <= 100">          <xsl:attribute name="bgcolor">#00ff00</xsl:attribute>        </xsl:when>        <xsl:otherwise>          <xsl:attribute name="bgcolor">#FF0000</xsl:attribute>        </xsl:otherwise>      </xsl:choose> 
image from book

The choose element is a container for when and otherwise elements. Each when element has a test expression. The content of the first valid test is applied to the result document. Therefore, if the price is less than or equal to 20, the background color is set to light gray. If it is greater than 20, but less than 101, the background is set to green. All other items have a background set to red.

Looping

Although templates apply to each node in the selected node-set, on occasion, you need to loop through a set of elements not using a template. This is the purpose of the for-each element. This element takes a single select statement containing an XPath expression. The content of the element is then applied to each node selected by the query. (See Listing 8-8.)

Listing 8-8: Using the for-each element

image from book
      <xsl:for-each select="catalog/row">        <xsl:copy-of select="category" />      </xsl:for-each> 
image from book

Given the source XML document in Listing 8-9, it is possible to create a destination document using either for-each (see Listing 8-10) or template (see Listing 8-11).

image from book
Should I use for-each or templates?

To developers who come to XSLT from traditional languages, templates are often confusing. XSLT just does not seem "like a real programming language" to people used to writing if statements and loops. So, many stick to creating repeating structures with for-each.

For example, given a block of XML similar to the fragment in Listing 8-9 that contains a number of categories and products, you could create a summary report of the products and their prices using for-each as shown in Listing 8-10.

      Chai: 18.00      Chang: 19.00      Chartreuse verte: 18.00      Côte de Blaye: 263.50      Guaraná Fantástica: 4.50      Ipoh Coffee: 46.00      Lakkalikööri: 18.00      ... 

If you do so, however, you miss the true power of XSLT. Templates are just like the subroutines in languages like Java, C#, or C++. Rather than templates being called manually, however, the data itself calls them. Remember that templates represent an example of what the output should look like. They are similar to someone saying, "Put all the yellow triangles in the box and the green squares in the bag." You essentially define an example of the desired result and identify when each result should happen. The data then flows into each appropriate template, creating the result document.

image from book

Listing 8-9: A product listing

image from book
      <catalog>        <row >          <category>Beverages</category>          <product>            <name>Chai</name>            <price>18.0000</price>          </product>          </row>          <row >          <category>Beverages</category>          <product>            <name>Chang</name>            <price>19.0000</price>          </product>          </row>      ...          <row >          <category>Condiments</category>          <product>            <name>Aniseed Syrup</name>            <price>10.0000</price>          </product>           </row>          <row >          <category>Condiments</category>          <product>            <name>Chef Anton's Cajun Seasoning</name>            <price>22.0000</price>          </product>          </row>      ...      </catalog> 
image from book

Listing 8-10: Using for-each to process XML

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">        <xsl:output method="text" encoding="UTF-16" omit-xml-declaration="yes"/>        <xsl:template match="/"> <xsl:for-each select="catalog/row/product">          <xsl:value-of select="name" />:          <xsl:value-of select='format-          <xsl:text>&#x0D;</xsl:text>          </xsl:for-each>          </xsl:template>      </xsl:stylesheet> 
image from book

The for-each element extracts the matching elements from the XML. The contents of the element are performed for each of these extracted elements; in this case, the name and price are outputted. The internal XSLT function format-number converts the price to a value with two decimal places. Finally, because the output method is text, the <xsl:text>&#x0D;</xsl:text> expression adds a carriage return (hex 13) to force a new line.

Listing 8-11: Using templates to process XML

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">        <xsl:output method="text" encoding="UTF-16" omit-xml-declaration="yes"/>        <xsl:template match="/">          <xsl:apply-templates select="catalog/row/product" />         </xsl:template>          <xsl:template match="product">          <xsl:value-of select="name" />: <xsl:value-of select='format-number(price,      "#.00")'/>          <xsl:text>&#x0D;</xsl:text>          </xsl:template>      </xsl:stylesheet> 
image from book

The processing for each product occurs in the template identified using the match syntax. Although this is a trivial example, with only a single template, it demonstrates how using templates narrows the scope and makes change easier.

The for-each element (as well as the apply-templates element) takes an optional child element sort. This enables you to sort the content before the template or loop is applied. This element takes a number of optional attributes as shown in the following table.

Open table as spreadsheet

Attribute

Description

select

An XPath expression that defines the content to sort on. This is based on the current context. Therefore, it is based on the current selection in a for-each or apply-templates element.

data-type

The data type of the content-text, numeric, or a qname. The default is text.

lang

The language to be used for the sort, using the language code. It ensures that the correct sorting is applied for the selected language.

order

The sort order, either ascending or descending.

case-order

The sort order when items may begin with either upper-or lowercase characters. Can be either upper-first or lower-first.

Sorting is a resource-intensive process if you have a large document or if you sort within another loop. Therefore, you should apply a sort only if it is needed for your result. The following code applies a sort on a product before the product name and price are written.

      <xsl:for-each select="catalog/row/product">        <xsl: sort select="name" data-type="text" />        <xsl:value-of select="name" />:        <xsl:value-of select='format        <xsl:text>&#x0D;</xsl:text>      </xsl:for-each> 

Variables and Parameters

Stylesheets and templates sometimes require additional data during the transformation of a document, often in the form of calculated values or temporary data. For this reason, XSLT provides both variables and parameters.

Variables provide a name that may hold a value for processing. The value held by the variable may be any valid data type, including the schema types and node-sets. You create a variable using the variable element.

      <xsl:variable name="someName" select="expression">contents</xsl:variable> 

The name attribute is required and identifies the variable. The select attribute can be used to assign a value to the variable; alternatively, the content provides the value.

The scope of the variable depends on where it is defined. If defined at the top-level of the stylesheet, it is globally available. If it is defined within another element, then it is only available within that element.

You access the value of a variable (or parameter) elsewhere in the stylesheet using the $name syntax.

A param element is similar to the variable element, but it defines a variable passed to a template. For example, the fragment in Listing 8-12 defines a parameter used to calculate the tax on a product.

Listing 8-12: Using parameters and variables

image from book
      <xsl:template match="/">        <xsl:apply-templates select="//product">        <xsl:with-param name="rate" select="0.07" />          </xsl:apply-templates>      </xsl:template>      <xsl:template match="product">          <xsl:param name="rate" />          <xsl:copy>          <xsl:attribute name="id">            <xsl:value-of select="generate-id()" />          </xsl:attribute>          <xsl:attribute name="name">            <xsl:value-of select="name" />          </xsl:attribute>          <xsl:attribute name="priceWithTax">            <xsl:value-of select="format-number(price+(price*$rate), '#.00')" />          </xsl:attribute>          </xsl:copy>      </xsl:template> 
image from book

The root template calls the product template as you've done elsewhere, but it includes the with-param element. This provides the value that is passed to the product template. Therefore, the param named rate will hold the value 0.07. This value is used in the final highlighted line to provide the tax rate for the calculation.

Other Functions and Expressions

XSLT leverages the functionality of XPath for most of its functions, providing over 100 different functions for string-handling, date processing, and more. In addition, XSLT supports a number of built-in functions (see the following table).

Open table as spreadsheet

Function

Description

document

Enables access to XML documents other than the source document. This can be used to merge the nodes of another document with those of the source document.

 <xsl:for-each select="document(documentURL)/XPath/expression> ..<!-- process content here --> </xsl:for-each> 

key

Used with the key element to generate keys in the result document. See Listing 8-2 for an example of using the key function.

generate-id

Used to generate ids for your result document. These ids are guaranteed to be unique based on the current context.

      <cust>        <xsl:attribute name="id">          <xsl:value-of select="generate-id(contact/name)" />        </xsl:attribute>      </cust> 

format number

Formats a value based on a supplied mask or pattern. These are characters that will be replaced by the data. For example, the mask ###,###.00 would format numbers to two decimal places, adding a grouping character if they are larger than 1,000.

current

Returns the current node, essentially equivalent to the . XPath expression.

system-property

Used to query the implementation for information. Typically, this includes version and vendor information, but the vendor can provide any information using this function.

Extending XSLT

Just like other XML syntaxes, XSLT is not fixed; it can be extended through the use of additional names-paces. This enables implementers to add functionality. One notable and commonly used extension is available with the Microsoft XSLT engine. You can apply script to your templates with the addition of the msxsl:script element. This element allows the addition of script code, using JavaScript, VBScript, C#, VB .NET, or another active scripting language. It also permits the addition of procedural functionality to a template.

For example, XSLT 1.0 does not have any means of manipulating text, such as substring extraction or case changing. Script extensions can provide this functionality, as shown in Listing 8-13.

Listing 8-13: Extending XSLT with script

image from book
      <?xml version="1.0" encoding="UTF-8"?>      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"         xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:ex="urn:some-URI">         <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>         <msxsl:script language = "C#"  implements-prefix = "ex">          <![CDATA[          string delim = " ";          public  String upperCase(String value) {            return value.ToUpper();          }          public String firstToken(String value) {            string[] temp = value.Split(delim.ToCharArray());            return temp[0];          }          public String lastToken(String value) {            string[] temp = value.Split(delim.ToCharArray());             return temp[temp.Length-1];          } ]]>          </msxsl:script>          <xsl:template match="/">          <xsl:apply-templates select="//customer[@id='ANTON']/contact" />          </xsl:template>          <xsl:template match="contact">          <contact>            <fullName><xsl:value-of select="name" /></fullName>            <firstName><xsl:value-of select="ex:firstToken(name)" /></firstName>            <lastName><xsl:value-of select="ex:upperCase(ex:lastToken(name))" />      </lastName>          </contact>          </xsl:template>      </xsl:stylesheet> 
image from book

When extending XSLT, you must provide additional namespaces for your extensions. The Microsoft-defined namespace for its scripting extensions is urn:schemas-microsoft-com:xslt. In addition, a second namespace is added for the script functions themselves. You can include multiple script blocks-even in different languages-as long as each uses a different implements-prefix. This prefix is used later when calling the functions. The output of this script is the following:

      <contact xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:ex="urn:some-URI">         <fullName>Antonio Moreno</fullName>         <firstName>Antonio</firstName>         <lastName>MORENO</lastName>      </contact> 




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