Kirk Evans Blog

.NET From a Markup Perspective

Splitting single column data into multiple column HTML tables

Splitting single column data into multiple column HTML tables

  • Comments 1

On the ASP.NET message boards, dorsai78664 asks how to create a multi-column table with single column data using XSLT. Given the input XML document:

<root>
 <ComputerName value ="ComputerA" />
 <ComputerName value ="ComputerB" />
 <ComputerName value ="ComputerC" />
 <ComputerName value ="ComputerD" />
 <ComputerName value ="ComputerE" />
 <ComputerName value ="ComputerF" />
 <ComputerName value ="ComputerG" />
 <ComputerName value ="ComputerH" />
 <ComputerName value ="ComputerI" />
 <ComputerName value ="ComputerJ" />
 </root>
 

Dorsai wanted to output this as an HTML table with each row containing only 6 columns.  The key is that the position() function is relative to the current node set. The pointer to the node (the context) is defined in the for-each select statement, so the first node selected is that with position = 1. The first tr is added to the result tree, and the current node (".") and its following 5 sibling nodes are selected and applied to the attribute template. This means that nodes 1-6 are selected in the first loop iteration. The mod() operation then selects node 7, because it is the next one where mod 6 = 1. The loop selects the current node ("."), which is node 7, and its following 5 sibling nodes, selecting 7-12 and applying the template.

<xsl:stylesheet version ="1.0" xmlns:xsl ="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match ="/" >
<html>
<table>
<xsl:for-each select ="/root/ComputerName[position() mod 6 = 1]" >
 <xsl:sort select ="@value" order ="ascending" />
<tr>
 <xsl:apply-templates select ="./@value | following-sibling::ComputerName[position() < 6]/@value" />
 </tr>
 </xsl:for-each>
 </table>
 </html>
 </xsl:template>
<xsl:template match ="@value" >
<td class ="normal" >
 <xsl:value-of select ="." />
 </td>
 </xsl:template>
 </xsl:stylesheet>

The result is:

<html>
<table>
<tr>
 <td class ="normal" >ComputerA</td>
 <td class ="normal" >ComputerB</td>
 <td class ="normal" >ComputerC</td>
 <td class ="normal" >ComputerD</td>
 <td class ="normal" >ComputerE</td>
 <td class ="normal" >ComputerF</td>
 </tr>
<tr>
 <td class ="normal" >ComputerG</td>
 <td class ="normal" >ComputerH</td>
 <td class ="normal" >ComputerI</td>
 <td class ="normal" >ComputerJ</td>
 </tr>
 </table>
 </html>
Leave a Comment
  • Please add 1 and 2 and type the answer here:
  • Post
Translate This Page
Search
Archive
Archives