查询 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");
...
要创建它,我不仅需要使用名称表为实例播种,还需要手动指定每个命名空间。这对我来说太愚蠢了。如果我必须去手动添加它们,那么传递名称表有什么意义呢?如果我需要为每个查询传回 namespace 管理器,那么传递名称表有什么意义呢?为什么它不能立即从文档中包含的内容构建命名空间管理器。似乎只是运行一个查询就需要大量的麻烦。
最佳答案
如果您的 XPath 具有命名空间前缀,则必须传入 NamespaceManager。以下是您不需要命名空间管理器的情况列表:
- 如果您的所有节点都在默认(空)命名空间中,您可以使用
/a/b/c
作为 XPath - 如果您更喜欢为每个节点手动指定命名空间/名称对,例如
*[namespace-uri()='urn:oasis:names' & name()='node1']
。 - 如果您只能在 XPath 中使用父/子、位置和兄弟
您传递 NameTable 以允许更快的字符串比较 - 如果文档和命名空间管理器共享相同的 NameTable,则相同的字符串实际上是相同的对象。您实际上不必传递相同的 NameTable。
您必须仅指定那些在您的 XPath 中使用的前缀。它通常远小于文档中的所有 namespace 。无法从 XML 自动计算映射,因为前缀到 namespace 的映射是任意的。
这是一个 XML 示例,其中所有前缀都相同,但每次都映射到不同的命名空间,以显示在 XPath 中自定义前缀映射的实际需要:
<a:a xmlns='a:my1'>
<a:a xmlns='a:my2' />
<a:a xmlns='a:my3' />
</a>
关于c# - 为什么我需要为 Xpath 查询指定命名空间管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7404386/