使用 xslt 复制所有 xml 元素,不包括匹配的元素根名称

Copy all xml elements excluding matched element root name using xslt

输入XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:VendorMessageRequest xmlns:ns2="http://order.com.company.com">
<ns2:purchaseOrder>     
<assignedTo>   
    <firstName>firstnm</firstName>
    <lastName>lstnm</lastName>
</assignedTo>
</ns2:purchaseOrder>
</ns2:VendorMessageRequest>

将 XSLT 用作:

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ns2="http://www.company.com/services/entity/v1"
                xmlns:ns3="http://www.company.com/services/dataobject/v1"
                 xmlns:ns4="http://order.com.company.com">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="ns4:purchaseOrder">
       <xsl:element name="ns3:someOtherPurchaseOrder" >
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                 </xsl:copy>
       </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出为:

<?xml version="1.0" encoding="UTF-8"?>
<ns3:someOtherPurchaseOrder xmlns:ns3="http://www.company.com/services/dataobject/v1">
<ns2:purchaseOrder xmlns:ns2="http://order.com.company.com">
firstnmlstn</ns2:purchaseOrder>
</ns3:someOtherPurchaseOrder>

并期望输出 XML 为:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:someOtherPurchaseOrder xmlns:ns2="http://www.company.com/services/dataobject/v1">
  <assignedTo>
      <firstName>firstnm</firstName>
      <lastName>lstnm</lastName>
    </assignedTo>
</ns2:someOtherPurchaseOrder>

================= 我期待如上所示的 xml,其中匹配的元素名称 (purchaseOrder) 应该替换为其他名称 (someOtherPurchaseOrder)。并且该匹配元素节点内的所有元素都应复制到更改后的元素名称下。

即复制所有内容并更改元素节点名称。

在匹配 purchaseOrder 的模板中,您创建了一个新元素,这是您所需要的,但您还执行了 xsl:copy,这将复制现有的 purchaseOrder 元素,即不是您需要的,因此您可以在此处删除 xsl:copy

<xsl:template match="ns4:purchaseOrder">
   <xsl:element name="ns3:someOtherPurchaseOrder" >
        <xsl:apply-templates select="@*|node()"/>
   </xsl:element>
</xsl:template>

然后您对 select 子项执行 xsl:apply-templates,这很好,但是您的 XSLT 中没有任何其他模板可以匹配它们。这意味着将应用 XSLT 的内置模板,所有这些都将输出文本,而不是任何元素本身。

您可以通过将 identity template 添加到您的 XSLT

来解决这个问题
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

但是,这也会复制根 VendorMessageRequest 元素,因此您需要添加一个模板来跳过它。

试试这个 XSLT

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ns2="http://www.company.com/services/entity/v1"
                xmlns:ns3="http://www.company.com/services/dataobject/v1"
                 xmlns:ns4="http://order.com.company.com"
                 exclude-result-prefixes="ns2 ns4">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ns4:VendorMessageRequest">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="ns4:purchaseOrder">
       <xsl:element name="ns3:someOtherPurchaseOrder" >
            <xsl:apply-templates select="@*|node()"/>
       </xsl:element>
    </xsl:template>
</xsl:stylesheet>

编辑:针对您的评论,如果您的输出中仍然存在未使用的名称空间声明,请尝试使用此 XSLT...

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ns2="http://www.company.com/services/entity/v1"
                xmlns:ns3="http://www.company.com/services/dataobject/v1"
                 xmlns:ns4="http://order.com.company.com"
                 exclude-result-prefixes="ns2 ns4">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*|node()[not(self::*)]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ns4:VendorMessageRequest">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="ns4:purchaseOrder">
       <xsl:element name="ns3:someOtherPurchaseOrder" >
            <xsl:apply-templates select="@*|node()"/>
       </xsl:element>
    </xsl:template>
</xsl:stylesheet>