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

XSLT分组需求:按type和pin字段合并或拆分file节点

问题描述

需求规则:

  • 当<file>节点的type和pin字段值均存在且相同时,将这些<file>合并到同一个<cat>节点下
  • 若type存在但pin值为空,则每个<file>节点单独生成一个<cat>节点

给定输入XML如下:

<?xml version='1.0' encoding='UTF-8'?>
    <record>
        <file>
            <type>DI</type>
            <pin>123</pin>
        </file>
        <file>
            <type>DI</type>
            <pin>123</pin>
        </file>
        <file>
            <type>DI</type>
            <pin>456</pin>
        </file>
        <file>
            <type>DI</type>
            <pin></pin>
        </file>
        <file>
            <type>DI</type>
            <pin></pin>
        </file>
        <file>
            <type>DM</type>
            <pin>123</pin>
        </file>
        <file>
            <type>DM</type>
            <pin>123</pin>
        </file>
        <file>
            <type>DM</type>
            <pin>456</pin>
        </file>
        <file>
            <type>DM</type>
            <pin></pin>
        </file>
        <file>
            <type>DM</type>
            <pin></pin>
        </file>
        <file>
            <type>CM</type>
            <pin>123</pin>
        </file>
        <file>
            <type>CM</type>
            <pin>123</pin>
        </file>
        <file>
            <type>CM</type>
            <pin>456</pin>
        </file>
        <file>
            <type>CM</type>
            <pin></pin>
        </file>
             <file>
            <type>CM</type>
            <pin></pin>
        </file>
    </record>

预期输出XML:

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <record>
        <cat>
            <file>
                <type>DI</type>
                <pin>123</pin>
            </file>
            <file>
                <type>DI</type>
                <pin>123</pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DM</type>
                <pin>123</pin>
            </file>
            <file>
                <type>DM</type>
                <pin>123</pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>CM</type>
                <pin>123</pin>
            </file>
            <file>
                <type>CM</type>
                <pin>123</pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DI</type>
                <pin>456</pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DM</type>
                <pin>456</pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>CM</type>
                <pin>456</pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DI</type>
                <pin></pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DI</type>
                <pin></pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DM</type>
                <pin></pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>DM</type>
                <pin></pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>CM</type>
                <pin></pin>
            </file>
        </cat>
        <cat>
            <file>
                <type>CM</type>
                <pin></pin>
            </file>
        </cat>
    </record>
</root>

现有失效XSLT代码:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/record">
    <root><xsl:for-each-group select="record" group-by="type">
            <xsl:choose>
            <xsl:for-each-group select="record" group-by="pin">
                <xsl:when test="current-grouping-key()">
                    <cat>
                        <xsl:copy-of select="current-group()"/>
                    </cat>
                </xsl:when></xsl:for-each-group>
                <xsl:otherwise>
                        <cat>
                            <xsl:copy-of select="."/>
                        </cat>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group></root>
</xsl:template>
</xsl:stylesheet>  
修正后的XSLT代码
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
    <root>
        <record>
            <!-- 处理pin非空的file节点,按type+pin组合值分组 -->
            <xsl:for-each-group select="record/file[string(pin)]" group-by="concat(type, '|', pin)">
                <cat>
                    <xsl:copy-of select="current-group()"/>
                </cat>
            </xsl:for-each-group>
            <!-- 处理pin为空的file节点,每个节点单独生成cat -->
            <xsl:for-each select="record/file[not(string(pin))]">
                <cat>
                    <xsl:copy-of select="."/>
                </cat>
            </xsl:for-each>
        </record>
    </root>
</xsl:template>
</xsl:stylesheet>
代码说明

原代码的核心问题:

  1. 模板匹配错误:原模板匹配/record,但文档根节点是/,无法完整处理整个文档
  2. 分组对象错误:原代码尝试对record节点分组,实际需要分组的是record下的file节点
  3. 分组逻辑混乱:嵌套分组逻辑错误,未正确将type和pin组合作为分组键,也未区分pin为空的场景

修正后的逻辑:

  • 匹配文档根节点,构建输出的root和record结构
  • 第一部分:筛选pin非空的file节点,用concat(type, '|', pin)作为分组键,确保相同type和pin的节点归为一组,每组生成一个<cat>节点并复制组内所有file
  • 第二部分:筛选pin为空的file节点,逐个遍历并为每个节点单独生成<cat>节点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 07:15:33