With a "global" (for every cell in table) $maxWith
you could handle colspans like this stylesheet (preserving your own logic):
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<output method="text"/>
<variable name="newline" select="' '"/>
<template match="xhtml:table">
<variable name="maxWidth">
<for-each select="xhtml:tr/xhtml:th | xhtml:tr/xhtml:td">
<sort select="string-length(child::text()|child::node())" order="descending" data-type="number"/>
<if test="position() = 1">
<value-of select="string-length(child::text()|child::node())"/>
</if>
</for-each>
</variable>
<for-each select="xhtml:tr">
<for-each select="xhtml:th|xhtml:td">
<variable name="string">
<for-each select="child::text()|child::node()">
<value-of select="."/>
</for-each>
</variable>
<variable name="padding">
<choose>
<when test="@colspan">
<value-of select="$maxWidth * @colspan + @colspan - 1 - string-length($string)"/>
</when>
<otherwise>
<value-of select="$maxWidth - string-length($string)"/>
</otherwise>
</choose>
</variable>
<value-of select="$string"/>
<call-template name="append-pad">
<with-param name="length" select="$padding"/>
</call-template>
<text> </text>
</for-each>
<value-of select="$newline"/>
</for-each>
<value-of select="$newline"/>
</template>
<template name="append-pad">
<param name="length" select="0"/>
<if test="$length != 0">
<value-of select="' '"/>
<call-template name="append-pad">
<with-param name="length" select="$length - 1"/>
</call-template>
</if>
</template>
</stylesheet>
Input:
<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<th>First</th>
<th>Second</th>
<th>Third</th>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<td colspan="2">Uno</td>
<td>Tres</td>
</tr>
</table>
Output:
First Second Third
One Two Three
Uno Tres
EDIT: In order to center the cells with colspan, use this stylesheet (now with my own logic):
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<output method="text"/>
<variable name="newline" select="' '"/>
<template match="xhtml:table">
<apply-templates>
<with-param name="maxWidth">
<for-each select="xhtml:tr/xhtml:th | xhtml:tr/xhtml:td">
<sort select="string-length(.)" order="descending" data-type="number"/>
<if test="position() = 1">
<value-of select="string-length(.)"/>
</if>
</for-each>
</with-param>
</apply-templates>
<value-of select="$newline"/>
</template>
<template match="xhtml:tr">
<param name="maxWidth"/>
<apply-templates>
<with-param name="maxWidth" select="$maxWidth"/>
</apply-templates>
<value-of select="$newline"/>
</template>
<template match="xhtml:th|xhtml:td">
<param name="maxWidth"/>
<variable name="string">
<for-each select="child::text()|child::node()">
<value-of select="."/>
</for-each>
</variable>
<variable name="padding">
<choose>
<when test="@colspan">
<value-of select="($maxWidth * @colspan + @colspan - 1 - string-length($string)) div 2"/>
</when>
<otherwise>
<value-of select="$maxWidth - string-length($string)"/>
</otherwise>
</choose>
</variable>
<if test="@colspan">
<call-template name="append-pad">
<with-param name="length" select="floor($padding)"/>
</call-template>
</if>
<value-of select="$string"/>
<call-template name="append-pad">
<with-param name="length" select="ceiling($padding)"/>
</call-template>
<text> </text>
</template>
<template name="append-pad">
<param name="length" select="0"/>
<if test="$length != 0">
<value-of select="' '"/>
<call-template name="append-pad">
<with-param name="length" select="$length - 1"/>
</call-template>
</if>
</template>
</stylesheet>
Output:
First Second Third
One Two Three
Uno Tres