XSLT 3.0中xsl:number在footnoteRef失效的表格脚注编号问题
问题解决:XSLT 3.0生成带脚注的表格时footnoteRef编号不显示
问题背景
使用XSLT 3.0结合XSL-FO生成带脚注的表格,要求:
- 表格行的Remarks列显示对应脚注编号
- 表尾显示脚注编号及内容
XML输入
<reqSpares> <spareDescrGroup> <spareDescr> <name>Bulb</name> <footnoteRemarks> <footnoteRef internalRefId="ftn-0001"/> <footnoteRef internalRefId="ftn-0002"/> </footnoteRemarks> </spareDescr> <spareDescr> <embeddedSpareDescr> <name>small bulb</name> <footnoteRemarks> <footnoteRef internalRefId="ftn-0002"/> </footnoteRemarks> </embeddedSpareDescr> </spareDescr> <footnote id="ftn-0001"> <para>Make sure the bulb works.</para> </footnote> <footnote id="ftn-0002"> <para>Make sure that the new bulb is not cracked.</para> </footnote> </spareDescrGroup> </reqSpares>
预期输出
| Name | Remarks |
|---|---|
| Bulb | 1 2 |
| small bulb | 2 |
| 1 Make sure the bulb works. | |
| 2 Make sure that the new bulb is not cracked. |
实际问题
表尾脚注编号显示正常,但<footnoteRef>中的xsl:number未生效,Remarks列为空:
| Name | Remarks |
|---|---|
| Bulb | |
| small bulb | |
| 1 Make sure the bulb works. | |
| 2 Make sure that the new bulb is not cracked. |
在<footnote>节点中使用<xsl:number count="footnote" from="reqSpares"/>可正常生成编号,但在<footnoteRef>节点中使用相同代码无效。
现有XSLT代码
<xsl:param name="footnote-count-pattern" static="yes" as="xs:string" select="'reqSpares/descendant::footnote'"/> <xsl:template match="footnoteRemarks"> <xsl:apply-templates/> </xsl:template> <xsl:template match="footnote"> <fo:block font-size="75%"> <xsl:number _count="{$footnote-count-pattern}" level="any"/> <xsl:apply-templates/> </fo:block> </xsl:template> <xsl:template match="footnoteRef"> <!-- only need footnote number here --> <fo:inline baseline-shift="super" font-size="75%"> <xsl:number _count="{$footnote-count-pattern}" level="any"/> <xsl:text> </xsl:text> </fo:inline> </xsl:template> <xsl:template match="reqSpares"> <fo:table> <fo:table-column/> <fo:table-column/> <fo:table-header> <fo:table-row> <fo:table-cell> <fo:block>Name</fo:block> </fo:table-cell> <fo:table-cell> <fo:block>Remarks</fo:block> </fo:table-cell> </fo:table-row> </fo:table-header> <fo:table-footer> <fo:table-row> <fo:table-cell number-columns-spanned="2"> <fo:block> <xsl:apply-templates select="descendant::footnote"/> </fo:block> </fo:table-cell> </fo:table-row> </fo:table-footer> <fo:table-body> <xsl:apply-templates/> </fo:table-body> </fo:table> </xsl:template> <xsl:template match="spareDescr"> <fo:table-row> <fo:table-cell> <fo:block> <xsl:apply-templates select="name"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:apply-templates select="footnoteRemarks"/> </fo:block> </fo:table-cell> </fo:table-row> </xsl:template>
问题原因
xsl:number默认对当前节点进行编号:在<footnote>模板中,当前节点是<footnote>,count="footnote"能匹配所有从reqSpares开始的<footnote>节点,因此生成编号正常;但在<footnoteRef>模板中,当前节点是<footnoteRef>,count="footnote"无法匹配任何节点,导致输出为空。- 代码中
_count是无效属性,正确的属性名应为count。
解决方案
- 定义键关联
footnoteRef的internalRefId和对应<footnote>的id,快速查找目标脚注节点。 - 在
<footnoteRef>模板中,通过键找到对应<footnote>节点,再对该节点应用xsl:number。 - 修正
_count为标准的count属性。
修改后的完整XSLT代码
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:param name="footnote-count-pattern" static="yes" as="xs:string" select="'footnote'"/> <!-- 定义键关联footnote的id和节点 --> <xsl:key name="footnote-key" match="footnote" use="@id"/> <xsl:template match="footnoteRemarks"> <xsl:apply-templates/> </xsl:template> <xsl:template match="footnote"> <fo:block font-size="75%"> <!-- 修正_count为count,指定from确保计数范围 --> <xsl:number count="{$footnote-count-pattern}" from="reqSpares" level="any"/> <xsl:text> </xsl:text> <xsl:apply-templates/> </fo:block> </xsl:template> <xsl:template match="footnoteRef"> <!-- only need footnote number here --> <fo:inline baseline-shift="super" font-size="75%"> <!-- 通过键找到对应的footnote节点 --> <xsl:variable name="target-footnote" select="key('footnote-key', @internalRefId)"/> <!-- 对目标footnote节点应用编号 --> <xsl:number select="$target-footnote" count="{$footnote-count-pattern}" from="reqSpares"/> <xsl:text> </xsl:text> </fo:inline> </xsl:template> <xsl:template match="reqSpares"> <fo:table> <fo:table-column/> <fo:table-column/> <fo:table-header> <fo:table-row> <fo:table-cell> <fo:block>Name</fo:block> </fo:table-cell> <fo:table-cell> <fo:block>Remarks</fo:block> </fo:table-cell> </fo:table-row> </fo:table-header> <fo:table-footer> <fo:table-row> <fo:table-cell number-columns-spanned="2"> <fo:block> <xsl:apply-templates select="descendant::footnote"/> </fo:block> </fo:table-cell> </fo:table-row> </fo:table-footer> <fo:table-body> <xsl:apply-templates/> </fo:table-body> </fo:table> </xsl:template> <xsl:template match="spareDescr"> <fo:table-row> <fo:table-cell> <fo:block> <xsl:apply-templates select="name | embeddedSpareDescr/name"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:apply-templates select="footnoteRemarks | embeddedSpareDescr/footnoteRemarks"/> </fo:block> </fo:table-cell> </fo:table-row> </xsl:template> </xsl:stylesheet>
额外说明
- 补充了
embeddedSpareDescr的内容处理,确保small bulb的名称和脚注引用能被正确渲染。 - 使用
xsl:key能高效查找对应脚注节点,避免重复遍历XML树。
内容的提问来源于stack exchange,提问作者Caroline
相关产品推荐
相关产品推荐

