使用 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>
输入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>