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

XML条件过滤求助:XSL处理New/Removed重复行的逻辑修正

问题描述

需要对XML数据按以下规则过滤:当两行除Status外其他所有字段完全匹配时,若一行Status为"New"、另一行为"Removed",则这两行互相抵消并移除;若某类行(比如"New")的数量多于对应的"Removed"行,多余的行需要保留。

现有逻辑在处理多行重复数据时失效:示例中行1(New)和行2(Removed)可抵消,但行3(New)无匹配的Removed行,应保留;但当前基于Key匹配的XSL代码会把所有行都移除,请求解决思路。

XML示例

<root>
<row>
    <ID>11111</ID>
    <Start>01052024</Start>
    <End>31102024</End>
    <Type>BB</Type>
    <Status>New</Status>
</row>
<row>
    <ID>11111</ID>
    <Start>01052024</Start>
    <End>31102024</End>
    <Type>BB</Type>
    <Status>Removed</Status>
</row>
<row>
    <ID>11111</ID>
    <Start>01052024</Start>
    <End>31102024</End>
    <Type>BB</Type>
    <Status>New</Status>
</row>
</root>

当前XSL代码

<xsl:for-each select="row">
<xsl:variable name="concatKey" select="concat(ID, '', Start, '', End, '', Type)"/>
<xsl:if test="Status = 'Removed'">
    <xsl:variable name="rowMatch" select="key('groupedRows', $concatKey) [Status = 'New']"/>
    <xsl:if test="not($rowMatch)">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:if>
<xsl:if test="Status = 'New'">
    <xsl:variable name="rowMatch" select="key('groupedRows', $concatkey) [Status = 'Removed']"/>
    <xsl:if test="not($rowMatch)">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:if>
</xsl:for-each>
处理思路

核心问题是当前逻辑只检查是否存在匹配的对立状态行,而没有考虑数量抵消。解决需要按分组统计数量,再保留多余的行:

  • 按非Status字段分组:用xsl:key将所有行按ID+Start+End+Type分组,确保同组内的行只有Status不同。
  • 统计组内状态数量:对每个分组,分别统计New和Removed的行数。
  • 计算需保留的行数:
    • 如果New数量 > Removed数量:保留New行,数量为两者的差值
    • 如果Removed数量 > New数量:保留Removed行,数量为两者的差值
    • 数量相等则全部移除
  • 输出保留的行:遍历分组,按计算出的数量输出对应状态的行。

修正后的XSL代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="groupedRows" match="row" use="concat(ID, Start, End, Type)"/>

    <xsl:template match="/root">
        <root>
            <!-- 遍历每个唯一分组 -->
            <xsl:for-each select="row[generate-id() = generate-id(key('groupedRows', concat(ID, Start, End, Type))[1])]">
                <xsl:variable name="currentGroup" select="key('groupedRows', concat(ID, Start, End, Type))"/>
                <xsl:variable name="newCount" select="count($currentGroup[Status='New'])"/>
                <xsl:variable name="removedCount" select="count($currentGroup[Status='Removed'])"/>
                
                <!-- 保留多余的New行 -->
                <xsl:if test="$newCount > $removedCount">
                    <xsl:copy-of select="$currentGroup[Status='New'][position() &lt;= ($newCount - $removedCount)]"/>
                </xsl:if>
                
                <!-- 保留多余的Removed行 -->
                <xsl:if test="$removedCount > $newCount">
                    <xsl:copy-of select="$currentGroup[Status='Removed'][position() &lt;= ($removedCount - $newCount)]"/>
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>

代码说明

  • 使用generate-id()确保每个分组只处理一次,避免重复遍历。
  • 统计组内两种状态的数量,计算差值后输出对应数量的行,实现精确抵消。
  • 针对示例场景,分组内New数量为2,Removed数量为1,差值为1,因此保留1条New行,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:45:07