首页 > 解决方案 > 通过匹配 XML 标签来复制内容

问题描述

我想通过匹配特定节点来复制 XML 的所有内容,并为每个重复的“postItemCost”节点添加一个 SOAP 信封。

源 XML:

    <ns1:postItemCost xmlns:ns1="http://items.test.com/">
      <ItemInvCostReqList>
        <ItemInvCostRequest>
          <invcost>
            <avgcost>0.00</avgcost>
            <lastcost>0.00</lastcost>
            <stdcost>0.00</stdcost>
          </invcost>
          <location>2201</location>
        </ItemInvCostRequest>
        <itemnum>9322979</itemnum>
      </ItemInvCostReqList>
    </ns1:postItemCost>

    <ns1:postItemCost xmlns:ns1="http://items.test.com/">
      <ItemInvCostReqList>
        <ItemInvCostRequest>
          <invcost>
            <avgcost>0.00</avgcost>
            <lastcost>0.00</lastcost>
            <stdcost>0.00</stdcost>
          </invcost>
          <location>1101</location>
        </ItemInvCostRequest>
        <itemnum>9322979</itemnum>
      </ItemInvCostReqList>
    </ns1:postItemCost>

    <ns1:postItemCost xmlns:ns1="http://items.test.com/">
      <ItemInvCostReqList>
        <ItemInvCostRequest>
          <invcost>
            <avgcost>1000.00</avgcost>
            <lastcost>1000.00</lastcost>
            <stdcost>1000.00</stdcost>
          </invcost>
          <location>1101</location>
        </ItemInvCostRequest>
        <itemnum>9322984</itemnum>
      </ItemInvCostReqList>
    </ns1:postItemCost>
  </ns0:Message1>
</ns0:Messages>

预期产出 -

<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
  <ns0:Message1>

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
    <ns1:postItemCost xmlns:ns1="http://items.test.com/">
      <ItemInvCostReqList>
        <ItemInvCostRequest>
          <invcost>
            <avgcost>0.00</avgcost>
            <lastcost>0.00</lastcost>
            <stdcost>0.00</stdcost>
          </invcost>
          <location>2201</location>
        </ItemInvCostRequest>
        <itemnum>9322979</itemnum>
      </ItemInvCostReqList>
    </ns1:postItemCost>
    </soapenv:Body>
    </soapenv:Envelope>

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
    <ns1:postItemCost xmlns:ns1="http://items.test.com/">
      <ItemInvCostReqList>
        <ItemInvCostRequest>
          <invcost>
            <avgcost>0.00</avgcost>
            <lastcost>0.00</lastcost>
            <stdcost>0.00</stdcost>
          </invcost>
          <location>1101</location>
        </ItemInvCostRequest>
        <itemnum>9322979</itemnum>
      </ItemInvCostReqList>
    </ns1:postItemCost>
    </soapenv:Body>
    </soapenv:Envelope>

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
    <ns1:postItemCost xmlns:ns1="http://items.test.com/">
      <ItemInvCostReqList>
        <ItemInvCostRequest>
          <invcost>
            <avgcost>1000.00</avgcost>
            <lastcost>1000.00</lastcost>
            <stdcost>1000.00</stdcost>
          </invcost>
          <location>1101</location>
        </ItemInvCostRequest>
        <itemnum>9322984</itemnum>
      </ItemInvCostReqList>
    </ns1:postItemCost>
    </soapenv:Body>
    </soapenv:Envelope>

这是我的 XSLT:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="w3.org/1999/XSL/Transform" xmlns:ns0="sap.com/xi/XI/SplitAndMerge" version="1.0">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="yes"/>
  <xsl:template match="/">
    <soapenv:Envelope xmlns:soapenv="schemas.xmlsoap.org/soap/envelope">
      <soapenv:Header/>
      <soapenv:Body>
        <xsl:template match="Message//Message1//postInvCostRequest">
          <xsl:copy-of select="/postInvCostRequest"/>
        </xsl:template>
      </soapenv:Body>
    </soapenv:Envelope>
  </xsl:template>
</xsl:stylesheet>

我想为每个重复的“postItemCost”节点添加 SOAP 信封。
那么,您能否帮助我提供可以帮助我实现预期输出的 XSLT 代码。

标签: xmlxsltxslt-1.0

解决方案


试试这个方法?

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge"
xmlns:ns1="http://items.test.com/">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/ns0:Messages">
    <xsl:copy>
        <ns0:Message1>
            <xsl:for-each select="ns0:Message1/ns1:postItemCost">
                <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                    <soapenv:Header/>
                    <soapenv:Body>
                        <xsl:copy-of select="."/>
                    </soapenv:Body>
                </soapenv:Envelope>
            </xsl:for-each>
        </ns0:Message1>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

演示:http: //xsltransform.net/jxWYjVU


添加:

如评论中所述,您无法控制名称空间声明的出现位置。以下技巧将适用于某些处理器并强制xmlns:ns1="http://items.test.com/"声明出现在 ns1:postItemCost元素上 - 但不能保证它适用于处理链的每个处理器或序列化组件:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge"
xmlns:ns3="http://items.test.com/"
exclude-result-prefixes="ns3">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/ns0:Messages">
    <xsl:copy>
        <ns0:Message1>
            <xsl:for-each select="ns0:Message1/ns3:postItemCost">
                <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                    <soapenv:Header/>
                    <soapenv:Body>
                        <xsl:copy-of select="."/>
                    </soapenv:Body>
                </soapenv:Envelope>
            </xsl:for-each>
        </ns0:Message1>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

推荐阅读