<?xml version="1.0" encoding="utf-8" ?>
<root>
  <h:table xmlns:h=http://www.w3.org/TR/html4/>
    <h:tr>
      <h:td>Apples</h:td>
      <h:td>Bananas</h:td>
    </h:tr>
  </h:table>
  <f:table xmlns:f="http://www.w3schools.com/furniture">
    <f:name>African Coffee Table</f:name>
    <f:width>80</f:width>
    <f:length>120</f:length>
  </f:table>
  <table>
    <name>Microsoft Visual C# 2008 Step by Step</name>
    <author>John Sharp</author>
  </table>
</root>
在 xml 的查詢中, Namespace 的處理往往都需事先知道後, 才能在程式中設定.
例如以下的程式:
XmlDocument doc = new XmlDocument(); 
doc.Load(@".\ns.xml"); 
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable); 
mgr.AddNamespace("h", "http://www.w3.org/TR/html4/"); 
mgr.AddNamespace("f", http://www.w3schools.com/furniture);
如果 ns.xml 檔案的 namespace 多了一個, 或是對應的 url 路徑異動了, 程式大概就要修改, 然後重新上版.    因為我覺得這樣蠻麻煩的, 所以寫了以下兩個方式來做 namespace 的設定.
- 使用 Regular Expression, 找出所有 xmlns:<perefix>="<uri>" 的 pattern.     
 程式參考如下:XmlDocument doc = new XmlDocument(); doc.Load(@".\ns.xml"); XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable); Regex reg = new Regex("xmlns[:]?(?<prefix>.*?)\\s*=\\s*\"(?<uri>.*?)\"", RegexOptions.IgnoreCase); Match match = reg.Match(doc.OuterXml); while (match.Success) { if (!mgr.HasNamespace(match.Groups["prefix"].Value)) { mgr.AddNamespace(match.Groups["prefix"].Value, match.Groups["uri"].Value); } match = match.NextMatch(); }
- 使用 SelectNodes(), 查出所有的 XmlDocument 中所有的 Node, 再針對屬性 Prefix 為 xmlns 的資料做設定.     
 程式參考如下 :
XmlDocument doc = new XmlDocument(); 
doc.Load(@".\ns.xml"); 
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable); 
XmlNodeList lstNodes = doc.SelectNodes("//child::*"); 
foreach (XmlNode node in lstNodes) 
{ 
    foreach (XmlAttribute attr in node.Attributes) 
    { 
        if (attr.Prefix.Equals("xmlns")) 
        { 
            if (!mgr.HasNamespace(attr.LocalName)) 
            { 
                mgr.AddNamespace(attr.LocalName, attr.Value); 
            } 
        } 
    } 
}
另外, 要避免使用 xmlns=http://www.w3.org/TR/html4/, 這種預設 namespace 的用法, 以免後續的 XPath 查詢出問題.
補充一下設定 namespace 後的查詢方式:
//查詢xmlns:h="http://www.w3.org/TR/html4/"的<h:table> 
XmlNodeList lstNode = doc.SelectNodes("//h:table", mgr); 
foreach (System.Xml.XmlNode node in lstNode) 
{ 
    Console.WriteLine(node.OuterXml); 
} 
//查詢xmlns:f="http://www.w3schools.com/furniture"的<f:table> 
lstNode = doc.SelectNodes("//f:table", mgr); 
foreach (System.Xml.XmlNode node in lstNode) 
{ 
    Console.WriteLine(node.OuterXml); 
} 
//查詢沒有設定NameSpace的<table> 
lstNode = doc.SelectNodes("//table", mgr); 
foreach (System.Xml.XmlNode node in lstNode) 
{ 
    Console.WriteLine(node.OuterXml); 
}
沒有留言:
張貼留言