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

XSLT 1.0按产品、账单分组生成重复表格时子上下文取值失效问题

XSLT 多分组遍历问题解决

问题背景

所用XML结构

<root>
    <Products name="product01">
        <Instruments name="ins01"/>
        <Instruments name="ins02"/>
        <Instruments name="ins01"/>
    </Products>
    <Products name="product02">
        <Instruments name="random text A">
            <Bill name="A"/>
        </Instruments>
        <Instruments name="random text B and C">
            <Bill name="B">
                <Notes>some text</Notes>
            </Bill>
            <Bill name="C">
                <Notes>some text</Notes>
            </Bill>
        </Instruments>
        <Instruments name="random text A and B">
            <Bill name="A">
                <Notes>some text</Notes>
            </Bill>
            <Bill name="B">
                <Notes>some text</Notes>
            </Bill>
        </Instruments>
        <Instruments name="random text B">
            <Bill name="B">
                <Notes>some text</Notes>
            </Bill>
        </Instruments>
        <Instruments name="random text C">
            <Bill name="C">
                <Notes>some text</Notes>
            </Bill>
        </Instruments>
        <Instruments name="random text C and A">
            <Bill name="C">
                <Notes>some text</Notes>
            </Bill>
            <Bill name="A">
                <Notes>some text</Notes>
            </Bill>
        </Instruments>
    </Products>
</root>

需求

先按Products节点分组,再在组内按Bill的name属性分组,表格左列展示账单类型,右列展示该账单类型对应分组下所有关联的Instruments名称,预期输出示例:

product02
Bill Type: A        random text A
                    random text A and B
                    random text C and A
Bill Type: B        random text B and C
                    random text A and B
                    random text B
Bill Type: C        random text B and C
                    random text C
                    random text C and A

原有模板问题

原有模板中定义的分组key是正确的,但右列遍历逻辑错误,无法取出对应账单类型下的所有Instruments名称。

修正方案

你定义的groupBilling已经实现了「产品名+账单名」的组合分组,在遍历到每个唯一账单分组节点时,直接用key函数取出同组所有Bill节点,再取其父节点Instruments的name属性即可。
只需将原有右表列的遍历逻辑:

<xsl:for-each select="../.">
    <fo:table-row>
        <fo:table-cell>
            <fo:block>
                <xsl:value-of select="@name" />
            </fo:block>
        </fo:table-cell>
    </fo:table-row>
</xsl:for-each>

替换为:

<xsl:for-each select="key('groupBilling', concat(../../@name, @name))">
    <fo:table-row>
        <fo:table-cell>
            <fo:block>
                <xsl:value-of select="../@name" />
            </fo:block>
        </fo:table-cell>
    </fo:table-row>
</xsl:for-each>

完整修正后模板代码

<xsl:key name="groupProducts" match="/root/Products/Instruments/Bill" use="../../@name" />
<xsl:key name="groupBilling" match="/root/Products/Instruments/Bill" use="concat(../../@name,@name)" />
<xsl:template name="myTemplate">
    <fo:block>
        <fo:table>
            <fo:table-column column-width="proportional-column-width(1)" />
            <fo:table-body>
                <xsl:for-each select="/root/Products/Instruments/Bill[generate-id(.) = generate-id(key('groupProducts',../../@name)[1])]">
                    <fo:table-row>
                        <fo:table-cell>
                            <fo:block font-weight="bold" margin-top="4pt">
                                <xsl:value-of select="../../@name" />
                            </fo:block>
                            <fo:block>
                                <fo:table>
                                    <fo:table-column column-width="50.000" column-number="1" />
                                    <fo:table-column column-width="50.000" column-number="2" />
                                    <fo:table-body>
                                        <xsl:for-each select="/root/Products/Instruments/Bill[generate-id(.) = generate-id(key('groupBilling',concat(current()/../../@name,@name))[1])]">
                                            <fo:table-row>
                                                <fo:table-cell>
                                                    <fo:block color="blue">
                                                                    Bill Type: <xsl:value-of select="@name" /></fo:block>
                                                    <fo:block />
                                                </fo:table-cell>
                                                <fo:table-cell>
                                                    <fo:block>
                                                        <fo:table>
                                                            <fo:table-column column-width="proportional-column-width(1)" />
                                                            <fo:table-body>
                                                                <!-- 修正后的遍历逻辑 -->
                                                                <xsl:for-each select="key('groupBilling', concat(../../@name, @name))">
                                                                    <fo:table-row>
                                                                        <fo:table-cell>
                                                                            <fo:block>
                                                                                <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>

内容的提问来源于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 07:27:05