我已经有点干到why年了——至少在future 几年是这样.Net框架——在执行XPath查询时,有必要使用XmlNamespaceManager来处理名称空间(或相当笨拙和冗长的[local-name()=... XPath谓词/函数/任何东西).我理解为什么名称空间是必要的,或者至少是有益的,但它这么复杂吗?

为了查询简单的XML文档(没有名称空间).

<?xml version="1.0" encoding="ISO-8859-1"?>
<rootNode>
   <nodeName>Some Text Here</nodeName>
</rootNode>

.可以使用类似于doc.SelectSingleNode("//nodeName")的值(这将与<nodeName>Some Text Here</nodeName>匹配)

Mystery #1:My first annoyance——如果我理解正确的话——这仅仅是向父/根标记(无论是否用作子 node 标记的一部分)添加名称空间引用,如下所示:

<?xml version="1.0" encoding="ISO-8859-1"?>
<rootNode xmlns="http://example.com/xmlns/foo">
   <nodeName>Some Text Here</nodeName>
</rootNode>

...需要多行代码才能获得相同的结果:

Dim nsmgr As New XmlNamespaceManager(doc.NameTable)
nsmgr.AddNamespace("ab", "http://example.com/xmlns/foo")
Dim desiredNode As XmlNode = doc.SelectSingleNode("//ab:nodeName", nsmgr)

...本质上是虚构一个不存在的前缀("ab")来找到一个甚至不使用前缀的 node .How does this make sense? doc.SelectSingleNode("//nodeName")在概念上有什么问题?

Mystery #2:假设您有一个使用前缀的XML文档:

<?xml version="1.0" encoding="ISO-8859-1"?>
<rootNode xmlns:cde="http://example.com/xmlns/foo" xmlns:feg="http://example.com/xmlns/bar">
   <cde:nodeName>Some Text Here</cde:nodeName>
   <feg:nodeName>Some Other Value</feg:nodeName>
   <feg:otherName>Yet Another Value</feg:otherName>
</rootNode>

...如果我理解正确的话,您必须将两个名称空间都添加到XmlNamespaceManager,才能查询单个 node ……

Dim nsmgr As New XmlNamespaceManager(doc.NameTable)
nsmgr.AddNamespace("cde", "http://example.com/xmlns/foo")
nsmgr.AddNamespace("feg", "http://example.com/xmlns/bar")
Dim desiredNode As XmlNode = doc.SelectSingleNode("//feg:nodeName", nsmgr)

...在这种情况下,为什么(在概念上)我需要一个名称空间管理器?

******编辑成下面的 comments ****

Edit Added:个 我修改和改进的问题基于XmlNamespaceManager在我认为大多数情况下的明显冗余,以及使用命名空间管理器指定前缀到URI的映射:

当名称空间前缀("cde")到名称空间URI("http://example.com/xmlns/foo")的直接映射在源文档中明确说明时:

...<rootNode xmlns:cde="http://example.com/xmlns/foo"...

程序员在进行查询之前重新创建该映射的概念性需求是什么?

推荐答案

基本要点(如Kev, above所指出的)是,名称空间URI是名称空间的重要组成部分,而不是名称空间前缀,前缀是"任意的便利"

至于为什么需要名称空间管理器,而不是使用文档来解决问题,我可以想到两个原因.

原因1

如果只允许向documentElement添加名称空间声明(如您的示例中所示),selectSingleNode只使用定义的内容确实是微不足道的.

但是,您可以在文档中的任何元素上定义命名空间前缀,并且命名空间前缀并不唯一地绑定到文档中的任何给定命名空间.请考虑以下示例

<w xmlns:a="mynamespace">
  <a:x>
    <y xmlns:a="myOthernamespace">
      <z xmlns="mynamespace">
      <b:z xmlns:b="mynamespace">
      <z xmlns="myOthernamespace">
      <b:z xmlns:b="myOthernamespace">
    </y>
  </a:x>
</w>

在本例中,您希望//z//a:z//b:z返回什么?如果没有某种外部名称空间管理器,您会如何表达这一点?

理由2

它允许您在任何等效文档中重用相同的XPath表达式,而无需了解任何正在使用的名称空间前缀.

myXPathExpression = "//z:y"
doc1.selectSingleNode(myXPathExpression);
doc2.selectSingleNode(myXPathExpression);

文件1:

<x>
  <z:y xmlns:z="mynamespace" />
</x>

文档2:

<x xmlns"mynamespace">
  <y>
</x>

为了在没有名称空间管理器的情况下实现后一个目标,您必须判断每个文档, for each 文档构建一个自定义XPath表达式.

.net相关问答推荐

.NET发布的应用程序运行与开发不同的端口

.NET MAUI ListView - ObservableCollection - 在异步方法期间不更新

.NET Core 中的微服务

与 Datagrid 的 SelectedItem 链接时的 WPF RadioButton 绑定问题

将字符串与容差进行比较

调整小数精度,.net

.NET 的 Visual Studio 调试器提示和技巧

从 switch 块中跳出 foreach 循环

是什么让 Enum.HasFlag 这么慢?

为什么字典比列表快得多?

为什么 LINQ .Where(predicate).First() 比 .First(predicate) 快?

在安全处理异常时避免首次机会异常消息

从 .NET 中的字符串末尾修剪字符串 - 为什么会丢失?

string.Empty vs null.你用哪一个?

将日期时间转换为时间跨度

并发字典正确用法

嵌套的 Try/Catch 块是个坏主意吗?

System.Array.CopyTo() 和 System.Array.Clone() 之间的区别

作者主签名的时间戳发现了一个建链问题:UntrustedRoot: self-signed certificate in certificate chain

WinForms 中的模型视图演示者