column-number or number of cells in the row overflows the number of fo:table-column specified for the table
...these tend to be a nightmare to track down, and very fiddly to fix, because often you need to add a number-columns-spanned attribute to one of the fo:table-cell elements, and in a dynamic world you have to figure out exactly how many cells to span. Agh!
It'd be much easier if XSL-FO let you just say number-columns-spanned="remainder". So today I wrote a little XSLT that you can put after your XSL-FO and before you try to serialize it (with something like Apache FOP).
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- number-columns-spanned: remainder -->
<xsl:template match="fo:table-cell[@number-columns-spanned = 'remainder']" mode="#all">
<xsl:copy>
<xsl:attribute name="number-columns-spanned">
<xsl:variable name="number-columns-in-table" as="xs:integer">
<xsl:value-of select="count(ancestor::fo:table[1]/fo:table-column)"/>
</xsl:variable>
<xsl:variable name="number-columns-in-row" as="xs:integer">
<xsl:value-of select="count(preceding-sibling::fo:table-cell[not(@number-columns-spanned)]) + count(following-sibling::fo:table-cell[not(@number-columns-spanned)])"/>
</xsl:variable>
<xsl:variable name="number-spanned-columns-in-row" as="xs:integer">
<xsl:value-of select="sum(preceding-sibling::fo:table-cell[@number-columns-spanned ne 'remainder']/@number-columns-spanned) + sum(following-sibling::fo:table-cell[@number-columns-spanned ne 'remainder']/@number-columns-spanned)"/>
</xsl:variable>
<xsl:value-of select="$number-columns-in-table - $number-columns-in-row - $number-spanned-columns-in-row"/>
</xsl:attribute>
<xsl:apply-templates select="@*[not(local-name() = 'number-columns-spanned')]|node()"/>
</xsl:copy>
</xsl:template>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- number-columns-spanned: remainder -->
<xsl:template match="fo:table-cell[@number-columns-spanned = 'remainder']" mode="#all">
<xsl:copy>
<xsl:attribute name="number-columns-spanned">
<xsl:variable name="number-columns-in-table" as="xs:integer">
<xsl:value-of select="count(ancestor::fo:table[1]/fo:table-column)"/>
</xsl:variable>
<xsl:variable name="number-columns-in-row" as="xs:integer">
<xsl:value-of select="count(preceding-sibling::fo:table-cell[not(@number-columns-spanned)]) + count(following-sibling::fo:table-cell[not(@number-columns-spanned)])"/>
</xsl:variable>
<xsl:variable name="number-spanned-columns-in-row" as="xs:integer">
<xsl:value-of select="sum(preceding-sibling::fo:table-cell[@number-columns-spanned ne 'remainder']/@number-columns-spanned) + sum(following-sibling::fo:table-cell[@number-columns-spanned ne 'remainder']/@number-columns-spanned)"/>
</xsl:variable>
<xsl:value-of select="$number-columns-in-table - $number-columns-in-row - $number-spanned-columns-in-row"/>
</xsl:attribute>
<xsl:apply-templates select="@*[not(local-name() = 'number-columns-spanned')]|node()"/>
</xsl:copy>
</xsl:template>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I should've done it years ago. Note unfortunately it won't work if you've got other rows that are using number-rows-spanned. Improvements welcome!