首頁  >  文章  >  後端開發  >  詳解XML命名空間(XML Namespaces)介紹以及節點讀取方法的範例程式碼

詳解XML命名空間(XML Namespaces)介紹以及節點讀取方法的範例程式碼

黄舟
黄舟原創
2017-03-21 16:39:282670瀏覽

XML 命名空間提供避免元素命名衝突的方法。

命名衝突

在 XML 中,元素名稱是由開發者定義的,當兩個不同的文件使用相同的元素名稱時,就會發生命名衝突。

這個XML 文件攜帶著某個表格中的信息:

   <tr>
   <td>Apples</td>
   <td>Bananas</td>
   </tr>

這個XML 文件攜帶有關桌子的信息(一件家具):

   <name>African Coffee Table</name>
   <width>80</width>
   <length>120</length>

假如這兩個XML 文件被一起使用,由於兩個文件都包含帶有不同內容和定義的f5d188ed2c074f8b944552db028f98a1 元素,就會發生命名衝突。

XML 解析器無法確定如何處理這類衝突。

使用前綴來避免命名衝突

此文件帶有某個表格中的信息:

   <h:tr>
   <h:td>Apples</h:td>
   <h:td>Bananas</h:td>
   </h:tr>

此XML 文件攜帶著有關一件家具的信息:

   <f:name>African Coffee Table</f:name>
   <f:width>80</f:width>
   <f:length>120</f:length>

現在,命名衝突不存在了,這是由於兩個文件都使用了不同的名稱來命名它們的f5d188ed2c074f8b944552db028f98a1 元素(fae077d51b591786197c1ce2523c9adb 和20e0d2c31ebbe4ee5491ba472c0918be)。

透過使用前綴,我們創建了兩種不同類型的 f5d188ed2c074f8b944552db028f98a1 元素。

使用命名空間(Namespaces)

這個XML 文件攜帶著某個表格中的信息:


   <h:tr>
   <h:td>Apples</h:td>
   <h:td>Bananas</h:td>
   </h:tr>

此XML 文件攜帶著有關一件家具的資訊:

d211f0a5ff2d5b27e2098f7409ee5eff
   5131fb50ac43ce34477ae02954db8af8African Coffee Tablef5a770fdb27d1c8ccb50245da14733bf
   b9784418d0fd3658f883ef7bdd1888468037265c5a838e5a28a65a2d8cfbd33e10
   61367a7e112dafa97c77aefb6b2c0f8b120ee55d0d45c3e1c817d93126a37f6bff6
008daa7d50ab7c214b59e96829b07c29

與僅使用前綴不同,我們為f5d188ed2c074f8b944552db028f98a1 標籤添加了一個xmlns 屬性,這樣就為前綴賦予了一個與某個命名空間相關聯的限定名稱。

XML Namespace (xmlns) 屬性

XML 命名空間屬性被放置於元素的開始標籤之中,並使用以下的語法:

xmlns:namespace-prefix="namespaceURI"

當命名空間被定義在元素的開始標籤中時,所有帶有相同前綴的子元素都會與同一個命名空間相關聯。

註解:用於標示命名空間的位址不會被解析器用於尋找資訊。其惟一的作用是賦予命名空間一個惟一的名稱。不過,許多公司常常會作為指標來使用命名空間指向實際存在的網頁,而這個網頁包含關於命名空間的資訊。

統一資源識別碼(Uniform Resource Identifier (URI))

#統一資源識別碼是一串可以標識網際網路資源的字元。最常用的 URI 是用來標示因特網域名位址的統一資源定位器(URL)。另一個不那麼常用的 URI 是統一資源命名(URN)。在我們的例子中,我們只使用 URL。

預設的命名空間(Default Namespaces)

為元素定義預設的命名空間可以讓我們省去在所有的子元素中使用前綴的工作。

請使用下面的語法:

xmlns="namespaceURI"

這個XML 文件攜帶著某個表格中的信息:


   <tr>
   <td>Apples</td>
   <td>Bananas</td>
   </tr>

此XML 文件攜帶著有關一件家具的信息:


   <name>African Coffee Table</name>
   <width>80</width>
   <length>120</length>
