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

如何在XSLT中将重复记录合并为单条记录?

XSLT子节点去重实现方案

需求说明

  • 处理包含2条父记录的XML,每个父记录下有多层子节点
  • 需按最内层Field元素的文本值去重,同一父记录下重复值仅保留一条,唯一值正常保留

输入XML

<Records count="2">
    <Record id="parentRecord">
      <Record id="childRecord1">
        <Record id="childRecord2">
          <Field id="childRecord2Field">Technology Asset Management</Field>
        </Record>
      </Record>
      <Record id="childRecord1">
        <Record id="childRecord2">
          <Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
        </Record>
      </Record>
      <Record id="childRecord1">
        <Record id="childRecord2">
          <Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
        </Record>
      </Record>
    </Record>
    <Record id="parentRecord">
        <Record id="childRecord1">
          <Record id="childRecord2">
            <Field id="childRecord2Field">Technology Asset Management</Field>
          </Record>
        </Record>
        <Record id="childRecord1">
          <Record id="childRecord2">
            <Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
          </Record>
        </Record>
        <Record id="childRecord1">
            <Record id="childRecord2">
              <Field id="childRecord2Field">Technology Asset Management</Field>
            </Record>
          </Record>
      </Record>
</Records>

期望输出XML

<Records>
    <Record id="parentRecord">
      <Record id="childRecord1">
        <Record id="childRecord2">
          <Field id="childRecord2Field">Technology Asset Management</Field>
        </Record>
      </Record>
      <Record id="childRecord1">
        <Record id="childRecord2">
          <Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
        </Record>
      </Record>
    </Record>
    <Record id="parentRecord">
        <Record id="childRecord1">
          <Record id="childRecord2">
            <Field id="childRecord2Field">Technology Asset Management</Field>
          </Record>
        </Record>
        <Record id="childRecord1">
          <Record id="childRecord2">
            <Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
          </Record>
        </Record>
</Records>

尝试的XSLT代码

<xsl:template match="Records">
    
    <Records>
      <xsl:for-each select="Record[id='parentRecord']">
       <xsl:variable name="MatchedChildRecord2Value" select="Record/Record/Field[id='childRecord2Field']">  //I am trying to store all the field values in paraent node
            <xsl:for-each select="Record/Record/Field[id=childRecord2']/">
                <xsl:choose>
                    <xsl:when test=".=$MatchedChildRecord2Value">
                        //Nothing I am doing
                    </xsl:when>
                    <xsl:otherwise>
                    <Record>
                        <Record id="childRecord1">
                        <Record id="childRecord2">
                            <Field>FieldRecordvalue</Field>
                        </Record>
                    </Record>     
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
      </xsl:for-each>
    </Records>
  </xsl:template>

正确实现方案

使用Muenchian分组是XSLT中高效去重的标准方法,核心思路是按每个父记录下Field的文本值分组,仅保留每组的第一个节点,同时完整保留原XML结构。

完整XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 定义分组键:按父记录下Field的文本值分组 -->
    <xsl:key name="field-by-value" match="Record[@id='parentRecord']/Record[@id='childRecord1']" use="Record/Field/text()"/>

    <!-- 复制所有节点的默认模板 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 处理Records节点,移除原count属性 -->
    <xsl:template match="Records">
        <Records>
            <xsl:apply-templates select="@*|node()"/>
        </Records>
    </xsl:template>

    <!-- 处理父记录下的子节点,仅保留每组的第一个节点 -->
    <xsl:template match="Record[@id='parentRecord']/Record[@id='childRecord1']">
        <xsl:if test="generate-id() = generate-id(key('field-by-value', Record/Field/text())[1])">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

代码说明

  1. 分组键定义:<xsl:key>定义了以Field文本值为键的分组,范围限定在每个父记录下的childRecord1节点
  2. 默认复制模板:保留XML的原有结构和属性,仅对需要修改的节点做特殊处理
  3. Records节点处理:移除原有的count属性,生成干净的根节点
  4. 去重逻辑:通过generate-id()判断当前节点是否是分组中的第一个节点,仅保留第一个节点,实现去重

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:45:42