XML:一个命名空间前缀被声明为未声明,而事实上它是

Posted

技术标签:

【中文标题】XML:一个命名空间前缀被声明为未声明,而事实上它是【英文标题】:XML: A namespace prefix is claimed to be not declared when it fact it is 【发布时间】:2011-01-09 14:47:11 【问题描述】:

我们有一个 Web 服务,它返回一个非常简单的 XML。

<?xml version="1.0"?>
<t:RequestResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://our.website.com/ns/" xmlns:t="http://our.website.com/ns/">
  <t:Result>No candy for you today.</t:Result>
  <t:Success>false</t:Success>
</t:RequestResult>

调用者得到这个 XML 没有问题,使用 XMLHTTP。 但是由于 "Reference to undeclared namespace prefix: 't'"

,XPath 查询对这个 XML 不起作用

为什么会这样?我想说't'前缀有点声明。 该文件是否无效?

如果您想知道为什么我们必须首先使用use XmlNamespaceDeclarations to add namespace prefixes,那是因为否则无法查询结果文档,因为它具有目标名称空间但没有前缀,因此 XPath 忽略节点名称,因为它们不属于请求的(空)命名空间,并且我们不想使用像 "//*[namespace-uri()='http://our.website.com/ns' and local-name()='RequestResult']" 这样的结构。

【问题讨论】:

【参考方案1】:

您已经回答了这个问题,但值得理解为什么会这样。

元素所在的命名空间不能仅由命名空间前缀确定。要查找名为 t:foo 的元素所在的命名空间,您必须向上搜索祖先或自我轴,直到找到定义 t: 命名空间的最近节点。例如:

<t:one xmlns:t="ns-one">
   <t:one>
      <t:two xmlns:t="ns-two">
         <t:two/>
      </t:two>
   </t:one>
</t:one>

在该文档中,名称为one 的每个元素都在ns-one 命名空间中,而名称为two 的每个元素都在ns-two 命名空间中。您可以看出该文档中最深的元素在ns-two 中,这并不是因为t: 本质上意味着ns-two,而是因为如果您搜索祖先或自我轴,您使用@987654331 击中的第一个元素@ 属性 - 它的父级 - 告诉你命名空间。

鉴于此,XPath 表达式//t:* 应该匹配哪些节点?无法说清楚,因为t: 映射到整个文档的变化是什么命名空间。

此外,命名空间前缀是临时的,但命名空间是永久的。如果你知道onens-one 中,你真的,真的不在乎它的前缀是t: 还是x:,或者它根本没有前缀,只有一个xmlns 属性。

当您使用 XPath 查询 XML 文档时,您需要一种方法来指定给定元素所在的命名空间。这就是 DOMDocument 中的 SelectionNamespaces 或 C# 中的命名空间管理器,或其他用途:它们告诉您 XPath 查询中的前缀代表什么名称空间。因此,如果我将前缀 a: 设置为 ns-one,XPath //a:one 将在 ns-one 命名空间中找到所有名为 one 的元素,而不管它们使用的实际前缀是什么我正在搜索的文档是。

当您第一次学习它时,这有点违反直觉,但实际上,这是唯一有意义的方法。

【讨论】:

我想将此作为可接受的答案。但它只是指实际的答案,所以,为了以后读者的方便,您能否将我的答案合并到您的答案中,以便我可以将其作为一个整体来接受?【参考方案2】:

令人惊讶的是(对我来说),这是 XPath 的默认行为。默认情况下,XPath 查询中不允许使用命名空间前缀。

要解决此问题,必须使用 DOMObject 的 SelectionNamespaces 属性注册所需的前缀。

objXML.setProperty("SelectionNamespaces", "xmlns:t='http://our.website.com/ns/'")

之后,可以在 XPath 查询中使用带有t: 限定的表达式。 这也解决了最初迫使我们使用 XmlNamespaceDeclarations 的原始问题。

【讨论】:

以上是关于XML:一个命名空间前缀被声明为未声明,而事实上它是的主要内容,如果未能解决你的问题,请参考以下文章

基于多部分 xml 根声明创建具有命名空间前缀的元素

XML 和 XSL 中的前缀命名空间处理由 XML 解析器返回错误

Open Graph 命名空间声明:带有 XMLNS 或 head 前缀的 HTML?

如果命名空间声明在 SOAP 信封上,如何使用 JAXB 解组 SOAP 响应?

『XML』XML/XSD命名空间解析

默认情况下声明了哪些 XML 命名空间?