Book HomeJava and XSLTSearch this book

2.6. Outputting Dynamic Attributes

Let's assume we have an XML document that lists books in a personal library, and we want to create an HTML document with links to these books on Amazon.com. In order to generate the hyperlink, the href attribute must contain the ISBN of the book, which can be found in our original XML data. An example of the URL we would like to generate is as follows:

<a href="http://www.amazon.com/exec/obidos/ASIN/0596000162">Java and XML</a>

One thought is to include <xsl:value-of select="isbn"/> directly inside of the attribute. However, XML does not allow you to insert the less-than (<) character inside of an attribute value:

<!-- won't work... -->
<a href="<xsl:value-of select="isbn"/>">Java and XML</a>

We also need to consider that the attribute value is dynamic rather than static. XSLT does not automatically recognize content of the href="..." attribute as an XPath expression, since the <a> tag is not part of XSLT. There are two possible solutions to this problem.

2.6.1. <xsl:attribute>

In the first approach, <xsl:attribute> is used to add one or more attributes to elements. In the following template, an href attribute is added to an <a> element:

<xsl:template match="book">
  <li>
    <a>  <!-- the href attribute is generated below -->
      <xsl:attribute name="href">
        <xsl:text>http://www.amazon.com/exec/obidos/ASIN/</xsl:text>
        <xsl:value-of select="@isbn"/>
      </xsl:attribute>
      <xsl:value-of select="title"/>
    </a>
  </li>
</xsl:template>

The <li> tag is used because this is part of a larger stylesheet that presents a bulleted list of links to each book. The <a> tag, as you can see, is missing its href attribute. The <xsl:attribute> element adds the missing href. Any child content of <xsl:attribute> is added to the attribute value. Because we do not want to introduce any unnecessary whitespace, <xsl:text> is used. Finally, <xsl:value-of> is used to select the isbn attribute.

2.6.2. Attribute Value Templates

Using <xsl:attribute> can be quite complex for a simple attribute value. Fortunately, XSLT provides a much simpler syntax called attribute value templates (AVT). The next example uses an AVT to achieve the identical result:

<xsl:template match="book">
  <li>
    <a href="http://www.amazon.com/exec/obidos/ASIN/{@isbn}">
      <xsl:value-of select="title"/>
    </a>
  </li>
</xsl:template>

The curly braces ({}) inside of the attribute value cause the magic to happen. Normally, when the stylesheet encounters attribute values for HTML elements, it treats them as static text. The braces tell the processor to treat a portion of the attribute dynamically.

In the case of {@isbn}, the contents of the curly braces is treated exactly as <xsl:value-of select="@isbn"/> in the previous approach. This is obviously much simpler. The text inside of the {} characters can be any location path, so you are not limited to selecting attributes. For example, to select the title of the book, simply change the value to {title}.

So where do you use AVTs and where don't you? Well, whenever you need to treat an attribute value as an XPath expression rather than static text, you may need to use an AVT. But for standard XSLT elements, such as <xsl:template match="pattern">, you don't need to use the AVT syntax. For nonXSLT elements, such as any HTML tag, AVT syntax is required.

2.6.3. <xsl:attribute-set>

There are times when you may want to define a group of attributes that can be reused. For this task, XSLT provides the <xsl:attribute-set> element. Using this element allows you to define a named group of attributes that can be referenced from other points in a stylesheet. The following stylesheet fragment shows how to define an attribute set:

<xsl:attribute-set name="body-style">
  <xsl:attribute name="bgcolor">yellow</xsl:attribute>
  <xsl:attribute name="text">green</xsl:attribute>
  <xsl:attribute name="link">navy</xsl:attribute>
  <xsl:attribute name="vlink">red</xsl:attribute>
</xsl:attribute-set>

This is a " top level element," which means that it can occur as a direct child of the <xsl:stylesheet> element. The definition of an attribute set does not have to come before templates that use it. The attribute set can be referenced from another <xsl:attribute-set>, from <xsl:element>, or from <xsl:copy> elements. We will talk about <xsl:copy> in the next chapter, but here is how <xsl:element> is used:

<xsl:template match="/">
  <html>
    <head>
      <title>Demo of attribute-set</title>
    </head>
    <xsl:element name="body" use-attribute-sets="body-style">
      <h1>Books in my library...</h1>
      <ul>
        <xsl:apply-templates select="library/book"/>
      </ul>
    </xsl:element>
  </html>
</xsl:template>

As you can probably guess, the code shown here will output an HTML body tag that looks like this:

<body bgcolor="yellow" text="green" link="navy" vlink="red">
...body content
</body>

In this particular example, the <xsl:attribute-set> was used only once, so its value is minimal. It is possible for one stylesheet to include another, however, as we will see in the next chapter. In this way, you can define the <xsl:attribute-set> in a fragment of XSLT included in many other stylesheets. Changes to the shared fragment are immediately reflected in all of your other stylesheets.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.