When displaying a web page containing multiple rows of data it is quite common to use the single-column view, as shown in figure 1:
Figure 1 - a single column view
But what happens if each row of data is quite narrow and you want to put more than one row on the same line? You want to display the rows side-by-side in a two-column view, as shown in figure 2:
Figure 2 - a two column view
This may be quite simple when you are constructing the web page from within a PHP script, but how do you achieve the same result with an XSL stylesheet? As I have recently had cause to produce a side-by-side view with XSL this article will explain how I achieved it. It may not be the only way, so if you have found an alternative perhaps you would let me know so I can publish it.
Here is a typical XSL stylesheet that will produce a single-column view:
<?xml version='1.0'?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method='html'/> <xsl:template match="/"> <html> <head> <meta http-equiv="Content-Type" content="text/html" /> <title>...title...</title> <link rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <form method="post" action="blah.php"> <div id="content"> <h1>...title...</h1> <table> <thead> <tr> <th>Heading 1</th> <th>Heading 2</th> </tr> </thead> <tbody> <xsl:apply-templates select="//stuff" /> </tbody> </table> </div> </form> </body> </html> </xsl:template> <xsl:template match="stuff"> <tr> <!-- set the row class to 'odd' or 'even' to determine the colour --> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="position()mod 2">odd</xsl:when> <xsl:otherwise>even</xsl:otherwise> </xsl:choose> </xsl:attribute> <td><xsl:value-of select="stuff_1"/></td> <td><xsl:value-of select="stuff_2"/></td> </tr> </xsl:template> </xsl:stylesheet>
Here is the same stylesheet after it has been changed to output two columns of data side-by-side. See if you can spot the differences (hint: they are highlighted).
<?xml version='1.0'?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method='html'/> <xsl:template match="/"> <html> <head> <meta http-equiv="Content-Type" content="text/html" /> <title>...title...</title> <link rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <form method="post" action="blah.php"> <div id="content"> <h1>...title...</h1> <table> <thead> <tr> <th>Heading 1</th> <th>Heading 2</th> <th>Heading 1</th> (1) <th>Heading 2</th> </tr> </thead> <tbody> <xsl:apply-templates select="//stuff[position()mod 2=1]" /> (2) </tbody> </table> </div> </form> </body> </html> </xsl:template> <xsl:template match="stuff"> <tr> <!-- set the row class to 'odd' or 'even' to determine the colour --> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="position()mod 2">odd</xsl:when> <xsl:otherwise>even</xsl:otherwise> </xsl:choose> </xsl:attribute> <!-- these table cells contain the data for 'odd' numbered rows --> <td><xsl:value-of select="stuff_1"/></td> <td><xsl:value-of select="stuff_2"/></td> <!-- these table cells contain the data for 'even' numbered rows --> (3) <xsl:choose> <!-- look for a sibling with same name as current node --> <xsl:when test="count(following-sibling::*[name()=name(current())])"> <td><xsl:value-of select="following-sibling::*/stuff_1"/></td> <td><xsl:value-of select="following-sibling::*/stuff_2"/></td> </xsl:when> <!-- there is nothing to follow, so create empty cells --> <xsl:otherwise> <td></td> <td></td> </xsl:otherwise> </xsl:choose> </tr> </xsl:template> </xsl:stylesheet>
Here is a description of the changes which are highlighted and numbered:
As you can see the "stuff" template is only called for odd numbered rows, but it processes an odd and an even numbered row at the same time. Isn't it easy when you know how?
Don't applaud, just throw money.