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

如何使用XSLT 1.0移除索引匹配的重复TypeCode节点

问题:移除XSLT转换中索引匹配的重复节点块

尝试多种方法去除重复节点值但未达预期,需要移除索引匹配的重复TypeCode节点块。

输入XML

<before>              
      <class>
         <type>352</type>
         <agent>19133</agent>
         <ins-co>60122</ins-co>        
      </class>
      <class>
         <type>351</type>
         <agent>19355</agent>
         <ins-co>60122</ins-co>        
      </class>     
    </area>
</before>
<after>         
      <class>
         <type>355</type>
         <agent>19355</agent>
         <ins-co>60122</ins-co>                                 
      </class>      
      <class>
         <type>352</type>
         <agent>19133</agent>
         <ins-co>60122</ins-co>                                 
      </class>                                                            
</after>

使用的XSLT转换代码

<xsl:template match="/">
    <MaintenanceMessage>            
        <BeforeImage>
            <MaintenanceList>
                <xsl:apply-templates select="//beforechange/area/stud-class-buckets">
                    <xsl:with-param name="placement">before</xsl:with-param>
                </xsl:apply-templates>
            </MaintenanceList>              
        </BeforeImage>
        <AfterImage>
            <MaintenanceList>
                <xsl:apply-templates select="//beforechange/area/stud-class-buckets">
                    <xsl:with-param name="placement">after</xsl:with-param>
                </xsl:apply-templates>
            </MaintenanceList>              
        </AfterImage>
    </MaintenanceMessage>
</xsl:template>
<xsl:template match="//before/class">        
        <xsl:param name="placement"/>
        <xsl:variable name="index" select="position()"/>        
        <xsl:if test="//before/class[$index] != //after/class[$index]">         
            <Maintenance>               
                <xsl:attribute name="index"><xsl:value-of select="$index"/></xsl:attribute>             
                <xsl:variable name="TypeCode">
                    <xsl:call-template name="FieldValue">
                        <xsl:with-param name="value" select="dyn:evaluate(concat('//MESSAGE/', $placement , '/class[$index]/type'))"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test="$TypeCode = 'null'">
                        <egm:TypeCode xsi:nil="true"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <egm:TypeCode>
                            <xsl:value-of select="$TypeCode"/>
                        </egm:TypeCode>
                    </xsl:otherwise>
                </xsl:choose>               
                <xsl:variable name="AgentCode">
                    <xsl:call-template name="FieldValue">
                        <xsl:with-param name="value" select="dyn:evaluate(concat('//MESSAGE/', $placement , '/class[$index]/agent'))"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test="$AgentCode = 'null'">
                        <egm:AgentCode xsi:nil="true"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <egm:AgentCode>
                            <xsl:value-of select="$AgentCode"/>
                        </egm:AgentCode>
                    </xsl:otherwise>
                </xsl:choose>               
                <xsl:variable name="InsCoCode">
                    <xsl:call-template name="FieldValue">
                        <xsl:with-param name="value" select="dyn:evaluate(concat('//MESSAGE/', $placement , '/class[$index]/ins-co'))"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test="$InsCoCode = 'null'">
                        <egm:InsCoCode xsi:nil="true"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <egm:InsCoCode>
                            <xsl:value-of select="$InsCoCode"/>
                        </egm:InsCoCode>
                    </xsl:otherwise>
                </xsl:choose>
        </Maintenance>      
    </xsl:if>   
</xsl:template>

当前输出结果

<MaintenanceMessage>
    <BeforeImage>
        <MaintenanceList>
            <Maintenance index="3">
                <TypeCode>352</TypeCode>
                <AgentCode>19133</AgentCode>
                <InsCoCode>60122</InsCoCode>                
            </Maintenance>
            <Maintenance index="4">
                <TypeCode>351</TypeCode>
                <AgentCode>19355</AgentCode>
                <InsCoCode>60122</InsCoCode>                
            </Maintenance>
...            
        </MaintenanceList>
    </BeforeImage>
    <AfterImage>
        <MaintenanceList>
            <Maintenance index="3">
                <TypeCode>355</TypeCode>
                <AgentCode>19355</AgentCode>
                <InsCoCode>60122</InsCoCode>                
            </Maintenance>
            <Maintenance index="4">
                <TypeCode>352</TypeCode>
                <AgentCode>19133</AgentCode>
                <InsCoCode>60122</InsCoCode>                
            </Maintenance>
