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