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

XSLT 3.0多循环代码问题求助:无法生成预期XML输出

XSLT多循环代码输出异常问题排查与修正

问题说明

我并非经常使用XSLT的开发者,编写了一段包含多循环的XSLT代码,但无法生成预期的XML输出。现提供相关输入、代码及预期输出,恳请技术建议。

XML输入

<Order>
    <OrderTypes>
        <SalesOrder>3000016154</SalesOrder>
        <SoldToParty>1</SoldToParty>
        <ItemPartner>
            <PartnerTypes>
                <PFunction>SH</PFunction>
                <Customer>A</Customer>
                <Address>
                    <AddressType>
                        <Name>Test_FinalCustomer1</Name>
                        <Address>Test_FinalCustomer1</Address>
                    </AddressType>
                </Address>
            </PartnerTypes>
            <PartnerTypes>
                <PFunction>FC</PFunction>
                <Customer>B</Customer>
                <Address>
                    <AddressType>
                        <Name>Test_FinalCustomer2</Name>
                        <Address>Test_FinalCustomer2</Address>
                    </AddressType>
                </Address>
            </PartnerTypes>
        </ItemPartner>
        <ItemTypes>
            <Types>
                <Unit>KG</Unit>
                <NetAmount>5000.00</NetAmount>
                <PricingElementsType>
                    <PrElementType>
                        <RateValue>2000</RateValue>
                        <Quantity>1</Quantity>
                        <Type>PR00</Type>
                    </PrElementType>
                    <PrElementType>
                        <RateValue>3000</RateValue>
                        <Quantity>2</Quantity>
                        <Type>PR01</Type>
                    </PrElementType>
                </PricingElementsType>
            </Types>
            <Types>
                <Unit>ML</Unit>
                <NetAmount>6000.00</NetAmount>
                <PricingElementsType>
                    <PrElementType>
                        <RateValue>4000</RateValue>
                        <Quantity>1</Quantity>
                        <Type>PR00</Type>
                    </PrElementType>
                    <PrElementType>
                        <RateValue>2000</RateValue>
                        <Quantity>2</Quantity>
                        <Type>PR01</Type>
                    </PrElementType>
                </PricingElementsType>
            </Types>
        </ItemTypes>
    </OrderTypes>
</Order>

当前XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:n0="http://sap.com/xi/SAPGlobal20/Global" exclude-result-prefixes="xs" xmlns:exsl="http://exslt.org/common" xmlns:ext="http://exslt.org/common">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="Order">
        <xsl:for-each select="OrderTypes">
            <data>
                <xsl:if test="SalesOrder">
                    <VBELN>
                        <xsl:value-of select="SalesOrder"/>
                    </VBELN>
                </xsl:if>
                <HEAD>
                    <xsl:if test="SalesOrder">
                        <VBELN>
                            <xsl:value-of select="SalesOrder"/>
                        </VBELN>
                    </xsl:if>
                    <xsl:if test="SoldToParty">
                        <KUNNR_AG>
                            <xsl:value-of select="SoldToParty"/>
                        </KUNNR_AG>
                    </xsl:if>
                
                <xsl:for-each select="//PartnerTypes">
                    <xsl:if test="PFunction = 'SH'">
                        <xsl:if test=" Customer">
                    <KUNNR_SH>
                        <xsl:value-of select="Customer"/>
                    </KUNNR_SH>
                </xsl:if>
                <xsl:for-each select="//AddressType">
                    <xsl:if test="Address">
                        <Address>
                            <xsl:value-of select="Address"/>
                        </Address>
                    </xsl:if>
                </xsl:for-each>
            </xsl:if>
        </xsl:for-each>
        <xsl:for-each select="//Types">
            <HEAD_ENTRIES>
                <xsl:if test="Unit">
                    <UNIT>
                        <xsl:value-of select="Unit"/>
                    </UNIT>
                </xsl:if>
                <xsl:if test="NetAmount">
                    <NET_AMOUNT>
                        <xsl:value-of select="NetAmount"/>
                    </NET_AMOUNT>
                </xsl:if>
                <xsl:for-each select="//PrElementType">
                
                <xsl:if test="Type ='PR00'">
                    <xsl:if test="RateValue">
                        <RATE_VALUE>
                            <xsl:value-of select="RateValue"/>
                        </RATE_VALUE>
                    </xsl:if>
                    <xsl:if test="Quantity">
                        <QUANTITY>
                            <xsl:value-of select="Quantity"/>
                        </QUANTITY>
                    </xsl:if>
                </xsl:if>   
                </xsl:for-each>
            </HEAD_ENTRIES>
            
        </xsl:for-each>
        </HEAD>
    </data>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

预期输出

