2

我有一个这样的 xml 字符串:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <ExecuteResponse xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
      <ExecuteResult i:type="a:RetrieveEntityResponse" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:ResponseName>RetrieveEntity</a:ResponseName>
        <a:Results xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
          <a:KeyValuePairOfstringanyType>
            <b:key>Some Value</b:key>
          </a:KeyValuePairOfstringanyType>
        </a:Results>
      </ExecuteResult>
    </ExecuteResponse>
  </s:Body>
</s:Envelope>

我正在尝试按照以下方式做一些事情:

var resolver = xmlDoc.createNSResolver(xmlDoc.documentElement);
return new XPathEvaluator().evaluate("//b:key", xmlDoc.documentElement, resolver, XPathResult.ANY_TYPE, null);

没有找到关键节点,原因是我调用的时候

resolver.lookupNamespaceURI("b")

直接返回null。但是,当我这样做时它确实返回了一些东西

resolver.lookupNamespaceURI("s")

所以我最好的猜测是 createNSResolver 方法只在传入的 xml 文档的根节点中查找命名空间。有没有办法让它找到在 xml 中定义的所有命名空间,或者其他方式来构建文档中存在的所有命名空间的列表?

谢谢!

4

1 回答 1

3

在一般情况下,根据 XML 文档中的所有命名空间声明设置一致的命名空间解析是不可能的,因为您可能拥有例如

<root xmlns="http://example.com/n1">
  <foo xmlns="http://example.com/n2">
   <p1:bar xmlns:p1="http://example.com/n1">
    <p2:baz xmlns:p2="http://example.com/n1">...</p2:baz>
   </p1:bar>
  </foo>
</root>

其中相同的命名空间与不同的前缀一起使用,当然你可以有示例,例如

<p:foo xmlns:p="http://example.com/n1">
  <p:bar xmlns:p="http://example.com/n2">...</p:bar>
</p:foo>

其中相同的前缀绑定到不同元素上的不同命名空间 URI。

所以基本上你需要知道你正在寻找的元素节点的命名空间URI,然后你可以使用你的代码可以选择的任何前缀设置一个命名空间解析器,例如

return xmlDoc.evaluate("//pf:key", xmlDoc, function(prefix) { if (prefix === 'pf' return 'http://schemas.datacontract.org/2004/07/System.Collections.Generic'; else return null; }, XPathResult.ANY_TYPE, null);

另一方面,对于那条简单的路径,我根本不会使用 XPath,evaluate而是选择return xmlDoc.getElementsByTagNameNS('http://schemas.datacontract.org/2004/07/System.Collections.Generic', 'b');.

至于在 DOM 树中查找名称空间声明以根据前缀自己构建名称空间解析器,XPath 可以通过查看名称空间轴来提供一些帮助,例如//namespace::*,但在浏览器内部,Mozilla/Firefox 从未认为有必要支持名称空间轴。然后是一些 DOM Level 3 方法http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefixhttp://www.w3.org/TR/DOM- Level-3-Core/core.html#Node3-lookupNamespaceURI这样您就可以编写自己的代码遍历 DOM 树并收集命名空间声明,但这在一般情况下无助于解决我在上面发布的两个示例示例中概述的问题.

于 2012-06-14T09:46:57.580 回答