使用XSLT将NameSpaces替换为另一个

时间:2013-12-26 09:33:20

标签: xslt

我有一个XML输入文件,我在其中获得了一些名称空间,我想用另一个使用XSLT替换它们。其实我是新的XSLT,所以无法找到合适的解决方案。下面是我想要的XML输入有效负载和输出有效负载。任何人都可以帮助我。

输入有效负载:

<ns:createOrderResponse xmlns:ns="http://services.oms.ecom.ecc.com"><ns:return type="com.ecc.ecom.oms.beans.xsd.CreateOrderResponse"><ns:omsGeneratedOrderId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" /><ns:responseCode>99</ns:responseCode><ns:responseDesc>INVALID ORDER</ns:responseDesc><ns:sellerSiteId>10196</ns:sellerSiteId><ns:serverProcElapsedTime>8</ns:serverProcElapsedTime><ns:siteGeneratedOrderId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" /><ns:subResponse><responseCode xmlns="http://beans.oms.ecom.ecc.com/xsd">1144</responseCode><responseDescription xmlns="http://beans.oms.ecom.ecc.com/xsd">Order Total mismatch</responseDescription></ns:subResponse><ns:subResponse><responseCode xmlns="http://beans.oms.ecom.ecc.com/xsd">1147</responseCode><responseDescription xmlns="http://beans.oms.ecom.ecc.com/xsd">Order Grand Total and sum of OrderItem Grand Total mismatch</responseDescription></ns:subResponse><ns:transactionNumber>0717299145</ns:transactionNumber></ns:return></ns:createOrderResponse>

期望的输出:

<ns:createOrderResponse xmlns:ns="http://services.oms.ecom.ecc.com"><ns:return type="com.ecc.ecom.oms.beans.xsd.CreateOrderResponse"><ns:omsGeneratedOrderId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" /><ns:responseCode>99</ns:responseCode><ns:responseDesc>INVALID ORDER</ns:responseDesc><ns:sellerSiteId>10196</ns:sellerSiteId><ns:serverProcElapsedTime>8</ns:serverProcElapsedTime><ns:siteGeneratedOrderId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" /><ns:subResponse><responseCode xmlns="http://services.oms.ecom.ecc.com">1144</responseCode><responseDescription xmlns="http://services.oms.ecom.ecc.com">Order Total mismatch</responseDescription></ns:subResponse><ns:subResponse><responseCode xmlns="http://services.oms.ecom.ecc.com">1147</responseCode><responseDescription xmlns="http://services.oms.ecom.ecc.com">Order Grand Total and sum of OrderItem Grand Total mismatch</responseDescription></ns:subResponse><ns:transactionNumber>0717299145</ns:transactionNumber></ns:return></ns:createOrderResponse>

基本上我想替换:

命名空间:http://beans.oms.ecom.shc.com/xsd 从 命名空间:http://services.oms.ecom.ecc.com

1 个答案:

答案 0 :(得分:0)

CAVEAT:以下是未经测试但展示了这些想法。

如果您知道要期望哪些特定元素和属性,则相对容易 - 它与任何其他元素和属性相同“当您看到此元素时,输出此其他元素而不是”模板,递归以覆盖整个文档。从身份样式表开始,添加表单的相应模板:

<xsl:template match="wrongnamespace:fred"
      xmlns:wrongnamespace="http://services.oms.ecom.ecc.com">
  <rightnamespace:fred xmlns:rightnamespace="http://beans.oms.ecom.shc.com/xsd">
      <xsl:apply-templates/>
  </rightnamespace:fred>
</xsl:template>

和(对于属性)

<xsl:template match="@wrongnamespace:george"
      xmlns:wrongnamespace="http://services.oms.ecom.ecc.com">
   <xsl:attribute name="ns:george" value="."
          namespace="http://beans.oms.ecom.shc.com/xsd"/>
</xsl:template>

......等等。

如果你不知道期望什么元素或属性,这就变得更加丑陋。在XSLT 1.0和XPath 1.0中,没有简单的方法可以说“任何元素节点”(尽管我认为这些在这些规范的2.0版本中得到了修复)。坚持使用1.0因为它得到了更广泛的支持,最简单的解决方案是使用优先级:拥有一个捕获属性的优先级较高的模板,然后使用另一个处理其他命名空间节点的模板(因此它们就是元素)。

<xsl:template match="@*[namespace-uri(.)="http://services.oms.ecom.ecc.com"
        priority="1">
    <xsl:attribute name="concat('ns:',localname(.))" value="."
            namespace="http://beans.oms.ecom.shc.com/xsd"/>
</xsl:template>

<xsl:template match="node()[namespace-uri(.)="http://services.oms.ecom.ecc.com"
           priority="1">
       <xsl:element name="concat('ns:',localname(.))"
              namespace="http://beans.oms.ecom.shc.com/xsd">
           <xsl:apply-templates/>
       </xsl:element>
</xsl:template>

再次,将这些添加到规范标识样式表将满足您的需求;它会捕捉并改变这两种情况,同时复制其他所有内容。

CAVEAT:这不会改变出现在字符串中的URIS。您可以添加一个模板,该模板查找包含旧URI的text()节点并输出新的URI;我将这作为读者的练习。

CAVEAT:这不会改变NAMESPACE NODES。您最终可能会使用旧前缀和命名空间的剩余声明。可以添加另一个模板来清理它;这也是留给读者的练习。

这应该足以让你开始。玩得开心。在XSLT中编程确实需要学习思考规则和替换而不是程序,但是当你习惯它时,它可以是一个非常富有表现力的工具。

(标准插件:如果你想要一个现成的测试解决方案,你可以在Dave Pawson的XSL FAQ网站上找到一个。如果在XSLT中工作,你真的需要注意这个资源;它会节省你做了很多工作,它有一些非常聪明且非常明显的解决方案。)