Note: For this tip, you can use any XSLT processor, such as Xalan or Saxon, or a browser-based solution, such as Microsoft Internet Explorer or Mozilla.
This tip describes a style sheet that converts an XML announcement into HTML. The overall goal is to provide default templates, but to allow the user enough latitude to change certain aspects of the style sheet if desired. Other aspects are not changeable. The style sheets work with the following source document:
Listing 1. The source document
<?xml version="1.0"?>
<?xml-stylesheet href="style.xsl" version="1.0"
type="text/xsl"?>
<announcement>
<headline>Contest Announcement</headline>
<description>
Do you love
<product>Pop's Homemade Mashed Potato Mix</product>?
Are you artistic? Well, here's your big big chance!
Loopy Foods, the company that brings you
<product>Pop's Homemade Mashed Potato Mix</product>
and <product>Aunt Susie's Squash in a Box</product>
is hosting a Mashed Potato Sculpting Contest. Send your
entry today. Contest rules are on the back of every box
of <product>Pop's Homemade Mashed Potato Mix</product>.
</description>
<copyright/>
</announcement> |
The goal is to create an HTML page with a style sheet such as this:
Listing 2. The basic style sheet
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head><title><xsl:value-of select="announcement/headline"/></title></head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="headline">
<h1><xsl:apply-templates/></h1>
</xsl:template>
<xsl:template match="description">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="product">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>
|
The result is a document that creates a paragraph for each announcement, and puts the product names in bold:
Listing 3. The basic transformation results
<html>
<head><title>Contest Announcement</title></head>
<body>
<h1>Contest Announcement</h1>
<p>
Do you love <b>Pop's Homade Mashed Potato Mix</b>?
Are you artistic? Well, here's your big big chance! Loopy Foods, the
company that brings you <b>Pop's Homemade Mashed Potato Mix</b>
and <b>Aunt Susie's Squash in a Box</b> is hosting a Mashed Potato
Sculpting Contest. Send your entry today. Contest rules are on the
back of every box of <b>Pop's Homemade Mashed Potato Mix</b>.
</p>
</body>
</html>
|
Creating the template style sheet
Using these templates, an administrator can build a basic style sheet that enables users to use default styles, but allows them to use custom styles if necessary. To do this, you need to include the basic templates in a second style sheet, in this case called import.xsl:
Listing 4. The imported style sheet (import.xsl)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="headline">
<h1><xsl:apply-templates/></h1>
</xsl:template>
<xsl:template match="description">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="product">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>
|
From there, it's a matter of creating a style sheet that imports the main styles. With this import in place, a style sheet that contains only the main template still acts as desired, but if an additional template is added, it overrides the corresponding template in the import:
Listing 5. Overriding imported templates
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="import.xsl"/>
<xsl:template match="/">
<html>
<head><title><xsl:value-of select="announcement/headline"/></title></head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="product">
<i><xsl:apply-templates/></i>
</xsl:template>
</xsl:stylesheet>
|
Imported style sheets have a lower precedence than the main style sheet, so the product template in the main style sheet is used instead of the imported product template:
Listing 6. Overridden template results
<html>
<head><title>Contest Announcement</title></head>
<body>
<h1>Contest Announcement</h1>
<p>
Do you love <i>Pop's Homade Mashed Potato Mix</i>?
Are you artistic? Well, here's your big big chance! Loopy Foods, the
company that brings you <i>Pop's Homemade Mashed Potato Mix</i>
and <i>Aunt Susie's Squash in a Box</i> is hosting a Mashed Potato
Sculpting Contest. Send your entry today. Contest rules are on the
back of every box of <i>Pop's Homemade Mashed Potato Mix</i>.
</p>
</body>
</html> |
Even when a template is overridden, you still have the opportunity to use the imported templates, however, using the apply-imports option:
Listing 7. Applying imports
...
</html>
</xsl:template>
<xsl:template match="product">
<i><xsl:apply-imports/></i>
</xsl:template>
</xsl:stylesheet> |
As a result, both the original template and the imported template are executed:
Listing 8. Using overridden templates
<html>
<head><title>Contest Announcement</title></head>
<body>
<h1>Contest Announcement</h1>
<p>
Do you love <i><b>Pop's Homade Mashed Potato Mix</b></i>?
Are you artistic? Well, here's your big big chance! Loopy Foods, the
company that brings you <i><b>Pop's Homemade Mashed Potato Mix</b></i>
and <i><b>Aunt Susie's Squash in a Box</b></i> is hosting a Mashed Potato
Sculpting Contest. Send your entry today. Contest rules are on the
back of every box of <i><b>Pop's Homemade Mashed Potato Mix</b></i>.
</p>
</body>
</html> |
The difference between importing and including
An import element must always be a top-level element, and must always come before any other elements. This requirement has a specific consequence in terms of precedence. In an XSLT style sheet, the last template processed has precedence over everything that has come before, so imported templates are always overridden. Imported templates also become part of the import tree, so they're available for the apply-imports element.
On the other hand, style sheets can also be included using the include element, which simply adds them to the main style sheet at the point in which they're included. What's more, while a style sheet must be included at the top level, it can be added at any point, so it can easily be added at the bottom of the page, overriding any templates the user might add.
For example, you could create an included style sheet that sets the copyright information, called include.xsl:
Listing 9. The included style sheet (include.xsl)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="copyright">
<p>Copyright 2003, Loopy Foods</p>
</xsl:template>
</xsl:stylesheet> |
When this style sheet is included at the end of the main style sheet, it overrides any other templates:
Listing 10. Including the style sheet
...
<xsl:template match="product">
<i><xsl:apply-imports/></i>
</xsl:template>
<xsl:template match="copyright">
<p><big>Copyright now, by ME</big></p>
</xsl:template>
<xsl:include href="include.xsl"/>
</xsl:stylesheet> |
So even though the main style sheet includes a copyright template, the included template is still used:
Listing 11. Inclusion results:
...
Sculpting Contest. Send your entry today. Contest rules are on the
back of every box of <i><b>Pop's Homemade Mashed Potato Mix</b></i>.
</p>
<p>Copyright 2003, Loopy Foods</p>
</body>
</html> |
Remember that the precedence is a matter of position; if the style sheet (include.xsl) had been included at the start of the main style sheet rather than the bottom, the copyright template in the main stylesheet (style.xsl) would have been used instead.
In addition to the basic rules about imports and includes, XSLT allows fine-grained control over which template is applied using the precedence attribute. With judicious use of all these techniques, you can enable your users to customize specific portions of a style sheet while still maintaining control over the rest.
- Check out the XSLT 1.0 Recommendation from the W3C.
- Get a look at different approaches for structuring style sheets with
"XML for Data: XSL style sheets: push or pull?" (developerWorks, May 2002) and "Multi-pass
XSLT" (developerWorks, September 2002).
- Find more XML resources on the developerWorks XML zone. For a complete list of XML tips to date, check out the tips summary page.
-
IBM trial software: Build your next development project with trial software available for download directly from developerWorks.
- Find out how you can become an IBM Certified Developer in XML and related technologies.
- Want us to send you useful XML tips like this every week? Sign up for the developerWorks XML Tips newsletter.
Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of Site Dynamics Interactive Communications in Clearwater, Florida, USA, and is the author of three books on Web development, including Java and XML From Scratch (Que) and the upcoming Primer Plus XML Programming (Sams). He loves to hear from readers and can be reached at nicholas@nicholaschase.com.