如何用 XSLT 2.0 正确转换 InDesign 合并单元格表格?
数据小陈
结论
现有算法无法正确计算单元格所在的行。aid:crows 表示单元格跨越的行数,并不表示后续单元格需要整体向后移动的行数。只统计前面带有 aid:crows 的单元格,会把跨 2 行和跨 3 行的情况都算作移动一次,也无法处理 aid:ccols 占用的列。
这个 XML 将所有 Cell 平铺排列,没有明确的行边界。要生成正确的表格,需要先按照表格网格规则确定每个单元格的行列位置,并跳过被 rowspan、colspan 占用的格子。可以先生成行结构,再用 XSLT 输出 XHTML;也可以在 XSLT 中完成整个网格布局过程。只调整当前的 start-row 表达式无法解决这个问题。
推荐做法:先明确每行的单元格
如果可以在源 XML 中增加行包装元素,渲染时就能直接用 XSLT 2.0 处理。例如,将表格规范化为 <Row> 和 <Cell>,同时保留原有的 aid:crows、aid:ccols 属性:
<table xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/"
xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/">
<Row>
<Cell aid5:cellstyle="TCH-l"><p>Fruit Part</p></Cell>
<Cell aid5:cellstyle="TCH-l" aid:ccols="2"><p>Variety/Color</p></Cell>
<Cell aid5:cellstyle="TCH-l"><p>Reference</p></Cell>
</Row>
<Row>
<Cell aid5:cellstyle="TB-f" aid:crows="3"><p><B>Peel</B></p></Cell>
<Cell aid5:cellstyle="TB-f" aid:crows="3"><p>Orange</p></Cell>
<Cell aid5:cellstyle="TB-f"><p>A1</p></Cell>
<Cell aid5:cellstyle="TB-f" aid:crows="3"><p>A2</p></Cell>
</Row>
<!-- 后续 Row 按网格布局继续列出 -->
</table>
对应的输出模板如下。它要求输入中已经包含正确的 Row 边界。对于没有行元素的原始平铺结构,需要先完成布局计算或规范化。
<xsl:template match="table">
<table border="1">
<tbody>
<xsl:apply-templates select="Row"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="Row">
<tr>
<xsl:apply-templates select="Cell"/>
</tr>
</xsl:template>
<xsl:template match="Cell">
<td>
<xsl:if test="@aid5:cellstyle">
<xsl:attribute name="class" select="@aid5:cellstyle"/>
</xsl:if>
<xsl:if test="@aid:ccols">
<xsl:attribute name="colspan" select="@aid:ccols"/>
</xsl:if>
<xsl:if test="@aid:crows">
<xsl:attribute name="rowspan" select="@aid:crows"/>
</xsl:if>
<p>
<xsl:apply-templates select="p/node()"/>
</p>
</td>
</xsl:template>
<xsl:template match="B">
<strong>
<xsl:apply-templates/>
</strong>
</xsl:template>
如果必须直接处理当前的平铺 XML,就需要逐格推进布局:从当前行下一个可用的列开始放置单元格,读取 aid:ccols 和 aid:crows,标记单元格覆盖的网格位置。遇到已被前面单元格占用的位置时跳过;如果当前行放不下,就转到下一行。行结构确定后,再应用上面的输出模板。
注意事项
- 输出 XHTML 时,根元素应位于
http://www.w3.org/1999/xhtml命名空间中。若源 XML 中的table、Cell、B没有默认命名空间,匹配时继续使用无前缀名称。 aid:crows和aid:ccols是 Adobe 命名空间中的属性,测试时应使用已声明的aid前缀;aid5:cellstyle属于aid5命名空间。aid:trows、aid:tcols可用于检查布局是否超出声明的表格大小,但不能据此确定平铺单元格分别属于哪一行。- 示例目标表格中,第一行的
Variety/Color占两列;后续行也需要跳过被跨行单元格占用的位置。生成器应检查每行最终的网格宽度是否为 4 列。
备注:内容仅供参考。