...            
        </MaintenanceList>
    </AfterImage>
</MaintenanceMessage>

期望输出结果

<MaintenanceMessage>
    <BeforeImage>
        <MaintenanceList>
            <Maintenance index="3">
                <TypeCode>351</TypeCode>
                <AgentCode>19355</AgentCode>
                <InsCoCode>60122</InsCoCode>               
            </Maintenance>            
...            
        </MaintenanceList>
    </BeforeImage>
    <AfterImage>
        <MaintenanceList>
            <HazardMaintenance index="3">
                <TypeCode>355</TypeCode>
                <AgentCode>19355</AgentCode>
                <InsCoCode>60122</InsCoCode>   
...            
        </MaintenanceList>
    </AfterImage>
</MaintenanceMessage>

解决方案

当前代码存在以下问题:

  • 节点选择路径错误(//beforechange/area/stud-class-buckets在输入XML中不存在)
  • 仅通过索引位置对比节点,未识别内容重复(前后class仅顺序调换,核心字段重复)
  • 使用非标准dyn:evaluate扩展,增加复杂度

调整后的XSLT代码如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:egm="http://example.com/egm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- 基于agent+ins-co组合键创建索引,用于去重 -->
    <xsl:key name="class-by-agent-insco" match="class" use="concat(agent, '|', ins-co)"/>

    <xsl:template match="/">
        <MaintenanceMessage>
            <BeforeImage>
                <MaintenanceList>
                    <!-- 只保留before中唯一的class,且与after中同agent+insco的class有type差异的 -->
                    <xsl:apply-templates select="//before/class[generate-id() = generate-id(key('class-by-agent-insco', concat(agent, '|', ins-co))[1])]">
                        <xsl:with-param name="placement" select="'before'"/>
                    </xsl:apply-templates>
                </MaintenanceList>
            </BeforeImage>
            <AfterImage>
                <MaintenanceList>
                    <!-- 只保留after中唯一的class,且与before中同agent+insco的class有type差异的 -->
                    <xsl:apply-templates select="//after/class[generate-id() = generate-id(key('class-by-agent-insco', concat(agent, '|', ins-co))[1])]">
                        <xsl:with-param name="placement" select="'after'"/>
                    </xsl:apply-templates>
                </MaintenanceList>
            </AfterImage>
        </MaintenanceMessage>
    </xsl:template>

    <xsl:template match="class">
        <xsl:param name="placement"/>
        <xsl:variable name="current-class" select="."/>
        <!-- 获取另一个节点集中匹配agent+insco的对应节点 -->
        <xsl:variable name="matching-class" select="
            $placement = 'before' 
            ? //after/class[agent = $current-class/agent and ins-co = $current-class/ins-co]
            : //before/class[agent = $current-class/agent and ins-co = $current-class/ins-co]
        "/>

        <!-- 仅当type不同时输出节点 -->
        <xsl:if test="$current-class/type != $matching-class/type">
            <!-- 根据placement选择节点名称 -->
            <xsl:element name="{if ($placement = 'after') then 'HazardMaintenance' else 'Maintenance'}">
                <xsl:attribute name="index">
                    <xsl:value-of select="position()"/>
                </xsl:attribute>
                <egm:TypeCode>
                    <xsl:value-of select="$current-class/type"/>
                </egm:TypeCode>
                <egm:AgentCode>
                    <xsl:value-of select="$current-class/agent"/>
                </egm:AgentCode>
                <egm:InsCoCode>
                    <xsl:value-of select="$current-class/ins-co"/>
                </egm:InsCoCode>
            </xsl:element>
        </xsl:if>
    </xsl:template>

    <!-- 保留原FieldValue模板处理空值逻辑 -->
    <xsl:template name="FieldValue">
        <xsl:param name="value"/>
        <xsl:choose>
            <xsl:when test="$value = '' or not($value)">null</xsl:when>
            <xsl:otherwise><xsl:value-of select="$value"/></xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

关键修改说明

  • 使用<xsl:key>实现基于agent和ins-co的去重,确保每个唯一组合只处理一次
  • 对比前后节点的type字段,仅当type不同时生成输出,过滤重复内容
  • 移除非标准dyn:evaluate,改用直接节点路径选择,提升代码可读性和兼容性
  • 针对AfterImage生成HazardMaintenance节点,匹配期望输出格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:19:52