Browse DevX
Sign up for e-mail newsletters from DevX


Occasional XSLT for Experienced Software Developers : Page 3

Although using XSLT to process XML is increasingly common, most developers still use it only occasionally—and often treat it as just another procedural language. But that's not the best way to use XSLT. Learn how to simplify and improve your XSLT processing using event-driven and declarative techniques.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Imperative XSLT
Unlike most programming languages, XSLT does not favor sequential execution. This is manifested by the verbosity of the related language constructs such as switch and for-each, and by weak support of side-effects (no variables in the traditional sense)

This common example illustrates the verbosity of the imperative approach, which constructs an HTML table, placing the book names in rows and alternating colors on odd and even rows from the input document:

<?xml version="1.0" encoding="utf-8"?> <table> <tr> <td style="color:red;">David Flannagan</td> </tr> <tr> <td style="color:blue;">David Flannagan</td> </tr> <tr> <td style="color:red;">Dan Margulis</td> </tr> </table>

Figure 1. Table with Alternating Colors: The figure shows how alternating red and blue rows of content might render in a browser.
Figure 1 shows how a browser would render the preceding code.

Here's how you can accomplish the task in the imperative style:

<?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output indent="yes" encoding="utf-8"/> <xsl:strip-space elements="*"/> <xsl:template match="row"> <table> <xsl:for-each select="book[1]"> <xsl:call-template name="process-book"> <xsl:with-param name="even" select="false()"/> </xsl:call-template> </xsl:for-each> </table> </xsl:template> <xsl:template name="process-book"> <xsl:param name="even"/> <xsl:choose> <xsl:when test="$even"> <tr><td style="color:blue;" > <xsl:value-of select="author"/></td></tr> </xsl:when> <xsl:otherwise> <tr><td style="color:red;" > <xsl:value-of select="author"/></td></tr> </xsl:otherwise> </xsl:choose> <xsl:for-each select="following-sibling::book[1]"> <xsl:call-template name="process-book"> <xsl:with-param name="even" select="not($even)"/> </xsl:call-template> </xsl:for-each> </xsl:template> <xsl:template match="text()"/> </xsl:stylesheet>

The stylesheet creates one table for each <row> element in the input, so it first matches the row tag. Then, it uses the for-each construct to change the execution context to the first book node, calling the process-book template for each with a parameter that controls the row color in the HTML table. The process-book template then outputs the row, with either a red or a blue color depending on the value of the parameter, and calls itself to process the next book element with the opposite parameter value.

As you can see, this processing method gets complex very quickly, and you'd need to alter it for every format alteration in the input XML file.

Declarative XSLT
For XSLT, declarative is the opposite of the common imperative or algorithmic strategy; that is, an XSLT programmer does not define a sequence of actions that form an algorithm but rather sets a number of rules that the result should satisfy.

The declarative nature of the language lets you place templates anywhere and in any order in the XSLT document, because order has no impact on the resulting document.

Author's Note: The preceding rule applies except in cases of conflict resolution where order is the last decision criteria.

Here is a stylesheet written with the declarative approach that provides the same output:

<?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output indent="yes" encoding="utf-8"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <table> <xsl:apply-templates select="@*|node()"/> </table> </xsl:template> <xsl:template match="book[(position() mod 2)=0]"> <tr><td style="color:red;"> <xsl:value-of select="author"/></td></tr> </xsl:template> <xsl:template match="book[(position() mod 2)=1]"> <tr><td style="color:blue;" > <xsl:value-of select="author"/></td></tr> </xsl:template> <xsl:template match="text()"/> </xsl:stylesheet>

In contrast to the procedural approach, this version doesn't define any algorithm. Instead, it specifies two templates for the processor to match: one for even-numbered rows and one for odd-numbered rows. The processor outputs the contents in red for even-numbered elements and in blue for odd-numbered elements.

Thanks for your registration, follow us on our social networks to keep up-to-date