求助:基于条件替换XML中VKORG元素值的XSLT实现
XSLT XML处理需求及修正方案
需求说明
当XML中E1EDL21元素的LFART值为LO时,将同层级E1EDL20下的VKORG元素值替换为该E1EDL20节点下PARTNER_Q为WE的E1ADRM1元素的PARTNER_ID值。
输入XML
<SHPMNT05> <IDOC BEGIN="1"> <EDI_DC40 SEGMENT="1"> <TABNAM>EDI_DC40</TABNAM> </EDI_DC40> <E1EDT20 SEGMENT="1"> <TKNUM>0000287306</TKNUM> <E1EDL20 SEGMENT="1"> <VBELN>0081018890</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LO</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>12417</PARTNER_ID> </E1ADRM1> </E1EDL20> <E1EDL20 SEGMENT="1"> <VBELN>0081018891</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LR</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>1112</PARTNER_ID> </E1ADRM1> </E1EDL20> <E1EDL20 SEGMENT="1"> <VBELN>0081018892</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LO</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>12418</PARTNER_ID> </E1ADRM1> </E1EDL20> </E1EDT20> </IDOC> </SHPMNT05>
当前错误XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="E1EDT20"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:for-each select="*[not(self::E1EDL20)]"> <xsl:copy-of select="."/> </xsl:for-each> </xsl:copy> <xsl:for-each select="E1EDL20"> <xsl:choose> <xsl:when test="E1EDL21/LFART='LO'"> <xsl:variable name="customer" select="E1ADRM1[PARTNER_Q='WE']/PARTNER_ID"/> <xsl:value-of select="$customer"/> <xsl:copy-of select="."/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet>
当前错误输出
<SHPMNT05> <IDOC BEGIN="1"> <EDI_DC40 SEGMENT="1"> <TABNAM>EDI_DC40</TABNAM> </EDI_DC40> <E1EDT20 SEGMENT="1"> <TKNUM>0000287306</TKNUM> </E1EDT20>12417<E1EDL20 SEGMENT="1"> <VBELN>0081018890</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LO</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>12417</PARTNER_ID> </E1ADRM1> </E1EDL20> <E1EDL20 SEGMENT="1"> <VBELN>0081018891</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LR</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>1112</PARTNER_ID> </E1ADRM1> </E1EDL20>12418<E1EDL20 SEGMENT="1"> <VBELN>0081018892</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LO</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>12418</PARTNER_ID> </E1ADRM1> </E1EDL20> </IDOC> </SHPMNT05>
期望输出
<SHPMNT05> <IDOC BEGIN="1"> <EDI_DC40 SEGMENT="1"> <TABNAM>EDI_DC40</TABNAM> </EDI_DC40> <E1EDT20 SEGMENT="1"> <TKNUM>0000287306</TKNUM> </E1EDT20> <E1EDL20 SEGMENT="1"> <VBELN>0081018890</VBELN> <VKORG>12417</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LO</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>12417</PARTNER_ID> </E1ADRM1> </E1EDL20> <E1EDL20 SEGMENT="1"> <VBELN>0081018891</VBELN> <VKORG>0200</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LR</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>1112</PARTNER_ID> </E1ADRM1> </E1EDL20> <E1EDL20 SEGMENT="1"> <VBELN>0081018892</VBELN> <VKORG>12418</VKORG> <E1EDL21 SEGMENT="1"> <LFART>LO</LFART> </E1EDL21> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>SP</PARTNER_Q> <PARTNER_ID>5041</PARTNER_ID> </E1ADRM1> <E1ADRM1 SEGMENT="1"> <PARTNER_Q>WE</PARTNER_Q> <PARTNER_ID>12418</PARTNER_ID> </E1ADRM1> </E1EDL20> </IDOC> </SHPMNT05>
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <!-- 身份模板:复制所有节点和属性,默认行为 --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <!-- 匹配需要替换的VKORG元素,仅当父节点E1EDL20下的E1EDL21/LFART为'LO'时生效 --> <xsl:template match="E1EDL20/VKORG[../E1EDL21/LFART='LO']"> <VKORG> <!-- 获取同层级下PARTNER_Q为'WE'的E1ADRM1的PARTNER_ID值 --> <xsl:value-of select="../E1ADRM1[PARTNER_Q='WE']/PARTNER_ID"/> </VKORG> </xsl:template> <!-- 修正原E1EDT20模板,保持节点结构完整 --> <xsl:template match="E1EDT20"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
修正说明
- 原代码错误原因:直接将
PARTNER_ID输出在E1EDL20外部,且用xsl:copy-of复制整个E1EDL20节点,未修改内部的VKORG值,还破坏了E1EDT20的节点结构。 - 修正思路:
- 保留身份模板,确保大部分节点原样复制。
- 精准匹配需要修改的
VKORG元素,仅当其父节点E1EDL20下存在LFART='LO'的E1EDL21时,替换VKORG的内容为目标PARTNER_ID。 - 修正
E1EDT20的模板,直接使用身份模板的逻辑,保持节点结构完整,无需拆分处理子节点。
内容的提问来源于stack exchange,提问作者Mike Dole
相关产品推荐
相关产品推荐

