王超 鄭清
(成都理工大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,四川成都610059)
可擴(kuò)展標(biāo)記語(yǔ)言(Extensible Markup Language,XML),用于標(biāo)記電子文件使其具有結(jié)構(gòu)性的標(biāo)記語(yǔ)言,可以用來(lái)標(biāo)記數(shù)據(jù)、定義數(shù)據(jù)類(lèi)型,是一種允許用戶(hù)對(duì)自己的標(biāo)記語(yǔ)言進(jìn)行定義的源語(yǔ)言。XML是標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言(SGML)的子集,非常適合Web傳輸。XML提供統(tǒng)一的方法來(lái)描述和交換獨(dú)立于應(yīng)用程序或供應(yīng)商的結(jié)構(gòu)化數(shù)據(jù),是獨(dú)立于軟件和硬件的信息傳輸工具。
XML與HTML的設(shè)計(jì)區(qū)別是:XML是用來(lái)存儲(chǔ)數(shù)據(jù)的,重在數(shù)據(jù)本身。而HTML是用來(lái)定義數(shù)據(jù)的,重在數(shù)據(jù)的顯示模式。HTML旨在顯示信息,而XML旨在傳輸信息。因此與HTML比起來(lái),XML應(yīng)用起來(lái)更方便,用戶(hù)可以根據(jù)自己得需要存儲(chǔ)數(shù)據(jù),而無(wú)需顧慮格式,XML只要求鍵值對(duì)成對(duì)出現(xiàn),并按照樹(shù)狀結(jié)果存儲(chǔ)即可。XML允許創(chuàng)作者定義自己的標(biāo)簽和自己的文檔結(jié)構(gòu)。
提到用C++解析XML,就不得不提起Tinyxml。Tinyxml是一個(gè)基于DOM模型的、非驗(yàn)證的輕量級(jí)C++解釋器。眾所周知,目前XML的解析主要有兩大模型:SAX和DOM。
其中SAX是基于事件的,其基本工作流程是分析XML文檔,當(dāng)發(fā)現(xiàn)了一個(gè)新的元素時(shí),產(chǎn)生一個(gè)對(duì)應(yīng)事件,并調(diào)用相應(yīng)的用戶(hù)處理函數(shù)。這種方式占用內(nèi)存少,速度快,但用戶(hù)程序相應(yīng)會(huì)比較復(fù)雜。而DOM(文檔對(duì)象模型),則是在分析時(shí),一次性地將整個(gè)XML文檔進(jìn)行分析,并在內(nèi)存中形成對(duì)應(yīng)的樹(shù)結(jié)構(gòu),同時(shí),向用戶(hù)提供一系列的接口來(lái)訪問(wèn)和編輯該樹(shù)結(jié)構(gòu)。這種方式占用內(nèi)存大,速度往往慢于SAX,但可以給用戶(hù)提供一個(gè)面向?qū)ο蟮脑L問(wèn)接口,對(duì)用戶(hù)更為友好。那何為驗(yàn)證和為非驗(yàn)證呢?首先一個(gè)合格的XML文檔必須符合其基本的格式要求。例如第一行要有聲明,標(biāo)簽的嵌套層次必須前后一致等等。解析器也分為兩種,一種是驗(yàn)證的,即會(huì)跟據(jù)XML文件中的聲明,用相應(yīng)的DTD文件對(duì)XML文件進(jìn)行校驗(yàn),檢查它是否滿(mǎn)足DTD文件的要求;另一種是忽略DTD文件,只要基本格式正確,就可以進(jìn)行解析。Tinyxml是不支持驗(yàn)證的,適合解析比較簡(jiǎn)單的XML文件,比如配置文件等。
TinyxML是一個(gè)開(kāi)源的解析XML的解析庫(kù),所以Tinyxml庫(kù)在網(wǎng)上即可下載,做了相應(yīng)的配置之后我們就可以使用它了。首先先介紹一下Tinyxml主要類(lèi)間的關(guān)系。
TiXm lBase:整個(gè)TinyXML模型的基類(lèi)。
TiXm lAttribute:對(duì)應(yīng)于XML中的元素的屬性。
TiXm lNode:對(duì)應(yīng)于DOM結(jié)構(gòu)中的節(jié)點(diǎn)。
TiXm lComment:對(duì)應(yīng)于XML中的注釋。
TiXm lDeclaration:對(duì)應(yīng)于XML中的申明部分。
TiXm lDocument:對(duì)應(yīng)于XML的整個(gè)文檔。
TiXm lElement:對(duì)應(yīng)于XML的元素。
TiXm lText:對(duì)應(yīng)于XML的文字部分。
TiXm lUnknown:對(duì)應(yīng)于XML的未知部分。
TiXm lHandler:定義了針對(duì)XML的一些操作。
在使用TinyXm l時(shí)有一點(diǎn)需要我們注意,因?yàn)樗遣恢С烛?yàn)證的,所以當(dāng)我們解析某個(gè)文件的時(shí)候,要檢查返回的指針是否為空,否則會(huì)出現(xiàn)內(nèi)存的訪問(wèn)錯(cuò)誤。
C++的開(kāi)發(fā)離不開(kāi)STL(標(biāo)準(zhǔn)模板庫(kù))的使用。STL(標(biāo)準(zhǔn)模板庫(kù))是在惠普實(shí)驗(yàn)室中開(kāi)發(fā)的,已納入ANSI/ISO C++標(biāo)準(zhǔn)。其中的代碼采用模板類(lèi)及模板函數(shù)的方式,可以極大地提高編程效率。STL中幾個(gè)關(guān)鍵基本概念是我們必須要知道的。首先是容器:可容納各種數(shù)據(jù)類(lèi)型的數(shù)據(jù)結(jié)構(gòu)。其次是迭代器:可依次存取容器中元素的東西。還有最重要的算法:用來(lái)操作容器中的元素的函數(shù)模板。例如,STL用sort()來(lái)對(duì)一個(gè)vector中的數(shù)據(jù)進(jìn)行排序,用find()來(lái)搜索一個(gè)list中的對(duì)象。而容器分為三大類(lèi):
(1)順序容器。vector:后部插入/刪除,直接訪問(wèn);deque:前/后部插入/刪除,直接訪問(wèn);list:雙向鏈表,任意位置插入/刪除。(2)關(guān)聯(lián)容器。set:快速查找,無(wú)重復(fù)元素;multiset:快速查找,可有重復(fù)元素;map:一對(duì)一映射,無(wú)重復(fù)元素,基于關(guān)鍵字查找;multimap:一對(duì)一映射,可有重復(fù)元素,基于關(guān)鍵字查找。前兩者合稱(chēng)為第一類(lèi)容器。3)容器適配器。stack:LIFO;queue:FIFO;priority_queue:優(yōu)先級(jí)高的元素先出。
在使用XML做配置文件的時(shí)候,基于XML的特殊性,我們很容易聯(lián)想到使用關(guān)聯(lián)容器存儲(chǔ)我們解析出來(lái)的數(shù)據(jù)。而map無(wú)疑是我們最好的選擇。我們將從XML讀出來(lái)的配置信息存放在map中。map中存放的是成對(duì)的key/value。根據(jù)key對(duì)元素進(jìn)行排序,可快速地檢索元素。當(dāng)我們要查詢(xún)配置信息的時(shí)候,可以高效地得到我們所需的查詢(xún)結(jié)果。本文就是使用map作為存儲(chǔ)容器,結(jié)合Tinyxml的使用,達(dá)到高效的對(duì)XML配置文檔的解析。應(yīng)用關(guān)鍵代碼如下:
以上程序可以幫助我們讀取XML文檔中第三級(jí)子節(jié)點(diǎn)的信息,我們可以根據(jù)實(shí)際需要增加循環(huán)或者嵌套語(yǔ)句來(lái)讀取更深級(jí)別的節(jié)點(diǎn)信息。通過(guò)以上程序,我們可以看出C++與Tinyxm l相結(jié)合可以幫助我們快速讀取XML文檔中的配置信息,也體現(xiàn)了Tinyxm l最大的特點(diǎn),即能夠快速地靜態(tài)連接到程序里面。但由于Tinyxm是非驗(yàn)證的,所以我們?cè)趯?shí)際應(yīng)用中要慎重考慮,避免不必要的檢查工作。
[1] 李普曼(Stanley B.Lippman)等.C++Primer中文版[M].李師賢、蔣愛(ài)軍等譯.第4版.北京:人民郵電出版社,2008.
[2] 楊柳青.TinyXml在Linux平臺(tái)中的應(yīng)用研[J].機(jī)械工程與自動(dòng)化,2009(5):41-43.
[3] 孫曉非等編著.XM L基礎(chǔ)教程與實(shí)驗(yàn)指導(dǎo)[M].清華大學(xué)出版社,2008.