XML:声称名称空间前缀在事实上未声明

GSe*_*erg 3 xml asp.net xpath namespaces .net-3.5

我们有一个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>
Run Code Online (Sandbox Code Playgroud)

调用者使用XMLHTTP获取此XML没问题.但是,由于"引用未声明的命名空间前缀:'t',因此XPath查询不会再次使用此XML

为什么这样?我会说't'前缀有点声明. 该文件是否以任何方式无效?

如果你想知道我们为什么必须首先使用XmlNamespaceDeclarations添加名称空间前缀,那是因为否则生成的文档会被查询,因为它有一个目标名称空间但没有前缀,所以XPath忽略节点名称,因为它们不属于请求的(空)命名空间,我们不想使用像这样的结构"//*[namespace-uri()='http://our.website.com/ns' and local-name()='RequestResult']".

Rob*_*ney 7

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

元素所在的命名空间不能仅由命名空间前缀确定.要查找命名元素所在的命名空间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>
Run Code Online (Sandbox Code Playgroud)

在该文档中,名称所在的每个元素one都在ns-one命名空间中,而名称所在的每个元素two都在ns-two命名空间中.您可以告诉该文档中最深的元素ns-two不是因为t:本质上意味着ns-two,但是因为如果您搜索祖先或自我轴,您使用其xmlns:t上的属性命中的第一个元素- 它的父元素- 会告诉您命名空间.

鉴于此,XPath表达式应//t:*匹配哪些节点?这是不可能的,因为什么命名空间t:映射到整个文档的变化.

此外,名称空间前缀是临时的,但名称空间是永久性的.如果你知道它onens-one,你真的,真的不关心它的前缀是否t:或者x:它根本没有前缀而只是一个xmlns属性.

当您使用XPath查询XML文档时,您需要一种方法来指定给定元素所在的命名空间.这就是SelectionNamespacesDOMDocument中的内容,或C#中的命名空间管理器,或者其他适用的内容:它们告诉您什么名称空间XPath查询中的前缀表示.所以,如果我设置前缀a:ns-one这个XPath //a:one会发现我所有命名元素onens-one命名空间,不论他们是怎么使用我搜索文档中的实际前缀.

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