如何移除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>
关键改动点
- 修正去重逻辑:将过滤条件改为
preceding-sibling::Z1CAWNM_SVMX/ATNAM,仅在当前Z1EQUIPMENT_SVMX的兄弟节点范围内去重,确保每个ATNAM只触发一次模板。 - 简化值拼接逻辑:用
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
相关产品推荐
相关产品推荐

