使用xslt复制除匹配元素根名称之外的所有xml元素

时间:2015-08-12 17:28:11

标签: xml xslt xslt-1.0 transformation xml-namespaces

输入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)。并且匹配元素节点内的所有元素都应该复制到更改的元素名称下。

即复制everthing并更改元素节点名称。

1 个答案:

答案 0 :(得分:0)

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

然后您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>