Rendering a node sequence as M x N table
You must ensure that nesting is never broken. Things you want nested in the output must be nested in the XSLT.
<xsl:variable name="perRow" select="3" />
<xsl:template match="recordset">
<table>
<xsl:apply-templates
mode = "tr"
select = "record[position() mod $perRow = 1]"
/>
</table>
</xsl:template>
<xsl:template match="record" mode="tr">
<tr>
<xsl:variable name="td" select="
. | following-sibling::record[position() < $perRow]
" />
<xsl:apply-templates mode="td" select="$td" />
<!-- fill up the last row -->
<xsl:if test="count($td) < $perRow">
<xsl:call-template name="filler">
<xsl:with-param name="rest" select="$perRow - count($td)" />
</xsl:call-template>
</xsl:if>
</tr>
</xsl:template>
<xsl:template match="record" mode="td">
<td>
<xsl:value-of select="." />
</td>
</xsl:template>
<xsl:template name="filler">
<xsl:param name="rest" select="0" />
<xsl:if test="$rest">
<td />
<xsl:call-template name="filler">
<xsl:with-param name="rest" select="$rest - 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Using xslt 2.0
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:param name="rows">3</xsl:param>
<xsl:template match="recordset">
<table>
<xsl:for-each-group select="record" group-by="count(preceding-sibling::*) mod $rows ">
<xsl:value-of select="current-grouping-key()"/>
<tr>
<xsl:for-each select="current-group()">
<td>
<xsl:apply-templates/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:stylesheet>