XSLT按条件替换值问题:CUOBJ字段替换为BELNR值失败
问题描述
我需要将/SHPMNT05/IDOC/E1EDT20/E1EDL20/E1EDL37/E1EDL44/CUOBJ的内容替换为同层级E1EDL24下E1EDL43/BELNR的值,但当前XSL转换后CUOBJ字段仅返回true,无法得到预期结果。推测是ancestor::node()[3]部分的写法有误,求正确的XSL转换方案。
补充说明:E1EDL44元素数量可能多于E1EDL24,二者通过POSNR关联;E1EDL20的VBELN与E1EDL24的POSNR组合唯一,每个E1EDL24仅包含一个E1EDL43。
原始XML数据
<SHPMNT05> <IDOC BEGIN="1"> <E1EDT20 SEGMENT="1"> <TKNUM>0000287302</TKNUM> <E1EDL20 SEGMENT="1"> <VBELN>0081018991</VBELN> <E1EDL24 SEGMENT="1"> <POSNR>000010</POSNR> <MATNR>000000000000009645</MATNR> <E1EDL43 SEGMENT="1"> <BELNR>0003196597</BELNR> </E1EDL43> </E1EDL24> <E1EDL24 SEGMENT="1"> <POSNR>000020</POSNR> <MATNR>000000000000009646</MATNR> <E1EDL43 SEGMENT="1"> <BELNR>0003196598</BELNR> </E1EDL43> </E1EDL24> <E1EDL37 SEGMENT="1"> <EXIDV>00387112831000247463</EXIDV> <E1EDL44 SEGMENT="1"> <VBELN>0081018991</VBELN> <POSNR>000010</POSNR> <CUOBJ>000000000000000000</CUOBJ> </E1EDL44> </E1EDL37> <E1EDL37 SEGMENT="1"> <EXIDV>00387112831000247470</EXIDV> <E1EDL44 SEGMENT="1"> <VBELN>0081018991</VBELN> <POSNR>000020</POSNR> <VEMNG>5000.000</VEMNG> <CUOBJ>000000000000000000</CUOBJ> </E1EDL44> </E1EDL37> </E1EDL20> </E1EDT20> </IDOC> </SHPMNT05>
当前使用的XSL代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="node()|@*" mode="#all"> <xsl:copy> <xsl:apply-templates select="node()|@*" mode="#current"/> </xsl:copy> </xsl:template> <xsl:template match="/SHPMNT05/IDOC/E1EDT20/E1EDL20/E1EDL37/E1EDL44/CUOBJ"> <CUOBJ> <xsl:value-of select="ancestor::node()[3]/VBELN=../VBELN and ancestor::node()[3]/E1EDL24/POSNR=../POSNR"/></CUOBJ> <xsl:for-each select="//E1EDL44"> </xsl:for-each> </xsl:template> </xsl:stylesheet>
当前转换结果
<SHPMNT05> <IDOC BEGIN="1"> <E1EDT20 SEGMENT="1"> <TKNUM>0000287302</TKNUM> <E1EDL20 SEGMENT="1"> <VBELN>0081018991</VBELN> <E1EDL24 SEGMENT="1"> <POSNR>000010</POSNR> <MATNR>000000000000009645</MATNR> <E1EDL43 SEGMENT="1"> <BELNR>0003196597</BELNR> </E1EDL43> </E1EDL24> <E1EDL24 SEGMENT="1"> <POSNR>000020</POSNR> <MATNR>000000000000009646</MATNR> <E1EDL43 SEGMENT="1"> <BELNR>0003196597</BELNR> </E1EDL43> </E1EDL24> <E1EDL37 SEGMENT="1"> <EXIDV>00387112831000247463</EXIDV> <E1EDL44 SEGMENT="1"> <VBELN>0081018991</VBELN> <POSNR>000010</POSNR> <CUOBJ>true</CUOBJ> </E1EDL44> </E1EDL37> <E1EDL37 SEGMENT="1"> <EXIDV>00387112831000247470</EXIDV> <E1EDL44 SEGMENT="1"> <VBELN>0081018991</VBELN> <POSNR>000020</POSNR> <VEMNG>5000.000</VEMNG> <CUOBJ>true</CUOBJ> </E1EDL44> </E1EDL37> </E1EDL20> </E1EDT20> </IDOC> </SHPMNT05>
预期转换结果
<SHPMNT05> <IDOC BEGIN="1"> <E1EDT20 SEGMENT="1"> <TKNUM>0000287302</TKNUM> <E1EDL20 SEGMENT="1"> <VBELN>0081018991</VBELN> <E1EDL24 SEGMENT="1"> <POSNR>000010</POSNR> <MATNR>000000000000009645</MATNR> <E1EDL43 SEGMENT="1"> <BELNR>0003196597</BELNR> </E1EDL43> </E1EDL24> <E1EDL24 SEGMENT="1"> <POSNR>000020</POSNR> <MATNR>000000000000009646</MATNR> <E1EDL43 SEGMENT="1"> <BELNR>0003196598</BELNR> </E1EDL43> </E1EDL24> <E1EDL37 SEGMENT="1"> <EXIDV>00387112831000247463</EXIDV> <E1EDL44 SEGMENT="1"> <VBELN>0081018991</VBELN> <POSNR>000010</POSNR> <CUOBJ>0003196597</CUOBJ> </E1EDL44> </E1EDL37> <E1EDL37 SEGMENT="1"> <EXIDV>00387112831000247470</EXIDV> <E1EDL44 SEGMENT="1"> <VBELN>0081018991</VBELN> <POSNR>000020</POSNR> <VEMNG>5000.000</VEMNG> <CUOBJ>0003196598</CUOBJ> </E1EDL44> </E1EDL37> </E1EDL20> </E1EDT20> </IDOC> </SHPMNT05>
解决方案
问题出在当前xsl:value-of返回的是布尔判断结果,而非对应的BELNR值。正确做法是先定位到同层级下匹配POSNR的E1EDL24节点,再取出其下的BELNR值。
修正后的XSL代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <!-- 身份转换模板,保留所有原始内容 --> <xsl:template match="node()|@*" mode="#all"> <xsl:copy> <xsl:apply-templates select="node()|@*" mode="#current"/> </xsl:copy> </xsl:template> <!-- 处理CUOBJ节点,替换为匹配的BELNR值 --> <xsl:template match="/SHPMNT05/IDOC/E1EDT20/E1EDL20/E1EDL37/E1EDL44/CUOBJ"> <xsl:variable name="current-posnr" select="../POSNR"/> <CUOBJ> <xsl:value-of select="ancestor::E1EDL20/E1EDL24[POSNR=$current-posnr]/E1EDL43/BELNR"/> </CUOBJ> </xsl:template> </xsl:stylesheet>
说明
- 定义变量
current-posnr,获取当前E1EDL44节点下的POSNR值作为关联条件; - 通过
ancestor::E1EDL20定位到共同父节点E1EDL20,筛选出其中POSNR与当前节点匹配的E1EDL24节点; - 取出该E1EDL24节点下E1EDL43的BELNR值,替换CUOBJ内容;
- 移除原代码中无用的
xsl:for-each循环,简化逻辑。
内容的提问来源于stack exchange,提问作者Mike Dole
相关产品推荐
相关产品推荐

