Chapter 6 - We Want Results! | |
XSLT For Dummies | |
by Richard Wagner | |
Hungry Minds 2002 |
The difference between what constitutes an attribute and what constitutes a child element is often arbitrary, because both describe its parent in some way. In the coffee.xml file, for example, I defined a coffees name as an attribute of the coffee element, while its price is a child element. However, it could have just as easily been the reverse: name as a child element and price as an attribute. For my purposes here, Im not concerned about which technique is best, but the important thing for XSLT is that moving from element to attribute and from attribute to element can be a typical scenario when transforming documents. In the previous example, I move attributes from one element to another, but suppose I also want to tweak the structure of the coffee element too. In particular, I want to convert the price element into an attribute of coffee and add a new descriptions element that converts the taste and bestwith elements into attributes that describe coffee . I use the XSLT code shown here to do this task: <!-- coffee-convert_to_attr.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Move region name to be an attribute of coffees --> <xsl:template match="coffees"> <coffees region="{region/@name}"> <xsl:apply-templates/> </coffees> </xsl:template> <xsl:template match="coffee"> <coffee name="{@name}" origin="{@origin}" price="{price}"> <availability><xsl:value-of select="availability"/></availability> <descriptions taste="{taste}" bestwith="{bestwith}"/> </coffee> </xsl:template> </xsl:stylesheet> Although the first template rule moves the region name to be the coffees region attribute, the second template is what Id like to focus on. It reconstructs the coffee element attribute by using literal text and attribute value templates. The first two name="{@name}" origin="{@origin}" simply re-create the attributes that the coffee element already had. An attribute value template that returns the value of the price element creates the new price attribute. The descriptions element follows suit with the taste and bestwith attributes. The results look like this: <?xml version="1.0" encoding="utf-8"?> <coffees region="Latin America"> <coffee name="Guatemalan Express" origin="Guatemala" price="11.99"> <availability>Year-round</availability> <descriptions taste="Curiously Mild And Bland" bestwith="Breakfast"/> </coffee> <coffee name="Costa Rican Deacon" origin="Costa Rica" price="12.99"> <availability>Year-round</availability> <descriptions taste="Solid Yet Understated" bestwith="Dessert"/> </coffee> <coffee name="Ethiopian Sunset Supremo" origin="Ethiopia" price="14.99"> <availability>Limited</availability> <descriptions taste="Exotic and Untamed" bestwith="Chocolate"/> </coffee> <coffee name="Kenyan Elephantismo" origin="Kenya" price="9.99"> <availability>Year-round</availability> <descriptions taste="Thick And Chewy" bestwith="Elephant Ears"/> </coffee> </coffees> Remember In this example, the built-in template for the price element is not called, because I didnt use an xsl:apply-templates instruction in the coffee template rule. However, in cases in which the price element is applied, I need to define an empty template rule to prevent the price elements content from appearing both as an attribute and as an element.
|