XSLT for Dummies
|
Chapter 6 - We Want Results! | |
XSLT For Dummies | |
by Richard Wagner | |
Hungry Minds 2002 |
Because XSLTs built-in templates automatically add the content of elements, you frequently have occasions when you need to prevent an element from appearing in the result document. XSLT doesnt have a remove instruction, but you can ensure an element doesnt appear in the transformation by using one of two methods .
Explicitly removing an element
The first technique is to explicitly delete an element by defining an empty template rule and using the element as the rules match pattern. An empty template rule is one that has a match pattern defined but no accompanying template. For example: <xsl:template match="dog"/> An empty template rule tells the processor to grab a node set and deliberately do nothing with it. As an illustration, I produce a result document that removes the taste and bestwith elements as part of the coffee element. After I set up my stylesheet, it looks like the following:
<!-- coffee-remove.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Remove taste element --> <xsl:template match="taste"/> <xsl:template match="bestwith"/> <!-- Copy everything else over --> <xsl:template match="@*node()"> <xsl:copy> <xsl:apply-templates select="@*node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> By defining an empty template rule for the taste and bestwith elements, I remove these as part of the result. I can then use my "catch-all" template rule to simply copy everything else over. The XML code generated from the transformation looks like: <?xml version="1.0" encoding="utf-8"?> <coffees> <region name="Latin America"> <coffee name="Guatemalan Express" origin="Guatemala"> <price>11.99</price> <availability>Year-round</availability> </coffee> <coffee name="Costa Rican Deacon" origin="Costa Rica"> <price>12.99</price> <availability>Year-round</availability> </coffee> </region> <region name="Africa"> <coffee name="Ethiopian Sunset Supremo" origin="Ethiopia"> <price>14.99</price> <availability>Limited</availability> </coffee> <coffee name="Kenyan Elephantismo" origin="Kenya"> <price>9.99</price> <availability>Year-round</availability> </coffee> </region> </coffees> Remember Because the taste and bestwith elements dont contain any other elements, running empty template rules on them only removed these two elements and nothing else. However, keep in mind, if you create an empty template rule for an element with children, the empty rule removes the specified element along with its children during the transformation. For example, running <xsl:template match="coffees"/> on the coffee.xml file generates an empty document, because coffees contains all other elements.
Implicitly removing an element
You can also implicitly remove an element by essentially ignoring it when template rules are applied. To demonstrate , imagine that you want to generate a new selectcoffees structure that removes the region , taste , and bandwidth elements. Heres the XSLT code that you use to do this operation:
<!-- coffee-remove2.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <selectcoffees> <xsl:apply-templates/> </selectcoffees> </xsl:template> <!-- Copy coffee and its price and availability children --> <xsl:template match="coffee"> <coffee> <price><xsl:apply-templates select="price"/></price> <availability><xsl:apply-templates select="availability"/></availability> </coffee> </xsl:template> </xsl:stylesheet> A new document element named selectcoffees is created in the first template. The start and end tags of selectcoffees is plugged in before and after the xsl:apply-templates instruction, which is run on all descendants of the root node (the / match pattern). The coffee template rule reconstructs the coffee element, but it does so by using literal text to redefine the price and availability tags and by using xsl:apply-templates to generate the child elements content. Notice that the context for these xsl:apply-templates instructions is very specific because the select attribute is defined for them, applying just the price and availability elements. As a result, taste and bestwith elements are summarily dropped from the result document. (Boy, XSLT is a tough business!) I also want to get rid of the region element, but because it doesnt have any text nodes defined as content, I simply allowed the built-in template rule to do its thing; in doing so, the region element tags arent added to the result document. The end result is a new selectcoffees structure: <?xml version="1.0" encoding="utf-8"?> <selectcoffees> <coffee> <price>11.99</price> <availability>Year-round</availability> </coffee> <coffee> <price>12.99</price> <availability>Year-round</availability> </coffee> <coffee> <price>14.99</price> <availability>Limited</availability> </coffee> <coffee> <price>9.99</price> <availability>Year-round</availability> </coffee> </selectcoffees>
|