Following the excellent response from Dimitre, another style sheet without keys.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="ObjectGroup">
<html>
<table border="1">
<xsl:apply-templates select="Object[@columnNo=0]"/>
</table>
</html>
</xsl:template>
<xsl:template match="Object">
<xsl:variable name="td"
select=".|following-sibling::*[@columnNo!=0][
count(current()|
preceding-sibling::*[@columnNo=0][1]
)=1]"/>
<tr>
<xsl:apply-templates select="$td/Value">
<xsl:with-param name="td-count" select="count($td)"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="Value">
<xsl:param name="td-count"/>
<td width="{100 div $td-count}%">
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
However, most XSLT processors allow the use of keys.
Now, for colspan:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:variable name="td-max">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="/*/*/Object[@columnNo=0]"/>
</xsl:call-template>
</xsl:variable>
<xsl:template name="max">
<xsl:param name="nodes"/>
<xsl:if test="$nodes">
<xsl:variable name="head"
select="count($nodes[1]/following-sibling::*[@columnNo!=0][
count($nodes[1]|
preceding-sibling::*[@columnNo=0][1]
)=1])+1"/>
<xsl:variable name="tail">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$head > $tail or $tail=''">
<xsl:value-of select="$head"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tail"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="ObjectGroup">
<html>
<table border="1">
<xsl:apply-templates select="Object[@columnNo=0]"/>
</table>
</html>
</xsl:template>
<xsl:template match="Object">
<xsl:variable name="td"
select=".|following-sibling::*[@columnNo!=0][
count(current()|
preceding-sibling::*[@columnNo=0][1]
)=1]"/>
<tr>
<xsl:apply-templates select="$td/Value">
<xsl:with-param name="td-count" select="count($td)"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="Value">
<xsl:param name="td-count"/>
<td width="{100 div $td-count}%">
<xsl:if test="position()=last() and $td-max > $td-count">
<xsl:attribute name="colspan">
<xsl:value-of select="$td-max - $td-count + 1"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
Edit: Added dynamic colspan. It could be less verbose if you don't care multiple colspan="1"
.
Edit 2: Better max pattern.