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

基于XSLT 1.0单模板按属性合并节点并求和的优化方案

XSLT 1.0 优化分组求和实现,减少循环次数

需求:在XSLT 1.0中使用单个模板,生成包含唯一role的结构,每个role节点的totalQty属性为对应所有bar节点qty属性的总和,且每个role下包含对应的bar子节点。

我当前实现的代码存在4次循环(2次for-each循环、1次sum中的循环、1次key中的循环),想知道有没有更优方式减少循环次数。

输入XML

<foo>
<bar  qty="1" unit="123">
<var  role="abc"/>
</bar>
<bar qty="1" unit="123">
<var  role="efg"/>
</bar>
<bar qty="2" unit="501">
<var  role="efg"/>
</bar>
<bar qty="1" unit="123">
<var  role="efg"/>
</bar>
<bar qty="1" unit="123">
<var  role="abc"/>
</bar>
<bar qty="1" unit="9085">
<var  role="abc"/>
</bar>
</foo>

期望输出XML

<foo>
<vars>
<var role="abc" totalQty="3">
<bar qty="1" unit="123" />
<bar qty="1" unit="123" />
<bar qty="1" unit="9085" />
</var>
<var role="efg" totalQty="4">
<bar qty="1" unit="123" />
<bar qty="2" unit="501" />
<bar qty="1" unit="123" />
</var>
</vars>
</foo>

现有XSLT 1.0代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:key name="uniquerole" match="//bar/var" use="@role"/>
    <xsl:template match="/">
        <foo>
            <vars>
                <xsl:for-each select="//bar/var[generate-id() = generate-id(key('uniquerole', @role))]">
                    <xsl:variable name="vRole">
                        <xsl:value-of select="@role"/>
                    </xsl:variable>
                    <xsl:variable name="tot_qty">
                        <xsl:value-of select="sum(//bar[var/@role=$vRole]/@qty)"/>
                    </xsl:variable>
                    <var>
                        <xsl:attribute name="role">
                            <xsl:value-of select="$vRole"/>
                        </xsl:attribute>
                        <xsl:attribute name="totalQty">
                            <xsl:value-of select="$tot_qty"/>
                        </xsl:attribute>
                        <xsl:for-each select="//bar[var/@role=$vRole]">
                            <bar>
                                <xsl:attribute name="qty">
                                    <xsl:value-of select="@qty"/>
                                </xsl:attribute>
                                <xsl:attribute name="unit">
                                    <xsl:value-of select="@unit"/>
                                </xsl:attribute>
                            </bar>
                        </xsl:for-each>
                    </var>
                </xsl:for-each>
            </vars>
        </foo>
    </xsl:template>
</xsl:stylesheet>

优化方案

核心思路是调整Muenchian分组的key定义,直接以bar节点为匹配对象,用var/@role作为键值,这样分组后可以直接复用同一role对应的所有bar节点集合,避免多次遍历整个文档查询:

  1. 重新定义key,直接匹配bar节点,键值为var/@role,一次建立索引后后续所有操作复用该索引
  2. 分组时选择每个role组的第一个bar节点作为分组标识
  3. 计算总和、生成子bar节点时,直接调用key获取对应集合,无需重复查询

优化后的XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <!-- 直接以bar为匹配对象,用var的role属性作为键 -->
    <xsl:key name="role-bar" match="bar" use="var/@role"/>

    <xsl:template match="/">
        <foo>
            <vars>
                <!-- 按role分组,选择每个组的第一个bar作为分组入口 -->
                <xsl:for-each select="foo/bar[generate-id() = generate-id(key('role-bar', var/@role)[1])]">
                    <xsl:variable name="current-role" select="var/@role"/>
                    <!-- 直接通过key获取当前role的所有bar节点集合 -->
                    <xsl:variable name="role-bars" select="key('role-bar', $current-role)"/>

                    <var role="{$current-role}" totalQty="{sum($role-bars/@qty)}">
                        <!-- 遍历复用已获取的bar集合,无需重新查询 -->
                        <xsl:for-each select="$role-bars">
                            <bar qty="{@qty}" unit="{@unit}"/>
                        </xsl:for-each>
                    </var>
                </xsl:for-each>
            </vars>
        </foo>
    </xsl:template>
</xsl:stylesheet>

优化说明

  • 循环次数大幅减少:key仅在初始化时遍历一次文档建立索引;分组遍历一次唯一组;每个组内的sum和子节点生成复用同一个role-bars集合,无需重复遍历文档查询
  • 使用属性值模板({})简化属性生成代码,更简洁高效
  • 避免了原代码中多次使用//bar的全局查询,减少不必要的节点遍历

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:09:24