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.