I'm generating PDF from Lotus Notes XML using FOP and XSL-FO. When all the cells in a row are merged in the Notes document, it becomes <tablerow/>
in the XML (without <tablecell>
child). For example :
<table widthtype='fixedleft' refwidth='12.5083in'>
<tablecolumn width='4.1694in'/>
<tablecolumn width='4.1694in'/>
<tablecolumn width='4.1694in'/>
<tablerow>
<tablecell rowspan='4'>...</tablecell>
<tablecell>...</tablecell>
<tablecell>...</tablecell>
</tablerow>
<tablerow>
<tablecell>...</tablecell>
<tablecell>...</tablecell>
</tablerow>
<tablerow>
<tablecell rowspan='2'>...</tablecell>
<tablecell rowspan='2'>...</tablecell>
</tablerow>
<tablerow/>
</table>
I'm looking for a workaround in xsl-fo to delete the empty rows and adjust the rowspan. Otherwise I have an error in FOP :
fo:table-row is missing child elements. Required content model: <table-cell+>
Here is the result I want :
<table widthtype='fixedleft' refwidth='12.5083in'>
<tablecolumn width='4.1694in'/>
<tablecolumn width='4.1694in'/>
<tablecolumn width='4.1694in'/>
<tablerow>
<tablecell rowspan='3'>...</tablecell>
<tablecell>...</tablecell>
<tablecell>...</tablecell>
</tablerow>
<tablerow>
<tablecell>...</tablecell>
<tablecell>...</tablecell>
</tablerow>
<tablerow>
<tablecell rowspan='1'>...</tablecell>
<tablecell rowspan='1'>...</tablecell>
</tablerow>
</table>
And here my xsl :
<xsl:template match="dxl:table">
<fo:table width="100%" table-layout="fixed">
<xsl:for-each select="dxl:tablecolumn">
<fo:table-column column-width="@width"/>
</xsl:for-each>
<fo:table-body>
<xsl:apply-templates />
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="dxl:tablerow">
<fo:table-row>
<xsl:apply-templates/>
</fo:table-row>
</xsl:template>
<xsl:template match="dxl:tablecell">
<xsl:variable name="rows">
<xsl:choose>
<xsl:when test="@rowspan">
<xsl:value-of select="@rowspan"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<fo:table-cell number-rows-spanned="{$rows}">
<xsl:apply-templates/>
</fo:table-cell>
</xsl:template>
Thanks in advance!
What you could do is create a second variable that counts all the "blank" rows following the row containing the current table cell
<xsl:variable
name="blankrows"
select="count(../following-sibling::dxl:tablerow[position() < number($rows)]
[not(dxl:tablecell)])" />
You can then adjust the $rows variable by this amount to generate the number-rows-spanned
attribute.
Try this XSLT (with made-up namespaces...)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:dxl="dxl" xmlns:fo="fo">
<xsl:output method="xml" indent="yes" />
<xsl:template match="dxl:table">
<fo:table width="100%" table-layout="fixed">
<xsl:for-each select="dxl:tablecolumn">
<fo:table-column column-width="@width"/>
</xsl:for-each>
<fo:table-body>
<xsl:apply-templates />
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="dxl:tablerow[not(dxl:tablecell)]" />
<xsl:template match="dxl:tablerow">
<fo:table-row>
<xsl:apply-templates/>
</fo:table-row>
</xsl:template>
<xsl:template match="dxl:tablecell">
<xsl:variable name="rows">
<xsl:choose>
<xsl:when test="@rowspan">
<xsl:value-of select="@rowspan"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="blankrows" select="count(../following-sibling::dxl:tablerow[position() < number($rows)][not(dxl:tablecell)])" />
<fo:table-cell>
<xsl:if test="$rows - 1 > $blankrows">
<xsl:attribute name="number-rows-spanned">
<xsl:value-of select="$rows - $blankrows" />
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</fo:table-cell>
</xsl:template>
</xsl:stylesheet>
I've made the attribute conditional, so it doesn't bother showing it if it is set to 1.
Also note the use of the empty template <xsl:template match="dxl:tablerow[not(dxl:tablecell)]" />
to remove the empty rows themselves.