XSLT for Dummies
|
Chapter 6 - We Want Results! | |
XSLT For Dummies | |
by Richard Wagner | |
Hungry Minds 2002 |
You can add a new element to the result tree by using one of two methods : literal text or the xsl:element instruction.
Using literal text
The simplest technique for creating a new element in your output is to simply create it in your stylesheet as literal text. Suppose, for example, that I want to add an online element as a child to the coffee element. This new element is used to indicate whether a particular type of coffee is available as an online purchase. In this example, all the coffees are defined the same, so I can define the elements content of Yes as literal text too. I begin by showing you the long version for this process and then explain a more efficient technique after that. For starters, here is a stylesheet that can be used for this transformation:
<!-- coffee-addelement_literal.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Add new element --> <xsl:template match="coffee"> <coffee> <taste><xsl:value-of select="taste"/></taste> <price><xsl:value-of select="price"/></price> <availability><xsl:value-of select="availability"/></availability> <bestwith><xsl:value-of select="taste"/></bestwith> <online>Yes</online> </coffee> </xsl:template> <!-- Recreate the top level node --> <xsl:template match="/"> <coffees> <xsl:apply-templates/> </coffees> </xsl:template> </xsl:stylesheet> The coffee template rule uses the reconstruction method I showed you earlierentering literal text to define the element tags and xsl:value-of to bring in the content of the matching child element from the source tree. The online element is simply added onto the end. To retain coffees as the document element, I recreate it with the second template rule. Its purpose is to use xsl:apply-templates to apply to every element, surrounding those results with a coffees tag pair. (Remember, I need to add these tags back into the result document, because the built-in template rules automatically strip them out.) After the transformation is performed, the following result is produced: <?xml version="1.0" encoding="utf-8"?> <coffees> <coffee> <taste>Curiously Mild And Bland</taste> <price>11.99</price> <availability>Year-round</availability> <bestwith>Breakfast</bestwith> <online>Yes</online> </coffee> <coffee> <taste>Exotic and Untamed</taste> <price>12.99</price> <availability>Year-round</availability> <bestwith>Dessert</bestwith> <online>Yes</online> </coffee> <coffee> <taste>Exotic and Untamed</taste> <price>14.99</price> <availability>Limited</availability> <bestwith>Chocolate</bestwith> <online>Yes</online> </coffee> <coffee> <taste>Solid Yet Understated</taste> <price>9.99</price> <availability>Year-round</availability> <bestwith>Elephant Ears</bestwith> <online>Yes</online> </coffee> </coffees> Tip The coffee template rule contains both literal text elements as well as XSLT instructions. A logical question you may be asking curiously is, "How does the XSLT processor know a literal element from an XSLT command?" The answer lies in the namespace: It treats all elements outside the xsl namespace as plain text and avoids trying to process them during transformations. Although the previous example is perfectly valid and produces the intended results, it sure is a lot of work to reconstruct several elements that dont change at all from the source to the result document. A much more efficient way to do the same task is as follows :
<!-- coffee-addelement_literal2.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Add new element --> <xsl:template match="coffee"> <coffee> <xsl:apply-templates/> <online>Yes</online> </coffee> </xsl:template> <!-- Copy everything else over --> <xsl:template match="@*node()"> <xsl:copy> <xsl:apply-templates select="@*node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> This stylesheet produces the exact same result tree as the previous example. It does so by defining two template rules. The coffee template rule focuses on recreating the coffee element tags and adding the new online element. These literal text nodes are added to the result tree using xsl:applytemplates . The second template rule is a nifty catchall template that is used to copy everything else over into the result document. It allows you to ignore the children elements that dont change as you create the coffee template rule.
Using xsl:element
In addition to adding elements using literal text, XSLT provides a specific instruction for adding elements: xsl:element . The xsl:element uses a name attribute to define the elements name while the content of the instruction defines the value. For example: <xsl:element name="dog">Sheepdog</xsl:element> This code produces the following element: <dog>Sheepdog</dog> I can use xsl:element to achieve the same result as with the previous example, simply by substituting the literal text for an xsl:element instruction:
<!-- coffee-addelement_instr.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Add new element using xsl:element --> <xsl:template match="coffee"> <coffee> <xsl:apply-templates/> <xsl:element name="online">Yes</xsl:element> </coffee> </xsl:template> <!-- Copy everything else over --> <xsl:template match="@*node()"> <xsl:copy> <xsl:apply-templates select="@*node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
|