XSLT Elements

Much of XSLT’s functionality is exercised in the form of elements that perform functions and tasks. In fact, the whole language is XML-based and describing its features is already the subject of several books. This section presents some of the XSLT elements and fundamentals so you can begin using it in your daily work.

The Stylesheet Element

The xsl:stylesheet element is always the root element of standalone stylesheets, and is also used for embedded stylesheets. The stylesheet element contains some optional and mandatory attributes that provide more details about the stylesheet to the XSLT processor. The specification defines a second root element in the XSLT namespace, called xsl:transform. This element is identical to xsl:stylesheet in every way but name, and can be used in place of xsl:stylesheet with no change in meaning.

The id attribute is optional. However, an identifier would certainly come in handy if this stylesheet were part of a larger XML document (as would be the case for an embedded stylesheet). The XML specification states that any attribute of type ID (not necessarily named id, but of the data type ID declared in the DTD) must be unique within any XML document. Use of an ID attribute on a stylesheet is powerful if you are dynamically generating several stylesheets collected together in a larger composite document.

The version attribute is required as it indicates which version of XSLT is being used. All xsl:stylesheet elements must have the version attribute. The root element of simplified stylesheets must also have a version attribute explicitly associated with the XSLT namespace, as shown in Example 6-1.

It is strongly recommended that you give a namespace prefix to the stylesheet elements to distinguish it from other elements that are part of the transformation or part of a larger document that contains the stylesheet. The URI of the namespace must be the W3C URI http://www.w3.org/1999/XSL/Transform.

A typical stylesheet element may start like this:

<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

In this example, the namespace and the version have been presented, but no id attribute is present.

Since XSLT can generate output, which is XML, HTML, or any other format, it is important to specify which form the output should take. This is done using the xsl:output element, which requires a single attribute:

<xsl:output method="xml"/>

The value of the method attribute can be xml, html, or text. The meaning of each of these values is roughly what you would expect. If the output should be XHTML, use the xml value. For all formats that are not XML or HTML, the text method allows control over each byte of the output, but the intended use is to generate text-based formats. If you need to generate formats such as RTF or any of the TeX-based languages, text is the right value to use. Many applications that require other formats can be satisfied by generating an XSL-FO document and then processing it using a processor that has a lot of information about details of the target format.

If the stylesheet does not contain an xsl:output element, or if the method attribute is not specified, the output is XML.

Creating a Template Element

The xsl:template element is regularly used to accomplish a great deal of work in the transformation process. This element is an XSLT instruction, and usually specifies a pattern for its invocation or defines a name so that it can be called by other parts of the XSL document. The body of the xsl:template element contains the output markup for when the template is either called or matched by the XSLT processor.

The attributes of the template element define optionally its name and matching rule (match). In addition to these attributes, mode and priority are available as well. The mode is used to indicate a namespace prefix to be considered by the XSLT processor when the xsl:apply-templates instruction (described in the next section) is used with a specific mode. The priority attribute is used to define a priority when the template is part of a collection of template elements that match the same pattern. In other words, when the XSLT processor has multiple templates to choose from, it defers to priority if specified.

The most important attribute here is match. The match attribute contains an XPath expression used to determine when the processor has hit the target element in the source XML document. For example, in the earlier address record, rather than parsing the document with SAX waiting for your event, use the following match attribute and XPath syntax to hit the first address line:

<xsl:template match="/addr-record/address1">

This expression starts with the root element addr-record and then further selects its child address1. To display the contents of this field, you could use the same expression in your select attribute (covered a little later in this chapter).

Earlier we created a template element to match an entire XML document and produce a complete HTML document. You can also use the template elements to match any element within the XML source document:

<xsl:template match="/addr-record/address1">
<html>
<head>
        <title>Transformed Address Record</title>
</head>
<body>
        <p>We have matched /addr-record/address1</p>
        <p><xsl:value-of select="/addr-record/address1"/></p>
</body>
</html>
</xsl:template>

In this example, you are matching an element address1 that is a child of the root addr-record element and then processing several rules and content. When the template is instantiated by the XSLT processor, it outputs the child elements of the template (in this case HTML) and processes any other XSLT elements contained therein. The result is the HTML written to standard output by the XSLT processor. If you run this modified version of the stylesheet against the XML document, you get the HTML expected in the previous code listing, but you also get the rest of the XML document’s character data trailing the HTML. This is because no instructions were given for the rest of the character data, so it is simply dumped out. The xsl:apply-templates element allows you to nest rules within each other to produce deeply nested documents that are transformed as expected.

Applying Templates

When you have a document that contains nested structures, the apply-templates element is used to recursively apply transformation rules throughout the document. An easy example that demonstrates the concept of nested structures is formatted text, wherein paragraphs may contain sentences with bold typeface of multiple colors, code examples, or other formatting structures that may appear nested within themselves.

Another deeply nested structure is a filesystem. A directory can contain any number of files and subdirectories. Each subdirectory follows the same content rule as any other and may contain any number of files and subdirectories. The resultant tree can become quite complex.

When dealing with XML documents containing nested structures, it may be desirable to establish a set of rules (templates) for specific tags, but allow those tags and rules to be nested inside each other. You can use the apply-templates elements to accomplish this. Consider the following XML:

