Splitting single column data into multiple column HTML tables
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 ="**https://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>