C#讀取XML文檔使用XMLTextReader類淺析
C#讀取XML文檔兩種方法的比較從何談起呢?讓我們首先來(lái)看看XMLTextReader和XmlDocument讀取XML文件的比較:
C#讀取XML文檔之在.NET框架的System.XML名稱空間中包含的XMLTextReader類不需要對(duì)系統(tǒng)資源要求很高,就能從XML文件中快速讀取數(shù)據(jù)。使用XMLTextReader類能夠從XML文件中讀取數(shù)據(jù),并且將其轉(zhuǎn)換為HTML格式在瀏覽器中輸出。
讀本文之前,讀者需要了解一些基本知識(shí):XML、HTML、C#編程語(yǔ)言,以及.NET尤其是ASP.NET框架的一些知識(shí)。
C#讀取XML文檔的解決為目的,微軟公司的.NET框架為開發(fā)者提供了許多開發(fā)的便利,隨著XML的重要性不斷增長(zhǎng),開發(fā)者們都期待著有一整套功能強(qiáng)大的XML工具被開發(fā)出來(lái)。.NET框架沒(méi)有辜負(fù)我們的這番期望,在System.XML 名稱空間中組織進(jìn)了以下幾個(gè)用于XML的類:
XMLTextReader------提供以快速、單向、無(wú)緩沖的方式存取XML數(shù)據(jù)。(單向意味著你只能從前往后讀取XML文件,而不能逆向讀?。?/P>
XMLValidatingReader------與XMLTextReader類一起使用,提供驗(yàn)證DTD、XDR和XSD架構(gòu)的能力。
XMLDocument------遵循W3C文檔對(duì)象模型規(guī)范的一級(jí)和二級(jí)標(biāo)準(zhǔn),實(shí)現(xiàn)XML數(shù)據(jù)隨機(jī)的、有緩存的存取。一級(jí)水平包含了DOM的最基本的部分,而二級(jí)水平增加多種改進(jìn),包括增加了對(duì)名稱空間和級(jí)連狀圖表(CSS)的支持。
XMLTextWriter------生成遵循 W3C XML 1.0 規(guī)范的XML文件。
本文主要講述的C#讀取XML文檔的方法是***個(gè)類XMLTextReader,這個(gè)類設(shè)計(jì)的目的就是從XML文件中快速的讀取數(shù)據(jù),而對(duì)系統(tǒng)資源(主要包括內(nèi)存和處理器時(shí)間)不做很高的要求。在父級(jí)程序的控制下,它通過(guò)每次只處理一個(gè)節(jié)點(diǎn)的方式對(duì)XML文件進(jìn)行逐步操作,實(shí)現(xiàn)這種工作過(guò)程。在XML文件的每個(gè)節(jié)點(diǎn)中,父級(jí)程序能決定該節(jié)點(diǎn)的類型,它的屬性和數(shù)據(jù)(如果有的話),以及其他有關(guān)該節(jié)點(diǎn)的信息?;谶@些信息,父級(jí)程序可以選擇是處理這個(gè)節(jié)點(diǎn)還是忽略該節(jié)點(diǎn)的信息,以滿足各種應(yīng)用程序請(qǐng)求的需要。這被稱為抽取式(pull)處理模型,因?yàn)楦讣?jí)程序發(fā)出請(qǐng)求并且從XML文件中抽取各個(gè)節(jié)點(diǎn),然后根據(jù)需要處理它或者是不處理它。
我們可以把XMLTextReader類和XML簡(jiǎn)單應(yīng)用程序接口,即SAX相比,后者是在編程人員中非常流行的另一種讀取XML數(shù)據(jù)的技術(shù)。XMLTextReader 和SAX有一點(diǎn)很相似,它們都不需要占用很多的系統(tǒng)資源,就能迅速的從XML文件讀取數(shù)據(jù)。但是,與XMLTextReader的抽取式模型迥然不同,SAX使用的是推入式模型:XML處理器通過(guò) “事件”告知主機(jī)應(yīng)用程序哪些節(jié)點(diǎn)數(shù)據(jù)是可以獲得,那些不能獲得;根據(jù)需要,主機(jī)程序則作出相應(yīng)的反應(yīng)或置之不理。換句話說(shuō),數(shù)據(jù)的傳送方向是從SAX處理程序中推入到主機(jī)。程序員們勢(shì)必會(huì)在抽取式和推入式處理模型誰(shuí)更有優(yōu)勢(shì)的問(wèn)題上爭(zhēng)論一番,但是大家都不可否認(rèn)的是,兩種模型都能很好的進(jìn)行工作。.NET 框架不支持SAX,但是你能使用現(xiàn)存的SAX工具, 例如 MSXML分析器,用于你的.NET 程序。
C#讀取XML文檔之XMLTextReader 類有一些構(gòu)造程序來(lái)適應(yīng)各種各樣的情況,比如從一個(gè)已經(jīng)存在的數(shù)據(jù)流或統(tǒng)一資源定位網(wǎng)址讀取數(shù)據(jù)。最常見(jiàn)的是,你或許想從一個(gè)文件讀取XML數(shù)據(jù),那么也就有一個(gè)相應(yīng)的構(gòu)造程序來(lái)為此服務(wù)。這里有一個(gè)例子(我的所有代碼例子都使用的是C#語(yǔ)言,如果你喜歡使用VISUAL BASIC語(yǔ)言,它們轉(zhuǎn)換起來(lái)很容易)。
- XMLTextReader myReader;
- myReader = New XMLTextReader("c:\data\sales.XML")
創(chuàng)建一個(gè)稱為Read()方法的循環(huán),這個(gè)方法的返回值總是為真,直到到達(dá)文件的底部時(shí),返回值才變?yōu)榧?。換句話說(shuō), 循環(huán)在文件的開始時(shí)啟動(dòng)并且讀入所有的節(jié)點(diǎn), 一次讀入一個(gè)節(jié)點(diǎn), 直到到達(dá)文件的結(jié)尾:
- While (myReader.Read()) {
- ...
- // 在這里處理每個(gè)節(jié)點(diǎn).
- ...
- }
每次成功調(diào)用Read()之后,XMLTextReader實(shí)例化程序包含了目前節(jié)點(diǎn)(即剛剛從文件中讀取的那個(gè)節(jié)點(diǎn))的信息。我們可以從XMLTextReader的成員中獲得上述信息,就像表格1中描述的一樣;并通過(guò)NodeType屬性判斷出當(dāng)前節(jié)點(diǎn)的類型。在節(jié)點(diǎn)類型的基礎(chǔ)上,程序的代碼可以讀取節(jié)點(diǎn)數(shù)據(jù),檢查它是否有屬性,到底是忽略它還是根據(jù)程序需要進(jìn)行相應(yīng)的操作和處理。
當(dāng)使用NodeType屬性時(shí),理解節(jié)點(diǎn)怎么聯(lián)系到XML單元是非常重要的。例如, 看下列 XML元素:
﹤city﹥Chongqing﹤/city﹥
C#讀取XML文檔之XMLtextReader 把這個(gè)元素看作 3 個(gè)節(jié)點(diǎn),順序如下:
1.﹤city﹥標(biāo)簽被讀為類型 XMLNodeType.Element 節(jié)點(diǎn),元素的名字“city”可從 XMLTextReader 的Name屬性中獲得。
2.文本數(shù)據(jù)“Chongqing”被讀為類型為XMLNodeType.Text的節(jié)點(diǎn)。數(shù)據(jù)“Chongqing ” 可從XMLTextReader 的Value屬性中取得。
3.﹤/city﹥標(biāo)簽被讀為類型為XMLNodeType.EndElement 節(jié)點(diǎn)。同樣,元素的名稱“city”可從XMLTextReader的Name屬性中獲得。
這是 3 種重要的節(jié)點(diǎn)類型,其它的類型在.NET的說(shuō)明文檔中有詳細(xì)說(shuō)明,請(qǐng)大家參閱相關(guān)資料。
如果XMLTextReader遇到一個(gè)錯(cuò)誤, 例如出現(xiàn)違反XML句法的情況,它拋出一個(gè)System.XML.XMLException類型的異常。使用這個(gè)類的代碼應(yīng)該總是被保護(hù) ( 在Try……Catch塊中),就像你以后在演示程序中看到的一樣。
本文只是一篇相當(dāng)簡(jiǎn)單的介紹C#讀取XML文檔之XMLTextReader 類的文章,XMLTextReader類有相當(dāng)多的成員,在這里不可能一一述及。當(dāng)讀入XML數(shù)據(jù)時(shí),XMLTextReader能提供相當(dāng)強(qiáng)的靈活性。即便如此,我仍然進(jìn)行了大量的論述,以保證讀者能編制程序來(lái)實(shí)現(xiàn)現(xiàn)實(shí)世界中經(jīng)常要求完成的任務(wù),也就是從一個(gè)XML文件讀取數(shù)據(jù)然后以HTML的格式輸出,從而實(shí)現(xiàn)在瀏覽器中的顯示。
這個(gè)ASP.NET程序(腳本)在服務(wù)器上運(yùn)行并產(chǎn)生一個(gè)HTML頁(yè)面返回瀏覽器。這段腳本程序在代碼段 1 給出,它用來(lái)工作使用的 XML 數(shù)據(jù)文件在代碼段 2給出。你能看到這個(gè) XML 文件包含一份表示聯(lián)系關(guān)系的列表;程序的目標(biāo)即是將這個(gè)列表顯示出來(lái),為了更容易我們觀察,這些列表已經(jīng)被格式化了。
運(yùn)行程序:
1. 將代碼段1存為XMLTextReader.ASPx文件,將代碼段2存為XMLData.XML文件。
2. 把這兩個(gè)文件都放在一個(gè)已經(jīng)安裝好.NET 框架的網(wǎng)絡(luò)服務(wù)器的虛擬文件夾中。
3. 打開 Internet Explorer 并且瀏覽這個(gè)ASPx文件,例如,在一個(gè)局域網(wǎng)服務(wù)器上, URL 將是 http://localhost/xmltextreader.ASPx。
程序工作的大部分都由XMLDisplay 類來(lái)做,尤其是被ProcessXML()方法完成的。它每次讀取一個(gè)節(jié)點(diǎn)XML數(shù)據(jù),對(duì)于感興趣的元素,節(jié)點(diǎn)數(shù)據(jù)和后跟冒號(hào)的節(jié)點(diǎn)名將和相應(yīng)的HTML格式化標(biāo)簽一起寫入輸出結(jié)果中。在這階段,“輸出結(jié)果”由一個(gè)HTML文本暫時(shí)儲(chǔ)存在其中的StringBuilder對(duì)象構(gòu)成。
ProcessXML()方法是從LoadDocument()方法調(diào)用的。這個(gè)方法執(zhí)行的任務(wù)是產(chǎn)生一個(gè)XMLTextReader實(shí)例化程序并在調(diào)用ProcessXML之前裝載XML文件。它同時(shí)也處理異常,隨后產(chǎn)生錯(cuò)誤的信息并在瀏覽器中顯示出來(lái)。最終該方法返回一個(gè)字符串,這個(gè)字符串或者包含產(chǎn)生的HTML內(nèi)容,或者如果異常發(fā)生的話就包含出錯(cuò)信息,。
程序執(zhí)行以Page_Load()程序開始,當(dāng)瀏覽器請(qǐng)求瀏覽這個(gè)頁(yè)面時(shí),這一步會(huì)自動(dòng)執(zhí)行。這里的代碼實(shí)例化了XMLDisplay 類并調(diào)用它的LoadDocument()方法。如果一切運(yùn)行正常的話,格式化的HTML形式的返回值將被拷貝到頁(yè)面的一個(gè)﹤div﹥標(biāo)簽中,生成的HTML文檔被送回到瀏覽器中并顯示出來(lái)。
其他的.NET 框架的類在C#讀取XML文檔方面如何呢?比如XMLDocument類在讀取XML數(shù)據(jù)方面表現(xiàn)如何呢?XMLDocument 類與XMLTextReader 類不同,它在存儲(chǔ)器中創(chuàng)建整個(gè)XML文檔的節(jié)點(diǎn)樹。這樣就可以隨機(jī)的獲得XML數(shù)據(jù)(與XMLTextReader 類獲得數(shù)據(jù)的線性方式正好相反),并且在修改XML文件的數(shù)據(jù)和結(jié)構(gòu)時(shí),具有非常***的靈活性。另外,XMLDocument允許執(zhí)行XSLT 轉(zhuǎn)變,不過(guò),這些額外的功能是以運(yùn)行速度的降低和系統(tǒng)資源的更多占用為代價(jià)的。
C#讀取XML文檔使用XMLTextReader類代碼段:XmlTextReader.aspx
- ﹤%@ Import Namespace="System.Xml" %﹥
- ﹤script language="C#" runat=server﹥
- public class XmlDisplay
- file://這個(gè)類讀入并處理XML文件。
- {
- public string LoadDocument(String XmlFileName) {
- XmlTextReader xmlReader = null;
- StringBuilder html = new StringBuilder();
- try {
- file://創(chuàng)建XMLTextReader的實(shí)例。
- xmlReader = new XmlTextReader(XmlFileName);
- // 處理XML文件
- html.Append(ProcessXml(xmlReader));
- }
- catch (XmlException ex){
- html.Append("發(fā)生一個(gè)XML異常:" +
- ex.ToString());
- }
- catch (Exception ex){
- html.Append("發(fā)生一個(gè)普通異常:" +
- ex.ToString());
- }
- finally
- {
- if (xmlReader != null)
- xmlReader.Close();
- }
- return html.ToString();
- }
- private string ProcessXml(XmlTextReader xmlReader)
- {
- StringBuilder temp = new StringBuilder();
- file://這個(gè)方法讀入XML文件并生成輸出的HTML文檔。
- while ( xmlReader.Read() )
- {
- // 處理一個(gè)元素節(jié)點(diǎn)的起始。
- if (xmlReader.NodeType == XmlNodeType.Element)
- {
- file://忽略﹤people﹥和﹤person﹥?cè)?
- if ((xmlReader.Name != "person") && (xmlReader.Name != "people"))
- {
- file://如果是一個(gè)﹤category﹥?cè)兀_始一個(gè)新的段落
- if ( xmlReader.Name == "category" )
- temp.Append("﹤p﹥");
- file://添加元素名到輸出中
- temp.Append( xmlReader.Name + ": " );
- }
- }
- // 處理文本節(jié)點(diǎn)
- else if (xmlReader.NodeType == XmlNodeType.Text)
- temp.Append(xmlReader.Value + "﹤br﹥");
- file://處理元素節(jié)點(diǎn)的結(jié)尾
- else if (xmlReader.NodeType == XmlNodeType.EndElement)
- {
- file://如果是﹤email﹥節(jié)點(diǎn),添加結(jié)束段落的標(biāo)記
- if ( xmlReader.Name == "email" )
- temp.Append("﹤/p﹥");
- }
- }//結(jié)束while循環(huán)
- return temp.ToString();
- } file://結(jié)束ProcessXML方法
- } file://結(jié)束XmlDisplay類
- private void Page_Load(Object sender, EventArgs e){
- file://創(chuàng)建XmlDisplay類的實(shí)例
- XmlDisplay XmlDisplayDemo = new XmlDisplay();
- output.InnerHtml = XmlDisplayDemo.LoadDocument(Server.MapPath("XMLData.xml"));
- }
- ﹤/script﹥
- ﹤html﹥
- ﹤head﹥
- ﹤/head﹥
- ﹤body﹥
- ﹤h2﹥演示XmlTextReader類﹤/h2﹥
- ﹤div id="output" runat="server"/﹥
- ﹤/body﹥
- ﹤/html﹥
- static void Main(string[] args)
- {
- DateTime d1 =DateTime.Now;
- XmlDocumentTest();
- DateTime d2 =DateTime.Now;
- TimeSpan ts =d2-d1 ;
- Console.WriteLine(ts.TotalMilliseconds) ;
- Console.Read() ;
- }
- public static string XmlFileName = "../../XML/1.xml";
- private static void XmlTextReaderTest()
- {
- XmlTextReader reader = new XmlTextReader(XmlFileName);
- while (reader.Read() )
- {
- bool exit =false;
- switch(reader.NodeType)
- {
- case XmlNodeType.Element :
- break;
- case XmlNodeType.Text :
- if (reader.Value=="last")
- {
- exit=true;
- }
- break;
- case XmlNodeType.EndElement :
- break;
- default:
- break;
- }
- if(exit)
- {
- return;
- }
- }
- }
- private static void XmlDocumentTest()
- {
- XmlDocument xd =new XmlDocument() ;
- xd.Load(XmlFileName) ;
- XmlNode node = xd.SelectSingleNode("/people/person[category='last']");
- Console.Write(node.Name) ;
- }
C#讀取XML文檔使用XMLTextReader類的方法就向你介紹到這里,希望對(duì)你理解和學(xué)習(xí)C#讀取XML文檔使用XMLTextReader類有所幫助。
【編輯推薦】