<deep-nest>
        <title>Sample Text</title>
        <big>T</big>his is an example of
        <red>Fancy Text</red> that comes in
        <blue>m<big>u</big></blue><green>l<big>
        t</big></green><blue>i<big>p</big>
        </blue><green>l<big>e</big></green>
        colors.  Many of <bold>these</bold>
        elements are <big><green>N</green>
        <blue>E</blue><green>S</green><blue>T</blue>
        <green>E</green><blue>D</blue></big> within
        each other.
</deep-nest>

This XML fragment contains elements with other elements within them. There is no set order as to which tags can be embedded within others, as there is not a specified DTD. To account for this nesting in your template elements, use the xsl:apply-templates instruction. For example, the big element can occur within a color element, a bold element, or a title element. Therefore, its template element is:

<xsl:template match="big">
        <font size="5"><xsl:apply-templates/></font>
</xsl:template>

Wherever there is a big element, it is replaced with the font tag. Furthermore, any content within the big tag is processed against any other template patterns since the xsl:apply-templates instruction is specified. Now let’s take a look at the whole stylesheet used to process the XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="deep-nest">
        <html><body><xsl:apply-templates/></body></html>
</xsl:template>

<xsl:template match="title">
        <h1><xsl:apply-templates/></h1>
</xsl:template>

<xsl:template match="big">
        <font size="5"><xsl:apply-templates/></font>
</xsl:template>

<xsl:template match="red">
        <font size="3" color="#FF0000"><u>
        <xsl:apply-templates/></u></font>
</xsl:template>

<xsl:template match="blue">
        <font color="#0000FF"><xsl:apply-templates/></font>
</xsl:template>

<xsl:template match="green">
        <font color="#00FF00"><b><xsl:apply-templates/></b></font>
</xsl:template>

<xsl:template match="bold">
        <b><i><xsl:apply-templates/></i></b>
</xsl:template>

</xsl:stylesheet>

The key to this stylesheet is well-formedness. Every XML element in the source document is accounted for in the stylesheet, and each defers to further processing by placing xsl:apply-templates square in the middle. If you run the XML and stylesheet through your XSLT processor, you get the following HTML:

<html>
  <body>
    <h1>Sample Text</h1>
    <font size='5'>T</font>his is an example of
        <font color='#FF0000' size='3'>
      <u>Fancy Text</u>
    </font> that comes in
        <font color='#0000FF'>m<font size='5'>u</font>
    </font>
    <font color='#00FF00'>
      <b>l<font size='5'>
        t</font></b>
    </font>
    <font color='#0000FF'>i<font size='5'>p</font>
    </font>
    <font color='#00FF00'>
      <b>l<font size='5'>e</font></b>
    </font>
        colors. Many of <b><i>these</i></b>
        elements are <font size='5'>
      <font color='#00FF00'>
        <b>N</b>
      </font>
      <font color='#0000FF'>E</font>
      <font color='#00FF00'>
        <b>S</b>
      </font>
      <font color='#0000FF'>T</font>
      <font color='#00FF00'>
        <b>E</b>
      </font>
      <font color='#0000FF'>D</font>
    </font> within
        each other.
</body>
</html>

Getting the Value of a Node

The xsl:value-of element generates output from an expression. It has two possible attributes: select and disable-output-escaping. The select attribute is mandatory as it’s used to generate the replacement content. The select attribute takes an XPath expression. Given the XML <a><b><c id="c">content</c></b></a>, the following expression produces the word “content.”

<xsl:value-of select="/a/b/c"/>

To retrieve an attribute of an element, use the @ symbol in your select attribute:

<xsl:value-of select="/a/b/c/@id"/>

The disable-output-escaping attribute causes the XSLT processor to suppress encoding of characters that could be confused with markup. This can be useful when generating text output. For example, consider the document:

<doc>A &amp; B</doc>

and this template:

<xsl:template match="doc">
  <xsl:value-of select="text(  )" disable-output-escaping="yes"/>
</xsl:template>

If disable-output-escaping were allowed to have its default value of no, the result of the template would be presented as A &amp; B — but when the attribute is set to yes, the presentation is A & B. This is not needed if the output method is set to text using the xsl:output element.

We have already used the xsl:value-of element in the previous examples in this chapter, as it is core to XSLT.

Iterating over Elements

The xsl:for-each element allows you to iterate through certain element types inside a template match. It has a mandatory select attribute that defines the node set to be iterated. The select attribute can contain anything that results in a collection of elements or nodes, and can be as simple as an element name or another type of path expression.

The xsl:for-each element is helpful when you are working with mixed content and want only to transform a subset of elements within a document. For example, the following purchases XML document describes multiple types of purchases:

<?xml version="1.0"?>
<purchases>
        <product name="floppy disk" price="3.50"/>
        <service name="web updates" price="6.95"/>
        <product name="ink-jet cartridge" price="19.95"/>
        <service name="consulting" price="150h"/>
</purchases>

If you are interested only in the product purchases and not services, you could use the for-each element to select only the product elements:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
        <html><body><xsl:apply-templates/>
        </body></html>
</xsl:template>
<xsl:template match="purchases">
        <xsl:for-each select="product">
            <p>Product: <xsl:value-of select="./@name"/>
                 Price: <xsl:value-of select="./@price"/></p>
        </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

This stylesheet generates HTML detailing information about products, but not about services.

XSLT is a substantial programming language and extends well beyond the scope of this book. In addition to the elements covered here that allow you to select, search, and iterate source XML, XSLT features all sorts of standard language features such as control structures, conditionals, variables, and functions. There are several resources available from which you can learn more about XSLT; if you are considering using XSLT for your projects, a good tutorial introduction is well worth the time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.66.94