使用 xslt 复制除匹配元素根名称之外的所有 xml 元素 [英] Copy all xml elements excluding matched element root name using xslt

查看:32
本文介绍了使用 xslt 复制除匹配元素根名称之外的所有 xml 元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

输入 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 作为:

using XSLT as:

    <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 为:

and expecting output XML as :

<?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).并将匹配元素节点内的所有元素复制到更改后的元素名称下.

================= I am expecting the xml as shown above where matched element name(purchaseOrder) should be replaced with some other name(someOtherPurchaseOrder). and all the elements inside that matched element node should be copy to under changed element name.

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

i.e copy everthing and change the element node name.

推荐答案

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

In your template that matches purchaseOrder you create a new element, which is what you require, but you also do xsl:copy which will copy the existing purchaseOrder element, which is not what you require, so you can remove the xsl:copy here.

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

然后您执行 xsl:apply-templates 来选择子项,这很好,但是您的 XSLT 中没有任何其他模板来匹配它们.这意味着将应用 XSLT 的内置模板,并且所有这些只会输出文本,而不是任何元素本身.

You then do xsl:apply-templates to select the children, which is good, but you don't have any other templates in your XSLT to match them. This means XSLT's built-in templates will apply, and all these will do is output the text, but not any elements themselves.

您可以通过将身份模板添加到您的 XSLT

You can solve this by adding the identity template to your XSLT

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

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

This, however, will copy the root VendorMessageRequest element too, so you would need to add a template to skip over that.

试试这个 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....

In response to your comments, if you are getting an unused namespace declaration still present in your output, try this XSLT instead....

<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>

这篇关于使用 xslt 复制除匹配元素根名称之外的所有 xml 元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