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

如何移除XSLT映射中的重复输出?技术求助

问题:XSLT映射后出现重复节点,需移除重复行

XML源文件

<?xml version="1.0" encoding="UTF-8"?>
<ZEQUIPMENT_SVMX01_01>
    <IDOC BEGIN="1">
        <Z1EQUIPMENT_SVMX SEGMENT="1">
            <Z1CAWNM_SVMX SEGMENT="1">
                <ATNAM>TS_DEVICE_USAGE_DEPARTMENT</ATNAM>
                <ATWRT>ABC</ATWRT>
                <ATZHL> 1</ATZHL>
            </Z1CAWNM_SVMX>
        </Z1EQUIPMENT_SVMX>
    </IDOC>
    <IDOC BEGIN="1">
        <Z1EQUIPMENT_SVMX SEGMENT="1">
            <Z1CAWNM_SVMX SEGMENT="1">
                <ATNAM>TS_DEVICE_USAGE_DEPARTMENT</ATNAM>
                <ATWRT>LOA</ATWRT>
                <ATZHL> 1</ATZHL>
            </Z1CAWNM_SVMX>
            <Z1CAWNM_SVMX SEGMENT="1">
                <ATNAM>TS_DEVICE_USAGE_DEPARTMENT</ATNAM>
                <ATWRT>VET</ATWRT>
                <ATZHL> 2</ATZHL>
            </Z1CAWNM_SVMX>
        </Z1EQUIPMENT_SVMX>
    </IDOC>
</ZEQUIPMENT_SVMX01_01>

当前映射输出(存在重复节点)

<?xml version="1.0" encoding="UTF-8"?>
<a:Upsert_Installed_Product_Buffer_Object__cBulkRequest xmlns:a="http:///10" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <batch>
      <sObject>
         <R3_DEVICE_USAGE_DEPARTMENT__c>ABC</R3_DEVICE_USAGE_DEPARTMENT__c>
      </sObject>
      <sObject>
         <R3_DEVICE_USAGE_DEPARTMENT__c>LOA;VET</R3_DEVICE_USAGE_DEPARTMENT__c>
         <R3_DEVICE_USAGE_DEPARTMENT__c>LOA;VET</R3_DEVICE_USAGE_DEPARTMENT__c>
      </sObject>
   </batch>
</a:Upsert_Installed_Product_Buffer_Object__cBulkRequest>

现有XSLT代码

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http:///10" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <a:Upsert_Installed_Product_Buffer_Object__cBulkRequest>
            <batch>
                <xsl:choose>
                    <xsl:when test="ZEQUIPMENT_SVMX01">
                        <xsl:apply-templates select="ZEQUIPMENT_SVMX01/IDOC"/>
                    </xsl:when>
                    <xsl:when test="ZEQUIPMENT_SVMX01_01">
                        <xsl:apply-templates select="ZEQUIPMENT_SVMX01_01/IDOC"/>
                    </xsl:when>
                </xsl:choose>
            </batch>
        </a:Upsert_Installed_Product_Buffer_Object__cBulkRequest>
    </xsl:template>
    <xsl:template match="IDOC">
        <sObject>
            <xsl:apply-templates select="Z1EQUIPMENT_SVMX/Z1CAWNM_SVMX[not(ATNAM=preceding::ATNAM[position()=0])]"/>
        </sObject>
    </xsl:template>
    <xsl:template match="Z1CAWNM_SVMX">
        <xsl:variable name="ChararcteristicName" select="ATNAM"/>
        <xsl:element name="{concat('R3_',substring-after(ATNAM,'TS_'),'__c')}">
            <xsl:apply-templates select="../Z1CAWNM_SVMX[ATNAM = $ChararcteristicName]/ATWRT"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="ATWRT">
        <xsl:value-of select="."/>
        <xsl:if test="position() != last()">
            <xsl:text>;</xsl:text>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

问题说明

映射后第二个sObject里出现了重复的<R3_DEVICE_USAGE_DEPARTMENT__c>节点,预期每个sObject下仅保留一行该节点,需解决重复输出问题。


解决方案

问题原因

现有代码中IDOC模板的过滤条件[not(ATNAM=preceding::ATNAM[position()=0])]无效:节点位置从1开始,position()=0不会匹配任何节点,导致所有Z1CAWNM_SVMX节点都会被处理。当一个IDOC下有多个同ATNAM的Z1CAWNM_SVMX时,每个都会触发模板生成重复节点。

修改后的XSLT代码

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http:///10" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    
    <!-- 主模板 -->
    <xsl:template match="/">
        <a:Upsert_Installed_Product_Buffer_Object__cBulkRequest>
            <batch>
                <xsl:choose>
                    <xsl:when test="ZEQUIPMENT_SVMX01">
                        <xsl:apply-templates select="ZEQUIPMENT_SVMX01/IDOC"/>
                    </xsl:when>
                    <xsl:when test="ZEQUIPMENT_SVMX01_01">
                        <xsl:apply-templates select="ZEQUIPMENT_SVMX01_01/IDOC"/>
                    </xsl:when>
                </xsl:choose>
            </batch>
        </a:Upsert_Installed_Product_Buffer_Object__cBulkRequest>
    </xsl:template>
    
    <!-- 处理每个IDOC,生成一个sObject -->
    <xsl:template match="IDOC">
        <sObject>
            <!-- 按ATNAM分组,仅处理每个分组的第一个节点 -->
            <xsl:apply-templates select="Z1EQUIPMENT_SVMX/Z1CAWNM_SVMX[not(ATNAM=preceding-sibling::Z1CAWNM_SVMX/ATNAM)]"/>
        </sObject>
    </xsl:template>
    
    <!-- 处理分组后的Z1CAWNM_SVMX,拼接同ATNAM的所有ATWRT值 -->
    <xsl:template match="Z1CAWNM_SVMX">
        <xsl:variable name="charName" select="ATNAM"/>
        <xsl:element name="{concat('R3_',substring-after(ATNAM,'TS_'),'__c')}">
            <!-- 遍历当前IDOC下所有同ATNAM的ATWRT节点 -->
            <xsl:for-each select="../Z1CAWNM_SVMX[ATNAM = $charName]/ATWRT">
                <xsl:value-of select="."/>
                <xsl:if test="position() != last()">
                    <xsl:text>;</xsl:text>
                </xsl:if>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

关键改动点

  1. 修正去重逻辑:将过滤条件改为preceding-sibling::Z1CAWNM_SVMX/ATNAM,仅在当前Z1EQUIPMENT_SVMX的兄弟节点范围内去重,确保每个ATNAM只触发一次模板。
  2. 简化值拼接逻辑:用xsl:for-each直接遍历同组ATWRT节点,避免重复调用模板导致的冗余。

预期输出

<?xml version="1.0" encoding="UTF-8"?>
<a:Upsert_Installed_Product_Buffer_Object__cBulkRequest xmlns:a="http:///10" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <batch>
      <sObject>
         <R3_DEVICE_USAGE_DEPARTMENT__c>ABC</R3_DEVICE_USAGE_DEPARTMENT__c>
      </sObject>
      <sObject>
         <R3_DEVICE_USAGE_DEPARTMENT__c>LOA;VET</R3_DEVICE_USAGE_DEPARTMENT__c>
      </sObject>
   </batch>
</a:Upsert_Installed_Product_Buffer_Object__cBulkRequest>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:05:23