这个一直困扰着我。我现在已经做了一些测试,所以希望我可以帮助你。
这是来自微软的源码,这是问题的关键
重要的段落在这里:
XPath 将空前缀视为空名称空间。换句话说,只有映射到命名空间的前缀才能在 XPath 查询中使用。这意味着如果您要查询 XML 文档中的命名空间,即使它是默认命名空间,也需要为其定义前缀。
本质上,您必须记住 XPath 解析器使用命名空间 URI - 前缀可互换的设计。就是这样,在编程时,您可以分配我们想要的任何前缀 - 只要 URI 匹配。
为了清楚起见,示例:
示例 A:
<data xmlns:nsa="http://example.com/ns"><nsa:a>World</nsa:a></data>
这有一个 NULL 默认 URI(xmlns=
未定义)。因此/data/nsa:a
返回“世界”。
示例 B:
<data xmlns:nsa="http://example.com/ns" xmlns="https://standardns/"><nsa:a>World</nsa:a></data>
该文档有一个命名的默认前缀https://standardns/
。XPathNavigator.Execute
因此不/data/nsa:a
返回任何结果。MS 认为 XML命名空间 uridata
应该为 NULL,而命名空间 URI实际上data
是“https://standardns/”。本质上,XPath 正在寻找/NULL:data/nsa:a
- 尽管这不起作用,因为您不能将 NULL URI 称为“NULL”作为前缀。NULL 前缀是所有 XPath 中的默认值 - 因此是问题所在。
我们如何解决这个问题?
XmlNamespaceManager result = new XmlNamespaceManager(xDoc.NameTable);
result.AddNamespace("DEFAULT", "https://standardns/");
result.AddNamespace("nsa", "http://example.com/ns");
这样,我们现在可以将 a 称为/DEFAULT:data/nsa:a
示例 C:
<data><a xmlns="https://standardns/">World</a></data>
在这个例子data
中是在 NULL 命名空间中。a
位于默认命名空间“https://standardns/”中。/data/a
根据微软的说法,它应该不起作用,因为a
它在 NS中https://standardns/
并且data
在命名空间 NULL 中。<a>
因此被隐藏(除非通过奇怪的“忽略名称空间”黑客)并且不能按原样选择。这本质上是根本原因——你不应该选择没有前缀的“a”和“data”,因为这会假设它们在同一个命名空间中,而它们不是!
我们如何解决这个问题?
XmlNamespaceManager result = new XmlNamespaceManager(xDoc.NameTable);
result.AddNamespace("DEFAULT", "https://standardns/");
这样,我们现在可以将 a 称为/data/DEFAULT:a
as,因为数据是从 NULL 命名空间中选择的,而 a 是从新前缀“DEFAULT”中选择的。在这个例子中重要的是命名空间前缀不需要保持不变。在您的代码中引用具有不同前缀的 URI 命名空间是完全可以接受的,这与您正在处理的文档中所写的内容有关。
希望这可以帮助一些人!