执行查询后如何修复附加名称空间属性?

时间:2019-04-24 23:43:24

标签: xml xpath xquery

我有以下xml文件。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:ns="http://example.com/ns">
  <soapenv:Header xmlns:ns1="http://www.ns1.com"/>
   <soapenv:Body>
     <ns:request>
      <ns:customer>
       <ns:id>123</ns:id>
       <ns:name type="NCHZ">John Brown</ns:name>
      </ns:customer>
     </ns:request>
   </soapenv:Body>
</soapenv:Envelope>

当我使用以下 xquery / xpath 获得<ns:request>元素时。

declare namespace soapenv="http://schemas.xmlsoap.org/soap/envelope/"; declare namespace ns="http://example.com/ns"; //soapenv:Envelope/soapenv:Body/ns:request

结果将是

<ns:request xmlns:ns="http://example.com/ns" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <ns:customer>
        <ns:id>123</ns:id>
        <ns:name type="NCHZ">John Brown</ns:name>
    </ns:customer>
</ns:request>

为什么在xmlns:ns="http://example.com/ns" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"元素中添加了<ns:request>属性,尽管该属性在主xml文件中不存在?以及如何解决?

2 个答案:

答案 0 :(得分:1)

您需要了解名称空间在XDM数据模型中的工作方式。每个元素节点都有一组范围内的命名空间(prefix-uri)绑定,这些绑定是通过查看祖先元素中的所有命名空间声明而获得的。当元素节点被序列化时,所有作用域内的名称空间都被序列化为名称空间声明属性,因为处理器不知道它们中的哪些是必需的。

在您的情况下,需要一个名称空间(ns)(因为它在元素名称中使用),而另一个则不需要(在任何地方都没有使用)。

在XSLT(2.0+)中,可以使用<xsl:copy>copy-namespaces='no'来摆脱未使用的名称空间。但是XPath始终为您提供输入节点不变:因此,如果元素在输入中具有两个作用域内的命名空间,则它在输出中仍将具有两个作用域内的命名空间,当元素被序列化时,这些可见。 >

答案 1 :(得分:1)

您可以通过使用xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"和XQuery中的文档构造函数来摆脱范围内但未使用的命名空间declare copy-namespaces no-preserve,例如

declare copy-namespaces no-preserve, no-inherit;

declare namespace soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
declare namespace ns="http://example.com/ns"; 

document {
//soapenv:Envelope/soapenv:Body/ns:request
}

https://xqueryfiddle.liberty-development.net/gWcDMes

这样,结果将是

<ns:request xmlns:ns="http://example.com/ns">
  <ns:customer>
   <ns:id>123</ns:id>
   <ns:name type="NCHZ">John Brown</ns:name>
  </ns:customer>
 </ns:request>