Following the Rules-Based Approach to Stylesheet Development, Page 2
A Rule-Based Stylesheet
Let's look at how we might solve this problem using rule-based templates instead of a procedural-based approach. The "rules" in the rule-based template approach are the XPath expressions in the
match attribute that cause a particular template to be invoked.
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <xsl:apply-templates select="Customers"/> </body> </html> </xsl:template> <xsl:template match="Customers"> <table> <tr> <td>Customer</td> <td>City</td> <td>State</td> </tr> <xsl:apply-templates select="Customer"> <xsl:sort select="Name"/> </xsl:apply-templates> </table> </xsl:template> <xsl:template match="Customer"> <tr> <td><xsl:value-of select="Name"/></td> <td><xsl:value-of select="City"/></td> <td><xsl:value-of select="State/></td> </tr> </xsl:template> </xsl:stylesheet>
Now we have three templates in our stylesheet rather than one. There are no looping constructs, either. The first template creates the outer shell of HTML. The
<xsl:apply-templates select="Customers"/> statement causes the second template to be invoked since its
match attribute's rule is looking for
Customers nodes. This template builds the outer shell of the table. It in turn selects the
Customer nodes and causes the third templates to be invoked via the
<xsl:apply-templates select="Customer"> statement. Finally, the last template builds each table row. Note that this template will be invoked once for each
Customer. Looping occurs naturally with the rules-based approach.
Once again, try to imagine this as a complex HTML page. Your code would be divided up among the three templates rather than the single template in the procedural example. There would also be a good chance that each template would take up no more than a page worth of code.
It may be hard to believe if you haven't run the examples, but the procedural-based and rule-based stylesheets will produce identical output. If the end result is what counts, does it matter which approach you use?
I would argue yes, it does matter.
The procedural-based example had a single "godzilla" template that contained all of the HTML markup language as well as the looping logic required to create that markup. If this were a complex page, this template would span several pages' worth of code. It could be very difficult to track down the starting and ending HTML tags because they could span these several pages.
The rules-based example had three templates, each designed to process nodes in the XML document that matched the "rule" specified in its
match attribute. The HTML markup is divided neatly among the templates and is produced at the appropriate time. Each template would result in a manageable piece of code.
The coding guidelines for most languages strongly suggest having methods or procedures of no more than one page of code. A XSL template is analogous to a method, although it is invoked differently. Shorter templates are much easier to read, understand, and maintain. A template should do only one thing and do it well.
Because early efforts often become the basis for more involved endeavors, it's as important to form good programming habits when beginning your stylesheet development as with any other language. Calling procedural-based stylesheets an "anti-pattern" might be too strong a criticism of this approach because it definitely has its place or it wouldn't be there. However, making a resolution to force yourself to use the rule-based pattern early in your stylesheet career will pay dividends later. It is one of the core features of the language. As you can see from the side-by-side comparison, it can result in more maintainable code.
To download the sample xml file and stylesheets, click here.
This article doesn't cover other features of XSL that help you write modular and maintainable code, such as imports, includes, calling named templates, parameters, and so on. Rather, it focuses on one of the core features of the language: applying templates to certain nodes in the source document in a rules-based fashion.
|Other Articles Written by Jeff Ryan|
About the Author
|Jeff Ryan is an architect for Hartford Financial Services. He has eighteen years of experience in information technology in architecting and developing automated solutions to business problems. He may be reached at firstname.lastname@example.org.|