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:
映射到整个文档的变化是什么命名空间。
此外,命名空间前缀是临时的,但命名空间是永久的。如果你知道one
在ns-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 和 XSL 中的前缀命名空间处理由 XML 解析器返回错误
Open Graph 命名空间声明:带有 XMLNS 或 head 前缀的 HTML?