Dot-Net

為什麼需要 XmlNamespaceManager?

  • August 24, 2011

關於為什麼- 至少在 .Net 框架中 - 在執行 XPath 查詢時有XmlNamespaceManager必要[local-name()=...使用. 我確實理解為什麼命名空間是必要的或至少是有益的,但為什麼它如此復雜?

為了查詢一個簡單的 XML 文件(無命名空間)…

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

…一個人可以使用類似的東西doc.SelectSingleNode("//nodeName")(匹配<nodeName>Some Text Here</nodeName>

謎團#1我的第一個煩惱——如果我理解正確的話——僅僅是將命名空間引用添加到父/根標記(無論是否用作子節點標記的一部分),如下所示:

<?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”)來找到一個甚至不使用前綴的節點。這有什麼意義?(概念上)有什麼問題doc.SelectSingleNode("//nodeName")

謎團 #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, 以便查詢單個節點…

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)

…為什麼,在這種情況下,我需要(概念上)一個命名空間管理器?

**已編輯為以下評論

編輯添加: 我修改和完善的問題是基於 XmlNamespaceManager 在我認為大多數情況下的明顯冗餘以及使用命名空間管理器來指定前綴到 URI 的映射:

當名稱空間前綴(“cde”)到名稱空間 URI(“ <http://example.com/xmlns/foo> ”)的直接映射在源文件中明確說明時:

...&lt;rootNode xmlns:cde="http://example.com/xmlns/foo"...

程序員在進行查詢之前重新創建該映射的概念需求是什麼?

基本點(正如上面Kev所指出的),是命名空間URI是命名空間的重要部分,而不是命名空間前綴,前綴是“任意方便”

至於為什麼需要命名空間管理器,而不是使用文件來解決問題,我可以想到兩個原因。

原因一

如果只允許向 documentElement 添加命名空間聲明,就像在您的範例中那樣,那麼 selectSingleNode 只使用定義的任何內容確實是微不足道的。

但是,您可以在文件中的任何元素上定義名稱空間前綴,並且名稱空間前綴不會唯一綁定到文件中的任何給定名稱空間。考慮以下範例

&lt;w xmlns:a="mynamespace"&gt;
 &lt;a:x&gt;
   &lt;y xmlns:a="myOthernamespace"&gt;
     &lt;z xmlns="mynamespace"&gt;
     &lt;b:z xmlns:b="mynamespace"&gt;
     &lt;z xmlns="myOthernamespace"&gt;
     &lt;b:z xmlns:b="myOthernamespace"&gt;
   &lt;/y&gt;
 &lt;/a:x&gt;
&lt;/w&gt;

在這個例子中,你想要什麼//z//a:z//b:z返回?如果沒有某種外部命名空間管理器,你會如何表達?

原因 2

它允許您對任何等效文件重用相同的 XPath 表達式,而無需了解正在使用的名稱空間前綴的任何資訊。

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

文件1:

&lt;x&gt;
 &lt;z:y xmlns:z="mynamespace" /&gt;
&lt;/x&gt;

文件2:

&lt;x xmlns"mynamespace"&gt;
 &lt;y&gt;
&lt;/x&gt;

為了在沒有命名空間管理器的情況下實現後一個目標,您必須檢查每個文件,為每個文件建構一個自定義 XPath 表達式。

引用自:https://stackoverflow.com/questions/7178111