XSLT转换XML至SAP IDOC时遇单条数据读取问题求助
XSLT转换XML到SAP IDOC格式的解决方案
需求说明
需要编写XSLT将源XML转换为SAP IDOC格式:
- 源XML包含根节点
<entities>,其下有多个<item>子节点 - 根据
<item>内的<item_registered>值设置<MATL_TYPE>:true对应ERSA,false对应HIBE - 每个
<item>对应输出一个<IDOC>节点
源XML示例
<entities actor="TXXXXX" timezone="Europe/Paris" messageId="771760c9-d24a-46dc-847a-6aef30c84c49" currencyCode="EUR" exchangeInterface="SAP_TEST"> <item id="190b41fda74-233f" code="M-016738"> <item_code>M-016738</item_code> <item_unit>PCE</item_unit> <item_description>Test SAP mass creation 1</item_description> <item_registered>false</item_registered> </item> <item id="190b41fda74-233g" code="M-016739"> <item_code>M-016739</item_code> <item_unit>PCE</item_unit> <item_description>Test SAP mass creation 2</item_description> <item_registered>true</item_registered> </item> </entities>
期望输出IDOC格式
<MATMAS_BAPI03> <IDOC BEGIN="1"> <EDI_DC40 SEGMENT="1"> <TABNAM>EDI_DC40</TABNAM> <MANDT>230</MANDT> <DOCNUM>0000000039534114</DOCNUM> </EDI_DC40> <E1BPMATHEAD SEGMENT="1"> <IND_SECTOR>M</IND_SECTOR> <MATL_TYPE>HIBE</MATL_TYPE> <!-- if item_registered is false --> <BASIC_VIEW>X</BASIC_VIEW> <MATL_DESC>Test SAP mass creation 1</MATL_DESC> <OLD_MAT_NO>M-016738</OLD_MAT_NO> </E1BPMATHEAD> </IDOC> <IDOC BEGIN="1"> <EDI_DC40 SEGMENT="1"> <TABNAM>EDI_DC40</TABNAM> <MANDT>230</MANDT> <DOCNUM>0000000039534114</DOCNUM> </EDI_DC40> <E1BPMATHEAD SEGMENT="1"> <IND_SECTOR>M</IND_SECTOR> <MATL_TYPE>ERSA</MATL_TYPE> <!-- if item_registered is true --> <BASIC_VIEW>X</BASIC_VIEW> <MATL_DESC>Test SAP mass creation 2</MATL_DESC> <OLD_MAT_NO>M-016739</OLD_MAT_NO> </E1BPMATHEAD> </IDOC> </MATMAS_BAPI03>
问题分析
原代码使用固定变量increment通过索引访问节点,导致只能处理单个<item>。正确做法是利用<xsl:for-each>的上下文特性,直接在循环内引用当前<item>节点的子元素。
完整XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <MATMAS_BAPI03> <!-- 遍历每个item节点,循环内上下文为当前item --> <xsl:for-each select="entities/item"> <IDOC BEGIN="1"> <EDI_DC40 SEGMENT="1"> <TABNAM>EDI_DC40</TABNAM> <MANDT>230</MANDT> <DOCNUM>0000000039534114</DOCNUM> </EDI_DC40> <E1BPMATHEAD SEGMENT="1"> <IND_SECTOR>M</IND_SECTOR> <!-- 根据item_registered的值设置MATL_TYPE --> <xsl:choose> <xsl:when test="item_registered = 'true'"> <MATL_TYPE>ERSA</MATL_TYPE> </xsl:when> <xsl:otherwise> <MATL_TYPE>HIBE</MATL_TYPE> </xsl:otherwise> </xsl:choose> <BASIC_VIEW>X</BASIC_VIEW> <!-- 直接引用当前item的子元素值 --> <MATL_DESC><xsl:value-of select="item_description"/></MATL_DESC> <OLD_MAT_NO><xsl:value-of select="item_code"/></OLD_MAT_NO> </E1BPMATHEAD> </IDOC> </xsl:for-each> </MATMAS_BAPI03> </xsl:template> </xsl:stylesheet>
关键要点说明
- 上下文节点利用:在
<xsl:for-each select="entities/item">循环内,当前上下文就是单个<item>节点,直接用item_description、item_registered即可访问子元素,无需通过索引定位。 - 条件判断:使用
<xsl:choose>实现<MATL_TYPE>的分支逻辑,根据<item_registered>的文本值匹配。 - 输出格式化:设置
xsl:output的indent="yes"让输出XML更易读。
内容的提问来源于stack exchange,提问作者Skyhald
相关产品推荐
相关产品推荐