(转原文http://www.cnblogs.com/mgen/archive/2011/05/24/2056025.html)

眾所周知,XmlDocument可以進行XPath查詢,但實際上這裡所說的XPath查詢僅限於沒有命名空間(沒有xmlns屬性)的XML,一旦遇到有命名空間的XML,對應XPath查詢都會無結果。

例如下面這個XML

<a xmlns="mgen.cnblogs.com">
    <b>ccc</b>
</a>

XPath查詢/a/b會回傳null,而如果沒有xmlns的話,會回傳節點b。

If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. 
If your XML includes a default namespace, you must still add a prefix and namespace URI to the XmlNamespaceManager; 
otherwise, you will not get any nodes selected

意思就是如果XPath表達式沒有加上前綴(如a:b中前綴是a),那麼所查詢節點(注意屬性也可以是節點)的命名空間URI就應該是空值(也是預設值),否則XPath不會回傳結果。

上面的XML, 因為節點a和b都有命名空間值,自然XPath查詢不會有結果。

(上面英文也提到如果節點有預設命名空間,那麼還得手動在XmlNamespaceManager中加入前綴和命名空間值,這個在後面會講的)

在看解決方案前,首先需要能夠辨識XML命名空間,當然辨識XML命名空間值還是很容易的,參考如下XML(這個XML在後面程式中也會用到)

<?xmlversion="1.0" encoding="utf-8"?>
<rootxmlns="dotnet" xmlns:w="wpf">
  <a>data in a</a>                
  <w:b>data in b</w:b>         
  <cxmlns="silverlight">
    <w:d>                             
      <e>data in e</e>              
    </w:d>
  </c>
</root>

它的所有XML節點的命名空間如下所示:

<?xmlversion="1.0" encoding="utf-8"?>
<rootxmlns="dotnet" xmlns:w="wpf">
  <!-- xmlns: dotnet -->
  <a>data in a</a>
  <!-- xmlns: dotnet -->
  <w:b>data in b</w:b>
  <!-- xmlns: wpf -->
  <cxmlns="silverlight">
    <!-- xmlns: silverlight -->
    <w:d>
      <!-- xmlns: wpf -->
      <e>data in e</e>
      <!-- xmlns: silverlight -->
    </w:d>
  </c>
</root>

如果識別XML命名空間沒有問題,那麼後面的操作就相當簡單了,你需要記住:在XmlDocument中用XPath查詢某一節點時,只要它的命名空間值不是空值,那麼你必須給它一個前綴, 用這個前綴代表這個節點的命名空間值!這些前綴是透過XmlNamespaceManager類別新增的,使用時將XmlNamespaceManager 傳入SelectNodes或SelectSingleNode中即可。這也是為什麼上面說「如果節點有預設命名空間,那麼還得手動在 XmlNamespaceManager中加入前綴和命名空間值」的原因。

另外构造一个XmlNamespaceManager需要XmlNameTable对象,这个对象可以从XmlDocument.NameTable和XmlReader.NameTable属性中得到。

下面我们步入代码,比如说查询上面XML中的节点e,分析位置节点e位于:root->c->d->e,然后将所需命名空间值加入到 XmlNamespaceManager中(前缀名称无所谓,只要在XPath一致即可),查询即可成功,如下代码:

   /*
              * 假设上面XML文件在C:\a.txt中
              * 下面代码会查询目标节点e,并输出数据:data in e
              * */
 
            var xmlDoc =newXmlDocument();
            xmlDoc.Load(@"C:\a.txt");
 
            //加入命名空间和前缀
            var xmlnsm =newXmlNamespaceManager(xmlDoc.NameTable);
            xmlnsm.AddNamespace("d", "dotnet");
            xmlnsm.AddNamespace("s", "silverlight");
            xmlnsm.AddNamespace("w", "wpf");
 
            var node = xmlDoc.SelectSingleNode("/d:root/s:c/w:d/s:e", xmlnsm);
            Console.WriteLine(node.InnerText);
 
            //输出:data in e


以上是詳解XML命名空間(XML Namespaces)介紹以及節點讀取方法的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn