为什么我需要为Xpath查询指定命名空间管理器

时间:2011-09-13 15:22:48

标签: c# xml

查询XmlDocument时,我需要在每次调用时传递名称空间管理器。真烦人,但这只是我们生活的东西。真正讨厌的一点是首先创建名称空间管理器。

XmlNamespaceManager nsMan = new XmlNamespaceManager(invoiceTextReader.NameTable);
nsMan.AddNamespace("", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2");
nsMan.AddNamespace("pb", "urn:pierbridge:names:specification:pbl:schema:xsd:tpn-1");
...

要创建它,我不仅要使用nametable为实例设定种子,还要手动指定每个命名空间。这对我来说似乎很愚蠢。如果我必须手动添加它们,那么传递名称表的重点是什么。如果我需要为每个查询传递命名空间管理器,那么传递名称表的重点是什么。为什么它不能直接从文档中包含的内容构建命名空间管理器。看起来只是为了运行一个查询而非常麻烦。

2 个答案:

答案 0 :(得分:3)

如果您的XPath具有名称空间前缀,则必须传入NamespaceManager。下面是不需要命名空间管理器的情况列表:

  • 如果您的所有节点都在默认(空)命名空间中,则可以使用/a/b/c作为XPath
  • 如果您希望为每个节点手动指定名称空间/名称对,例如*[namespace-uri()='urn:oasis:names' & name()='node1']
  • 如果您只能在XPath中使用父/子,位置和兄弟姐妹

传递NameTable以允许更快的字符串比较 - 如果文档和命名空间管理器共享相同的NameTable,则相同的字符串实际上是同一个对象。您实际上不必传递相同的NameTable。

您必须仅指定XPath中使用的前缀。它通常远小于文档中的所有名称空间。无法从XML自动计算映射,因为前缀到命名空间映射是任意的。

这是XML的一个示例,其中所有前缀都相同,但每次映射到不同的命名空间以显示XPath中前缀的自定义映射的实际需要:

<a:a xmlns='a:my1'>
 <a:a xmlns='a:my2' />
 <a:a xmlns='a:my3' />
</a>

答案 1 :(得分:0)

MSDN州:

  

带有名称空间前缀的限定元素和属性名称将XPath查询返回的节点限制为仅属于特定名称空间的那些节点。

     

例如,如果前缀书籍映射到名称空间http://www.contoso.com/books,则以下XPath查询/书籍:书籍/书籍:书籍仅选择名称空间http://www.contoso.com/books中的书籍元素。

此外:

  

XPath将空前缀视为null命名空间。换句话说,只有映射到名称空间的前缀才能用于XPath查询。这意味着如果要查询XML文档中的命名空间,即使它是默认命名空间,也需要为其定义前缀。

所以这应该回答你的问题。