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

基于XSLT 1.0实现多级BOM XML到单层级父子结构XML的转换(不支持Muenchian分组)

解决方案:无key函数支持下的多级BOM转单层级XML(XSLT 1.0)

我明白你的困境——在XSLT 1.0环境里没法用key函数,没法依赖Muenchian分组来处理多级BOM的扁平化。别担心,咱们可以用递归模板来搞定这个需求,完全不需要key函数,靠层级遍历和参数传递就能实现父子关系的拆解。

下面是修改后的完整XSLT代码,我替换了你原框架里的transform模板部分:

<?bpc.pltype.out bpm.pltype=xml?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b1e="urn:com.sap.b1i.sim:b1event" xmlns:b1ie="urn:com.sap.b1i.sim:b1ievent" xmlns:b1im="urn:com.sap.b1i.sim:b1imessage" xmlns:bfa="urn:com.sap.b1i.bizprocessor:bizatoms" xmlns:exslt="http://exslt.org/common" xmlns:jdbc="urn:com.sap.b1i.adapter:jdbcadapter" xmlns:js="com.sap.b1i.bpc_tools.Javascript" xmlns:rev="urn:com.sap.b1i.adapter:revaadapter" xmlns:rfc="urn:sap-com:document:sap:rfc:functions" xmlns:sim="urn:com.sap.b1i.sim:entity" xmlns:utils="com.sap.b1i.bpc_tools.Utilities" xmlns:vpf="urn:com.sap.b1i.vplatform:entity" xmlns:xci="urn:com.sap.b1i.xcellerator:intdoc" version="1.0" exclude-result-prefixes="b1e b1ie b1im bfa jdbc js rfc utils xci vpf exslt sim rev" b1e:force="" b1ie:force="" b1im:force="" bfa:force="" jdbc:force="" js:force="" rfc:force="" utils:force="" xci:force="" vpf:force="" exslt:force="" sim:force="" rev:force="">
 <?prodver 1.0.0?>
 <!--<xsl:include href="../../com.sap.b1i.dev.repository/IDE/init.xsl" />-->
 <xsl:variable name="msg" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']" />
 <xsl:template match="/">
 <Msg xmlns="urn:com.sap.b1i.vplatform:entity">
 <xsl:copy-of select="/vpf:Msg/@*" />
 <xsl:copy-of select="/vpf:Msg/vpf:Header" />
 <Body>
 <xsl:copy-of select="/vpf:Msg/vpf:Body/*" />
 <Payload Role="X" id="999999">
 <xsl:call-template name="transform" />
 </Payload>
 </Body>
 </Msg>
 </xsl:template>

 <xsl:template name="transform">
  <Items>
    <!-- 遍历所有顶层level01物料 -->
    <xsl:for-each select="$msg/Items/level01">
      <!-- 生成顶层Item(无父项) -->
      <Item>
        <xsl:copy-of select="itemcode | quantity | whs" />
      </Item>
      <!-- 处理level02的子项,传递顶层物料编码作为父ID -->
      <xsl:call-template name="process-child-rows">
        <xsl:with-param name="parent-code" select="itemcode" />
        <xsl:with-param name="rows" select="level02/row" />
      </xsl:call-template>
    </xsl:for-each>
  </Items>
 </xsl:template>

 <!-- 递归处理子项行的模板 -->
 <xsl:template name="process-child-rows">
  <xsl:param name="parent-code" />
  <xsl:param name="rows" />

  <xsl:for-each select="$rows">
    <!-- 生成当前子项的Item记录,带父项编码 -->
    <Item>
      <father><xsl:value-of select="$parent-code" /></father>
      <xsl:copy-of select="itemcode | quantity | whs" />
    </Item>
    <!-- 如果当前行有下一级子项(比如level03),递归处理 -->
    <xsl:if test="level03">
      <xsl:call-template name="process-child-rows">
        <xsl:with-param name="parent-code" select="itemcode" />
        <xsl:with-param name="rows" select="level03/row" />
      </xsl:call-template>
    </xsl:if>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

代码逻辑说明

  • 顶层物料处理:transform模板先遍历所有level01节点,生成无father字段的顶层Item,然后调用递归模板处理它的子层级。
  • 递归子项处理:process-child-rows模板接收两个参数:parent-code(父项编码)和rows(需要处理的子项行)。对于每一行,先输出带father的Item,然后检查是否有下一级子节点(比如level03),如果有就再次调用自己,把当前行的编码作为新的父ID传递下去。
  • 灵活性:这个方案不局限于三级BOM,哪怕有更多层级(比如level04、level05),递归都会自动遍历处理,完全适配任意深度的BOM结构。

注意事项

你给出的期望输出里,<Item>和<item>大小写不一致,我在代码里统一用了大写的<Item>,如果需要和你的期望完全匹配,只需要把代码里的<Item>改成<item>即可。

用这个代码处理你的示例XML,会生成和你期望一致的单层级XML结果,每个父子关系都拆分成独立的记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 02:57:28