<data xmlns:java="http://xml.apache.org/xslt/java"
      xmlns:map="http://www.w3.org/2005/xpath-functions/map"
      xmlns:n0="http://sap.com/xi/SAPGlobal20/Global"
      xmlns:exsl="http://exslt.org/common"
      xmlns:ext="http://exslt.org/common">
   <VBELN>3000016154</VBELN>
   <HEAD>
      <VBELN>3000016154</VBELN>
      <KUNNR_AG>1</KUNNR_AG>
      <KUNNR_SH>A</KUNNR_SH>
      <Address>Test_FinalCustomer1</Address>
      <HEAD_ENTRIES>
         <UNIT>KG</UNIT>
         <NET_AMOUNT>5000.00</NET_AMOUNT>
         <RATE_VALUE>2000</RATE_VALUE>
         <QUANTITY>1</QUANTITY>
      </HEAD_ENTRIES>
      <HEAD_ENTRIES>
         <UNIT>ML</UNIT>
         <NET_AMOUNT>6000.00</NET_AMOUNT>
         <RATE_VALUE>4000</RATE_VALUE>
         <QUANTITY>1</QUANTITY>
      </HEAD_ENTRIES>
   </HEAD>
</data>

问题分析

原代码的核心问题是错误使用了绝对路径//,导致循环时选取了文档中所有匹配的节点,而非当前上下文的关联节点:

  1. 遍历PartnerTypes时,用//AddressType会选取所有AddressType节点,包括FC类型下的地址,不符合预期;应改为当前PartnerTypes下的Address/AddressType。
  2. 遍历Types时,用//PrElementType会选取所有PrElementType节点,导致每个HEAD_ENTRIES都包含所有PR00类型的RateValue和Quantity,而非当前Types对应的内容;应改为当前Types下的PricingElementsType/PrElementType。
  3. 遍历PartnerTypes时,原路径//PartnerTypes会选取所有PartnerTypes,虽然加了PFunction=SH的判断,但更高效的写法是直接选取当前OrderTypes下的ItemPartner/PartnerTypes[PFunction='SH']。

修正后的XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:n0="http://sap.com/xi/SAPGlobal20/Global" exclude-result-prefixes="xs" xmlns:exsl="http://exslt.org/common" xmlns:ext="http://exslt.org/common">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="Order">
        <xsl:for-each select="OrderTypes">
            <data>
                <xsl:if test="SalesOrder">
                    <VBELN>
                        <xsl:value-of select="SalesOrder"/>
                    </VBELN>
                </xsl:if>
                <HEAD>
                    <xsl:if test="SalesOrder">
                        <VBELN>
                            <xsl:value-of select="SalesOrder"/>
                        </VBELN>
                    </xsl:if>
                    <xsl:if test="SoldToParty">
                        <KUNNR_AG>
                            <xsl:value-of select="SoldToParty"/>
                        </KUNNR_AG>
                    </xsl:if>
                    
                    <!-- 仅选取当前OrderTypes下PFunction为SH的PartnerTypes -->
                    <xsl:for-each select="ItemPartner/PartnerTypes[PFunction='SH']">
                        <xsl:if test="Customer">
                            <KUNNR_SH>
                                <xsl:value-of select="Customer"/>
                            </KUNNR_SH>
                        </xsl:if>
                        <!-- 选取当前PartnerTypes下的AddressType -->
                        <xsl:for-each select="Address/AddressType">
                            <xsl:if test="Address">
                                <Address>
                                    <xsl:value-of select="Address"/>
                                </Address>
                            </xsl:if>
                        </xsl:for-each>
                    </xsl:for-each>
                    
                    <!-- 遍历当前OrderTypes下的Types节点 -->
                    <xsl:for-each select="ItemTypes/Types">
                        <HEAD_ENTRIES>
                            <xsl:if test="Unit">
                                <UNIT>
                                    <xsl:value-of select="Unit"/>
                                </UNIT>
                            </xsl:if>
                            <xsl:if test="NetAmount">
                                <NET_AMOUNT>
                                    <xsl:value-of select="NetAmount"/>
                                </NET_AMOUNT>
                            </xsl:if>
                            <!-- 选取当前Types下的PR00类型PrElementType -->
                            <xsl:for-each select="PricingElementsType/PrElementType[Type='PR00']">
                                <xsl:if test="RateValue">
                                    <RATE_VALUE>
                                        <xsl:value-of select="RateValue"/>
                                    </RATE_VALUE>
                                </xsl:if>
                                <xsl:if test="Quantity">
                                    <QUANTITY>
                                        <xsl:value-of select="Quantity"/>
                                    </QUANTITY>
                                </xsl:if>
                            </xsl:for-each>
                        </HEAD_ENTRIES>
                    </xsl:for-each>
                </HEAD>
            </data>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

验证结果

修正后的代码会生成与预期完全一致的XML输出,解决了原代码中路径选取错误导致的内容重复、关联节点匹配错误问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 06:24:50