You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT1.0实现三层级分组输出PDF的技术问题求解

问题原因

现有代码核心错误集中在分组规则和节点选择逻辑上:

  • 三个层级的分组键全部匹配Products节点,没有对应到Instruments和Bill层级的节点
  • 分组键拼接未添加分隔符,可能出现不同命名拼接后重复的问题
  • 内层循环全局遍历/root/Products,没有限定在当前父分组范围内,导致取值和分组混乱

修正后的完整代码

<!-- 三级分组键定义,新增|作为分隔符避免命名冲突 -->
<xsl:key name="groupProducts" match="/root/Products" use="@name"/>
<xsl:key name="groupInstruments" match="Instruments" use="concat(parent::Products/@name, '|', @name)"/>
<xsl:key name="groupBilling" match="Bill" use="concat(ancestor::Products/@name, '|', parent::Instruments/@name, '|', @name)"/>

<xsl:template name="testing">
    <fo:block>
        <fo:table>
            <fo:table-column column-width="proportional-column-width(1)"/>
            <fo:table-body>
                <!-- 第一级:按Products分组 -->
                <xsl:for-each select="/root/Products[generate-id(.) = generate-id(key('groupProducts',@name)[1])]">
                    <xsl:variable name="currentProductName" select="@name"/>
                    <fo:table-row>
                        <fo:table-cell>
                            <fo:block font-weight="bold" margin-top="4pt">
                                <xsl:value-of select="@name"/>
                            </fo:block>
                            <fo:block margin-left="10pt">
                                <fo:table>
                                    <fo:table-column column-width="proportional-column-width(1)"/>
                                    <fo:table-body>
                                        <!-- 第二级:当前产品下按Instruments分组 -->
                                        <xsl:for-each select="key('groupProducts', $currentProductName)/Instruments[generate-id(.) = generate-id(key('groupInstruments', concat($currentProductName, '|', @name))[1])]">
                                            <xsl:variable name="currentInstrumentName" select="@name"/>
                                            <fo:table-row>
                                                <fo:table-cell>
                                                    <fo:block color="blue" margin-top="2pt">
                                                        Instruments: <xsl:value-of select="@name"/>
                                                    </fo:block>
                                                    <fo:block margin-left="10pt">
                                                        <fo:table>
                                                            <fo:table-column column-width="proportional-column-width(1)"/>
                                                            <fo:table-body>
                                                                <!-- 第三级:当前仪器下按Bill分组 -->
                                                                <xsl:for-each select="key('groupInstruments', concat($currentProductName, '|', $currentInstrumentName))/Bill[generate-id(.) = generate-id(key('groupBilling', concat($currentProductName, '|', $currentInstrumentName, '|', @name))[1])]">
                                                                    <fo:table-row>
                                                                        <fo:table-cell>
                                                                            <fo:block color="green" margin-top="2pt">
                                                                                Billing: <xsl:value-of select="@name"/>
                                                                            </fo:block>
                                                                        </fo:table-cell>
                                                                    </fo:table-row>
                                                                </xsl:for-each>
                                                            </fo:table-body>
                                                        </fo:table>
                                                    </fo:block>
                                                </fo:table-cell>
                                            </fo:table-row>
                                        </xsl:for-each>
                                    </fo:table-body>
                                </fo:table>
                            </fo:block>
                        </fo:table-cell>
                    </fo:table-row>
                </xsl:for-each>
            </fo:table-body>
        </fo:table>
    </fo:block>
</xsl:template>

核心修改说明

  • 重新定义三级分组键,分别匹配对应层级的节点,拼接时加入|作为唯一分隔符,避免不同层级命名重复导致分组错误
  • 内层循环限定在当前父分组的子节点范围内,不再全局遍历根节点,避免范围错误
  • 新增变量存储上层分组标识,避免current()嵌套时上下文混乱
  • 节点取值使用相对路径,避免根路径匹配错误

内容的提问来源于stack exchange,提问作者iwasaki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:54:03