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

添加SAP PI信封后XSLT转换失效,求可行解决方案

解决SAP PI信封下XSLT转换失效问题

问题背景

我有一套可正常运行的XSLT,处理不带信封的目标命名空间XML时能得到预期转换结果。但当SAP PI为XML添加带有http://sap.com/xi/XI/SplitAndMerge命名空间的<ns0:Messages>信封后,XSLT转换仅输出空的<Containers>节点。希望修改XSLT,既能保留信封结构,又能正确转换内部的Containers内容。

输入XML(无信封)

<Containers xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer">
    <Container>
        <Name>INTERIEUR1</Name>
        <Number>1</Number>
        <SSCC>111</SSCC>
        <SubContainers>
            <Container>
                <Id>I1371851</Id>
                <SalesOrderNumber>2012231</SalesOrderNumber>
                <ProductionOrderNumber>I2017658</ProductionOrderNumber>
                <Name>ACCESSOIRE1</Name>
                <Barcode>181001371851</Barcode>
                <Items>
                    <Item>
                        <Id>I8709475</Id>
                        <SalesOrderRowId>I671068</SalesOrderRowId>
                        <SalesOrderRowExternalReference>1</SalesOrderRowExternalReference>
                        <Quantity>1</Quantity>
                    </Item>
                    <Item>
                        <Id>I8709476</Id>
                        <SalesOrderRowId>I671068</SalesOrderRowId>
                        <SalesOrderRowExternalReference>1</SalesOrderRowExternalReference>
                        <Quantity>1</Quantity>
                    </Item>
                </Items>
            </Container>
            <Container>
                <Id>I1371852</Id>
                <SalesOrderNumber>2012231</SalesOrderNumber>
                <ProductionOrderNumber>I2017658</ProductionOrderNumber>
                <Name>PANEEL1</Name>
                <Barcode>181001371852</Barcode>
                <Items>
                    <Item>
                        <Id>I8709492</Id>
                        <SalesOrderRowId>I671068</SalesOrderRowId>
                        <SalesOrderRowExternalReference>1</SalesOrderRowExternalReference>
                        <Quantity>1</Quantity>
                    </Item>
                </Items>
            </Container>
        </SubContainers>
    </Container>
</Containers>

原XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xpath-default-namespace="https://www.uniconcreation.com/2021/IvenzaShippingContainer" xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
   <xsl:template match="Containers">
      <xsl:variable name="sscc" select="Container/SSCC"/>
      <xsl:copy>
         <xsl:for-each select="//Container">
            <xsl:variable name="level" select="count(ancestor::*)"/>
            <xsl:choose>
               <xsl:when test="$level = 1">
                  <xsl:copy>
                     <xsl:copy-of select="Id"/>
                     <xsl:copy-of select="SalesOrderNumber"/>
                     <xsl:copy-of select="ProductionOrderNumber"/>
                     <xsl:copy-of select="Name"/>
                     <xsl:copy-of select="Type"/>
                     <xsl:copy-of select="Number"/>
                     <xsl:copy-of select="SSCC"/>
                     <xsl:copy-of select="Barcode"/>
                     <xsl:copy-of select="StartedAt"/>
                     <xsl:copy-of select="CompletedAt"/>
                     <xsl:choose>
                        <xsl:when test="SubContainers">
                           <Items>
                              <xsl:for-each select="SubContainers">
                                 <Item>
                                    <Id>
                                       <xsl:value-of select="Container[1]/Id"/>
                                    </Id>
                                    <SalesOrderRowId>
                                       <xsl:value-of select="Container[1]/Items/Item[1]/SalesOrderRowId"/>
                                    </SalesOrderRowId>
                                    
                                    <Quantity>1</Quantity>
                                 </Item>
                              </xsl:for-each>
                           </Items>
                        </xsl:when>
                        <xsl:otherwise>
                           <xsl:copy-of select="Items"/>
                        </xsl:otherwise>
                     </xsl:choose>
                  </xsl:copy>
               </xsl:when>
               <xsl:otherwise>
     </xsl:otherwise>
            </xsl:choose>
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

原转换结果

<?xml version="1.0" encoding="UTF-8"?>
<Containers xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer">
   <Container>
      <Name>INTERIEUR1</Name>
      <Number>1</Number>
      <SSCC>111</SSCC>
      <Items>
         <Item>
            <Id>I1371851</Id>
            <SalesOrderRowId>I671068</SalesOrderRowId>
            <Quantity>1</Quantity>
         </Item>
      </Items>
   </Container>
</Containers>

带SAP PI信封的输入XML

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
   <ns0:Message1>
