Copy all xml elements excluding matched element root name using xslt

你离开我真会死。 提交于 2019-12-13 19:24:27

问题


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

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>

Output coming as:

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

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>

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


回答1:


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>

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.

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>

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

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

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


来源:https://stackoverflow.com/questions/31971750/copy-all-xml-elements-excluding-matched-element-root-name-using-xslt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!