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

XSLT copy-of如何以当前节点值为动态条件匹配目标节点

问题背景
  • 给定如下源XML:
<?xml version="1.0" encoding="utf-8"?>
<multimap:Messages xmlns:multimap="http://sap.com/xi/XI/SplitAndMerge">
    <multimap:Message1>
        <INVOIC02>
            <E1EDP19>
                <QUALF>003</QUALF>
                <IDTNR>105</IDTNR>
                <KTEXT>TEST-1</KTEXT>
            </E1EDP19>
            <E1EDP19>
                <QUALF>003</QUALF>
                <IDTNR>104</IDTNR>
                <KTEXT>TEST-2</KTEXT>
            </E1EDP19>
        </INVOIC02>
    </multimap:Message1>
    <multimap:Message2>
        <Message2>
            <ZZ1_Result>
                <Material>M1</Material>
                <ProductStandardID>104</ProductStandardID>
                <PurchaseOrder>1A</PurchaseOrder>
                <Supplier>AA</Supplier>
            </ZZ1_Result>
            <ZZ1_Result>
                <Material>M2</Material>
                <ProductStandardID>105</ProductStandardID>
                <PurchaseOrder>1B</PurchaseOrder>
                <Supplier>BB</Supplier>
            </ZZ1_Result>
        </Message2>
    </multimap:Message2>
</multimap:Messages>
  • 需求:为每个E1EDP19/IDTNR节点匹配对应的ZZ1_Result节点,匹配规则为ZZ1_Result/ProductStandardID的取值与E1EDP19/IDTNR的取值相等。
  • 现有硬编码实现的XSLT代码如下:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn:sap-com:document:sap:idoc:soap:messages">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <!-- Only match root of IDoc FIDCCP02 -->
    <xsl:template match="document-node()">
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <!-- Select all nodes plus attributes -->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <!--At E1EDP19(QUALF=003) segment, field IDTNR, try to find a matching PO item from message 2-->
    <xsl:template match="E1EDP19[QUALF='003']/IDTNR">
        <IDTNR>
            <xsl:value-of select="."/>
        </IDTNR>
        <xsl:copy-of copy-namespaces="no" select="//ZZ1_Result[ProductStandardID = '104']"/>
    </xsl:template>
</xsl:stylesheet>
  • 硬编码版本运行后,所有IDTNR节点后都固定插入ProductStandardID为104的ZZ1_Result,不符合动态匹配要求,错误运行结果如下:
<?xml version='1.0' encoding='UTF-8' ?>
<Messages xmlns="urn:sap-com:document:sap:idoc:soap:messages">
  <Message1>
    <INVOIC02>
      <E1EDP19>
        <QUALF>003</QUALF>
        <IDTNR>105</IDTNR>
        <ZZ1_Result>
          <Material>M1</Material>
          <ProductStandardID>104</ProductStandardID>
          <PurchaseOrder>1A</PurchaseOrder>
          <Supplier>AA</Supplier>
        </ZZ1_Result>
        <KTEXT>TEST-1</KTEXT>
      </E1EDP19>
      <E1EDP19>
        <QUALF>003</QUALF>
        <IDTNR>104</IDTNR>
        <ZZ1_Result>
          <Material>M1</Material>
          <ProductStandardID>104</ProductStandardID>
          <PurchaseOrder>1A</PurchaseOrder>
          <Supplier>AA</Supplier>
        </ZZ1_Result>
        <KTEXT>TEST-2</KTEXT>
      </E1EDP19>
    </INVOIC02>
  </Message1>
  <Message2>
    <Message2>
      <ZZ1_Result>
        <Material>M1</Material>
        <ProductStandardID>104</ProductStandardID>
        <PurchaseOrder>1A</PurchaseOrder>
        <Supplier>AA</Supplier>
      </ZZ1_Result>
      <ZZ1_Result>
        <Material>M2</Material>
        <ProductStandardID>105</ProductStandardID>
        <PurchaseOrder>1B</PurchaseOrder>
        <Supplier>BB</Supplier>
      </ZZ1_Result>
    </Message2>
  </Message2>
</Messages>
  • 需要修改的目标代码行如下,要求替换硬编码的'104'为当前上下文IDTNR的动态值:
<xsl:copy-of copy-namespaces="no" select="//ZZ1_Result[ProductStandardID = '104']" />
  • 预期运行结果:
<?xml version='1.0' encoding='UTF-8' ?>
<Messages xmlns="urn:sap-com:document:sap:idoc:soap:messages">
  <Message1>
    <INVOIC02>
      <E1EDP19>
        <QUALF>003</QUALF>
        <IDTNR>105</IDTNR>
        <ZZ1_Result>
          <Material>M2</Material>
          <ProductStandardID>105</ProductStandardID>
          <PurchaseOrder>1B</PurchaseOrder>
          <Supplier>BB</Supplier>
        </ZZ1_Result>
        <KTEXT>TEST-1</KTEXT>
      </E1EDP19>
      <E1EDP19>
        <QUALF>003</QUALF>
        <IDTNR>104</IDTNR>
        <ZZ1_Result>
          <Material>M1</Material>
          <ProductStandardID>104</ProductStandardID>
          <PurchaseOrder>1A</PurchaseOrder>
          <Supplier>AA</Supplier>
        </ZZ1_Result>
        <KTEXT>TEST-2</KTEXT>
      </E1EDP19>
    </INVOIC02>
  </Message1>
  <Message2>
    <Message2>
      <ZZ1_Result>
        <Material>M1</Material>
        <ProductStandardID>104</ProductStandardID>
        <PurchaseOrder>1A</PurchaseOrder>
        <Supplier>AA</Supplier>
      </ZZ1_Result>
      <ZZ1_Result>
        <Material>M2</Material>
        <ProductStandardID>105</ProductStandardID>
        <PurchaseOrder>1B</PurchaseOrder>
        <Supplier>BB</Supplier>
      </ZZ1_Result>
    </Message2>
  </Message2>
</Messages>
解决方案

替换动态值不生效的核心原因是XPath的作用域规则:

  • 方括号谓词内的.,指代的是当前正在被筛选的节点(即此处的ZZ1_Result节点),而非模板匹配到的IDTNR上下文节点。如果直接把硬编码的'104'替换为.,判断逻辑会变成「ProductStandardID取值等于ZZ1_Result节点自身的字符串值」,自然无法得到正确匹配结果。
  • 要获取当前模板匹配到的IDTNR节点值,需要使用XSLT内置的current()函数,该函数始终返回当前模板规则绑定的上下文节点,不受XPath谓词内作用域影响。

修改方法

将目标代码行替换为以下内容即可:

<xsl:copy-of copy-namespaces="no" select="//ZZ1_Result[ProductStandardID = current()]" />

XSLT在做节点值比较时会自动提取节点的字符串值做对比,无需额外调用text()或string()函数取值,直接写current()即可匹配IDTNR节点内的文本值。

修改后运行即可得到预期结果:IDTNR为105时匹配ProductStandardID为105的ZZ1_Result,IDTNR为104时匹配ProductStandardID为104的ZZ1_Result。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 04:39:43