<Containers xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer">
        <Container>
            <Name>INTERIEUR1</Name>
            <Number>1</Number>
            <SSCC>111</SSCC>
            <SubContainers>
                <Container>
                    <Id>I1371851</Id>
                    <SalesOrderNumber>2012231</SalesOrderNumber>
                    <ProductionOrderNumber>I2017658</ProductionOrderNumber>
                    <Name>ACCESSOIRE1</Name>
                    <Barcode>181001371851</Barcode>
                    <Items>
                        <Item>
                            <Id>I8709475</Id>
                            <SalesOrderRowId>I671068</SalesOrderRowId>
                            <SalesOrderRowExternalReference>1</SalesOrderRowExternalReference>
                            <Quantity>1</Quantity>
                        </Item>
                        <Item>
                            <Id>I8709476</Id>
                            <SalesOrderRowId>I671068</SalesOrderRowId>
                            <SalesOrderRowExternalReference>1</SalesOrderRowExternalReference>
                            <Quantity>1</Quantity>
                        </Item>
                    </Items>
                </Container>
                <Container>
                    <Id>I1371852</Id>
                    <SalesOrderNumber>2012231</SalesOrderNumber>
                    <ProductionOrderNumber>I2017658</ProductionOrderNumber>
                    <Name>PANEEL1</Name>
                    <Barcode>181001371852</Barcode>
                    <Items>
                        <Item>
                            <Id>I8709492</Id>
                            <SalesOrderRowId>I671068</SalesOrderRowId>
                            <SalesOrderRowExternalReference>1</SalesOrderRowExternalReference>
                            <Quantity>1</Quantity>
                        </Item>
                    </Items>
                </Container>
            </SubContainers>
        </Container>
</Containers>
   </ns0:Message1>
</ns0:Messages>

当前错误输出

<?xml version="1.0" encoding="UTF-8"?>
<Containers xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer"
            xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge"/>

期望输出

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
   <ns0:Message1>
<Containers xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer">
   <Container>
      <Name>INTERIEUR1</Name>
      <Number>1</Number>
      <SSCC>111</SSCC>
      <Items>
         <Item>
            <Id>I1371851</Id>
            <SalesOrderRowId>I671068</SalesOrderRowId>
            <Quantity>1</Quantity>
         </Item>
      </Items>
   </Container>
</Containers>
   </ns0:Message1>
</ns0:Messages>

解决方案

添加身份模板复制SAP PI信封节点,同时保留原有Containers处理逻辑,无需手动处理所有命名空间。

修改后的XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
                xpath-default-namespace="https://www.uniconcreation.com/2021/IvenzaShippingContainer" 
                xmlns="https://www.uniconcreation.com/2021/IvenzaShippingContainer" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:pi="http://sap.com/xi/XI/SplitAndMerge">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <!-- 身份模板:复制所有未被匹配的节点和属性,保留SAP PI信封结构 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 保留原有的Containers处理逻辑,仅针对目标命名空间节点转换 -->
    <xsl:template match="Containers">
        <xsl:copy>
            <xsl:for-each select="//Container">
                <xsl:variable name="level" select="count(ancestor::*)"/>
                <xsl:choose>
                    <xsl:when test="$level = 1">
                        <xsl:copy>
                            <xsl:copy-of select="Id"/>
                            <xsl:copy-of select="SalesOrderNumber"/>
                            <xsl:copy-of select="ProductionOrderNumber"/>
                            <xsl:copy-of select="Name"/>
                            <xsl:copy-of select="Type"/>
                            <xsl:copy-of select="Number"/>
                            <xsl:copy-of select="SSCC"/>
                            <xsl:copy-of select="Barcode"/>
                            <xsl:copy-of select="StartedAt"/>
                            <xsl:copy-of select="CompletedAt"/>
                            <xsl:choose>
                                <xsl:when test="SubContainers">
                                    <Items>
                                        <xsl:for-each select="SubContainers">
                                            <Item>
                                                <Id>
                                                    <xsl:value-of select="Container[1]/Id"/>
                                                </Id>
                                                <SalesOrderRowId>
                                                    <xsl:value-of select="Container[1]/Items/Item[1]/SalesOrderRowId"/>
                                                </SalesOrderRowId>
                                                
                                                <Quantity>1</Quantity>
                                            </Item>
                                        </xsl:for-each>
                                    </Items>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:copy-of select="Items"/>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:copy>
                    </xsl:when>
                    <xsl:otherwise>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

方案说明

  • 身份模板:匹配所有节点和属性,默认执行复制操作,确保SAP PI信封节点完整保留,无需单独编写模板处理该命名空间。
  • 原有Containers模板逻辑不变,仅对目标命名空间下的节点进行转换,不干扰信封结构。
  • 声明SAP PI命名空间前缀pi,避免命名空间解析冲突,确保XSLT能正确识别信封节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:15:41