Reputation: 23880
I'm getting this error:
Error reported by XML parser: The element type "fo:table-row" must be terminated by the matching end-tag "
</fo:table-row>
".
When trying to dynamically create fo:table-row
s.
This is my current XSLT code:
<xsl:template match="sec|ack">
<xsl:call-template name="subtitle">
<xsl:with-param name="text" select="title"/>
</xsl:call-template>
<fo:table width="100%">
<fo:table-column column-width="45%"/>
<fo:table-column column-width="45%"/>
<fo:table-body>
<xsl:for-each select="sec/*">
<xsl:variable name="i" select="position()" />
<xsl:if test="($i == 1)">
<fo:table-row>
</xsl:if>
<xsl:if test="($i mod 2) && $i > 1">
</fo:table-row>
<fo:table-row>
</xsl:if>
<fo:table-cell>
<fo:block><xsl:value-of select="*" /></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</fo:table-body>
</fo:table>
</xsl:template>
and this the XML I'm using (although I think it is my syntax not the actual XML that is the issue):
<sec>
<title>Section Title</title>
<sec>
<title>Paragraph 1 Title</title>
<p>Body paragraph</p>
</sec>
<sec>
<title>Paragraph 2 Title</title>
<list list-type="order">
<list-item>
<p>Step 1.</p>
</list-item>
<list-item>
<p>Step 2.</p>
</list-item>
<list-item>
<p>Step 3.</p>
</list-item>
<list-item>
<p>Step 4.</p>
</list-item>
<list-item>
<p>Step 5.</p>
</list-item>
<list-item>
<p>Step 6.</p>
</list-item>
<list-item>
<p>Step 7.</p>
</list-item>
<list-item>
<p>Step 8.</p>
</list-item>
<list-item>
<p>Step 9.</p>
</list-item>
<list-item>
<p>Step 10.</p>
</list-item>
<list-item>
<p>Step 11.</p>
</list-item>
<list-item>
<p>Step 12.</p>
</list-item>
<list-item>
<p>Step 13.</p>
</list-item>
<list-item>
<p>Step 14.</p>
</list-item>
</list>
</sec>
</sec>
I'm converting our historical code from a 1 column display to a 2 column display. If there is a better, non-table approach I'd be interested in that as well. I tried using float
s but wasn't able to get it to work. With this approach I can get a static 2 column display working.
This was my static approach:
<xsl:template match="sec|ack">
<xsl:call-template name="subtitle">
<xsl:with-param name="text" select="title"/>
</xsl:call-template>
<fo:table width="100%" >
<fo:table-column column-width="45%"/>
<fo:table-column column-width="45%"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block><xsl:apply-templates select="*[name()!='title']|text()" mode="xhtml"/></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>This is the second content block.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</xsl:template>
Upvotes: 0
Views: 455
Reputation: 167716
As you indicate you use XSLT 2 you can use positional grouping with for-each-group group-adjacent="(position() - 1) idiv 2"
to group every two selected adjacent nodes into a table-row so instead of the <xsl:for-each select="sec/*">
you use
<xsl:for-each-group select="*" group-adjacent="(position() - 1) idiv 2">
<fo:table-row>
<xsl:apply-templates select="current-group()" mode="cell"/>
</fo:table-row>
</xsl:for-each-group>
and then write a template transforming any element into a cell in that named mode:
<xsl:template match="*" mode="cell">
<fo:table-cell>
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:table-cell>
</xsl:template>
Upvotes: 2