xml 文件解析方法


轉載自:http://www.cnblogs.com/zhangyf/archive/2009/06/03/1495459.html

內容提要

1.解析Xml文件有哪些方法?各有什么優缺點?

2.如何用XPath解析xml文檔的要點。 

     

先來看看解析xml文件的方法都有哪些吧,本段文字來自網絡,可以幫助大家對這個問題有個概要的了解。

在程序中訪問並操作XML文件一般有兩種模型:流模型和DOM(文檔對象模型)。流模型中有兩種變體——“推”模型和“拉”模型。 

 “推”模型也就是常說的SAX,SAX是一種靠事件驅動的模型。它每發現一個節點就用“推”模型引發一個事件,而我們必須編寫這些事件的處理程序,很麻煩。

.NET中使用的是基於“拉”模型的實現方案。 “拉”模型在遍歷文檔時會把感興趣的文檔部分從讀取器中拉出,不需要引發事件,允許我們以編程的方式訪問文檔,這大大的提高了靈活性,“拉”模型可以選擇性的處理節點。在.NET中,“拉”模型通過XML閱讀器(XMLTextReader類)來實現的。該類提供Xml文件讀取的功能,它可以驗證文檔是否格式良好,如果不是格式良好的Xml文檔,該類在讀取過程中將會拋出XmlException異常。任何時候在內存中只有當前節點,但它是只讀的,向前的,不能在文檔中執行向后導航操作。 

DOM的好處在於它允許編輯和更新XML文檔,可以隨機訪問文檔中的數據,可以使用XPath查詢。但是,DOM的缺點在於它需要一次性的加載整個文檔到內存中,對於大型的文檔,這會造成資源問題。在.NET中使用XML DOM分析器(XMLDocument)實現DOM模型。

因此,.NET Framework完全支持XML DOM模式,但它不支持SAX模式。.NET Framework支持兩種不同的分析模式:XML DOM分析器(XMLDocument類)和XML閱讀器(XMLTextReader類),不支持SAX分析器, 但這並不意味着它沒有提供類似SAX分析器的功能。通過XML閱讀器可以將SAX的所有的功能很容易的實現及更有效的運用。

 

在項目中,我們選用xpath的方式來解析xml文檔。這是基於以下的幾點原因:

1, 文件大小。要處理的文件不大,一般都在幾百K到1M。

2,  XPath的靈活性。不需要獲取文檔的全部數據,只需要獲取大部分想要的數據。

3,  學習代價低。符合一般的思維習慣,通過Path獲取結果。

 

通過XPath的方式解析xml文檔,需要先加載文檔,然后再讀取想要的節點值。

xml文檔

protected XmlDocument doc = null;

xml文檔的根元素(節點)

protected XmlElement root = null;

 xml文檔的名空間管理器 

protected XmlNamespaceManager nsmgr = null;

接下來就是加載文檔了

View Code
 1 protected void LoadXmlFile(FileInfo xmlFile)
 2         {
 3             if (xmlFile == null || !xmlFile.Exists)
 4             {
 5                 throw new FileNotFoundException(string.Format("要解析的文件不存在{0}。",xmlFile.FullName));
 6             }
 7             //加載文件
 8             this.doc = new XmlDocument();
 9             doc.Load(xmlFile.FullName);
10             //准備讀取文件
11             root = doc.DocumentElement;
12             string nameSpace = root.NamespaceURI;
13             nsmgr = new XmlNamespaceManager(doc.NameTable);
14             nsmgr.AddNamespace("ns", nameSpace);
15         }

這里有幾行要注意。

      這兩行是取得xml文檔的名空間

            root = doc.DocumentElement;
            string nameSpace = root.NamespaceURI;

      這兩行是建立xml文檔的名空間管理器

            nsmgr = new XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("ns", nameSpace);

      如果你的xml文檔有名空間,則這部分的代碼是必不可少的。

 

   接下來就是讀取文檔節點的值了

      這里兩個傳入參數prefixPath是節點的上級節點路徑,xRelativePath是要讀取的節點名稱。

另外,變量XmlFileInfo是要加載的xml文件。

View Code
 1 protected string GetNodeValue(string prefixPath, string xRelativePath)
 2         {
 3             if (doc == null)
 4             {
 5                 LoadXmlFile(XmlFileInfo);
 6             }
 7             string xPath = string.Empty;
 8             if (!string.IsNullOrEmpty(xRelativePath))
 9             {
10                 if (!string.IsNullOrEmpty(prefixPath))
11                 {
12                     xPath = prefixPath + xRelativePath;
13                 }
14                 else
15                 {
16                     xPath = xRelativePath;
17                 }
18             }
19             xPath = xPath.Replace("/", "/ns:");
20             XmlNode node = root.SelectSingleNode(xPath, nsmgr);
21             if (node == null)
22             {
23                 return null;
24             }
25             return node.InnerXml;

可能有的朋友要問,為什么要設置兩個參數prefixPath和xRelativePath呢,其實這個沒有多大的關系,我只是為了自己覺得方便,你也可以在方法外確定了這個XPath,在方法中只設置一個傳入參數,效果是一樣的。

   注意這一行:

      xPath = xPath.Replace("/", "/ns:");

   如果你的xml文檔帶名空間,則這行是比不可少的,否則會出現找不到節點,無法解析的情況。

   這里還有一個不得不說的問題,就是關於XPath的。

   對於這樣一個xml文檔,要查找第一個節點下的學生的Name時(ID=01),其XPath應該是"/ns:Root/ns:Students/ns:Student[1]/ns:Name"。xml對於重復的節點名稱,是按照順序1,2,3...的方式遍歷的,也就是說如果要找第N個Student節點的下的節點之,那么應使用Student[N]的標識方式。  

View Code
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <Root xmlns="urn:ClassNameSpace">
 3 <Class>
 4 <ClassID>1234</ClassID>
 5 </Class>
 6 <Students>
 7 <Student>
 8 <ID>01</ID><Name>Name01</Name>
 9 </Student>
10 <Student>
11 <ID>02</ID><Name>Name02</Name>
12 </Student>
13 </Students>
14 </Root>

當然,這里也可以獲取節點屬性的值,查找滿足特定值的節點等等,這些和上面獲取節點值的過程是類似的。這里推薦一篇介紹xpath的文章XPath 教程,大家不妨看看,關於xpath的常見問題都可以得到解決。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM