TinyXML
TinyXML 是一個(gè)簡單的、小的、可以容易地集成到其他程序中的 C++ 解析器。
1. 它可以做些什么
簡單地講,TinyXML 可以分析 XML 文檔并從一個(gè)可以被讀取、修改和存儲的文檔對象模型(Document Object Model, DOM)。
XML 是 eXtensible Markup Language 的簡稱。它允許你建立自己的文檔標(biāo)記。HTML 可以很好地為瀏覽器標(biāo)記文檔,XML 允許你定義任何文檔標(biāo)記,比如一個(gè)描述為組織應(yīng)用的 “to do” 列表的文檔。XML 是一種非常結(jié)構(gòu)化和方便的格式。所有那些用來存儲應(yīng)用數(shù)據(jù)的穩(wěn)健格式都可以用 XML 來代替。這樣的解析器對一切適用。
你可以到 http://www.w3.org/TR/2004/REC-xml-20040204 尋找完整、正確的說明書。你也可以到 http://skew.org/xml/tutorial 來看一下 XML 的簡介。
有不懂的方法來讀取和交互 XML 數(shù)據(jù)。TinyXML 使用一個(gè)文檔對象模型(DOM),XML 數(shù)據(jù)被解析為一個(gè)可以瀏覽、操作和寫到硬盤或其他輸出流的 C++ 對象。你也可以從 C++ 對象建立一個(gè) XML 文檔,并將其寫到硬盤或其他的輸出流中。
TinyXML 被設(shè)計(jì)成容易和快速地學(xué)習(xí)。它有兩個(gè)頭文件和四個(gè) cpp 文件。你可以很簡單地將其添加到你的工程中。這里有一個(gè)例子文件 xmltest.cpp,你可以從這里開始。
TinyXML 是在 ZLib 協(xié)議下發(fā)布的,你可以將其應(yīng)用于開源項(xiàng)目中或者商業(yè)代碼中。這個(gè)協(xié)議的細(xì)節(jié)位于每個(gè)源文件的最上端。
TinyXML 嘗試成為一個(gè)靈活的解析器,正確的和順從于 XML 輸出。
TinyXML 應(yīng)該可以在任何合適的 C++ 系統(tǒng)中編譯。它不依賴于異常機(jī)制和運(yùn)行時(shí)類型識別(RTTI)。在有或無 STL 支持的環(huán)境下,它都可以編譯。TinyXML 完全支持 UTF-8 編碼,和最前面的 64k 的字符實(shí)體。
2。它不可以做什么
TinyXML 不能解析或使用 DTDs(Document Type Definitions)或者 XSLs(eXtensible Stylesheet Language)。有其他的解析器(http://www.sourceforge.org, 搜索 XML)可以做其上的工作。但是這些解析器更大,需要更長的時(shí)間以建立在你的工程中,更高的學(xué)習(xí)曲線并且有更多的限制協(xié)議。如果你需要為一個(gè)瀏覽器工作或者有更完全的 XML 需求,TinyXML 并不適合你。
下面的 DTD 語法在 TinyXML 中無法解析:
@verbatim
<!DOCTYPE Archiv [
<!ELEMENT Comment (#PCDATA)>
]>
@endverbatim
TinyXML 視 !DOCTYPE 節(jié)點(diǎn)非法嵌入一個(gè) !ELEMENT 節(jié)點(diǎn)。將來這個(gè)問題可能被解決。
3。教程
對于急切的人,這里有個(gè)教程可以幫助你入門。非常好的入門方法,但是把這個(gè)手冊讀完是值得的。
4。代碼狀況
TinyXML 是一個(gè)成熟的、被測試過的代碼。它非常穩(wěn)定。如果你發(fā)現(xiàn)了 bugs,請?jiān)?sourceforge (http://www.sourceforge.net/projects/tinyxml)上寫一份 bug 報(bào)告。我們將盡快將其校正。
有一些需要改進(jìn)的方面,如果你對 TinyXML 有興趣,請加入檢查 sourceforge。
5. 相關(guān)的工程
TinyXML 工程,你可能發(fā)現(xiàn)它非常有用。
TinyXPath:http://tinyxpath.sourceforge.net ,一個(gè)小的 XPath 語法解碼器,C++ 實(shí)現(xiàn)。
TinyXML++:http://code.google.com/p/ticpp ,一個(gè)相對 TinyXML 更新接口的 XML 解析器。它利用了許多 C++ 的功能,比如模板、異常處理機(jī)制和許多更好的錯誤處理。
6。特征
6。1 使用 STL
TinyXML 在有或無 STL 的環(huán)境下都可以被編譯。當(dāng)使用 STL 時(shí),TinyXML 使用 std::string 類,支持 std::istream, std::ostream, operator<<, 和 operator>>。許多 API 有 'const char*' 和 'const std::strign&' 兩種形式。
當(dāng) STL 支持被編譯出時(shí),非 STL 文件不管怎么被包含。所有的 string 類是有 TinyXML 自身實(shí)現(xiàn)的。API 都使用 'const char*' 形式來支持輸入。
使用編譯時(shí) #define:
TIXML_USE_STL
來編譯一個(gè)版本或其他版本。可以通過編譯期傳遞或者放在 "tinyxml.h" 文件的第一行中。
注意:如果在 Linux 中編譯測試代碼,設(shè)置環(huán)境變量 TINYXML_USE_STL=YES/NO 來控制編譯。在 Windows 工程文件中,STL 和 non STL 目標(biāo)都是被支持的。在你的工程中,在 tinyxml.h 的文件的第一行中添加 #define TIXML_USE_STL 是非常容易的。
6。2 UTF-8
TinyXML 支持允許以任何語言操作 XML 文件的 UTF-8 編碼方式。TinyXML 也支持合法模式(legacy mode),其實(shí)一種被用于 UTF-8 之前的編碼方式,可以被描述成“擴(kuò)展的ASCII”(extended ASCII).
一般地,TinyXML 試著檢測正確的編碼方式并使用它。但是,可以通過在頭文件中設(shè)置 TIXML_DEFAULT_ENCODING 的值來強(qiáng)制使用某一種編碼方式。
TinyXML 將要假設(shè)一種合法模式,直到一下的其中之一發(fā)生:
1)。如果不是標(biāo)準(zhǔn)的,但是 UTF-8 帶頭字節(jié)(UTF-8 lead bytes)出現(xiàn)在文件或數(shù)據(jù)流的頭部,TinyXML 將按照 UTF-8 的編碼方式讀取。
2)。如果聲明的標(biāo)簽被讀取,并且它有個(gè) encoding="UTF-8",則按照 UTF-8 編碼方式讀取。
3)。如果聲明的標(biāo)簽被讀取,它沒有特殊的編碼,則按照 UTF-8 編碼。
4)。如果聲明表中是 encoding="something else",TinyXML 將其讀作為合法模式(legacy mode)。在合法模式中,TinyXML 和以前工作一樣。不清楚具體是哪種模式,老的內(nèi)容應(yīng)該保持工作。
5)。直到上面的一種準(zhǔn)則滿足,TinyXML 按照合法模式執(zhí)行。
如果編碼是不正確的,或者被檢測出來將要發(fā)生什么?TinyXML 將其看做不合適的編碼。你可能得到的是不正確的結(jié)果或亂碼。你可能想強(qiáng)制 TinyXML 變?yōu)檎_的模式。
這一通過 LoadFile( TIXML_ENCODING_LEGACY ) 或者 LoadFile( filename, TIXML_ENCODING_LEGACY ) 的方式強(qiáng)制 TinyXML 設(shè)置為合法模式。你可以設(shè)置 TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY 來一直使用合法模式。同樣地,你也可以使用同樣的技術(shù)將其設(shè)置為 TIXML_ENCODING_UTF8。
對于英語用戶,使用英文的 XML,UTF-8 與 low-ASCII 是一樣的,你不需要檢測 UTF-8 或者改變你的代碼。可以將 UTF-8 看做 ASCII 的一個(gè)超集。
UTF-8 不是雙字節(jié)格式,但是它是 Unicode 的標(biāo)準(zhǔn)編碼。
TinyXML 不使用和直接同時(shí)支持 wchar, TCHAR, 或者 微軟的 _UNICODE。
用 Unicode 指代 UTF-16 是不合適的,UTF-16 是 Unicode 的一種寬字節(jié)編碼方式。這引起了混亂。
對于 high-ascii 語言,TinyXML 可以處理所有的語言,同時(shí),只要 XML 被編碼成 UTF-8。這樣有些滑稽,老的程序員和操作系統(tǒng)趨向于使用 default 和 traditional 的代碼頁。許多應(yīng)用可以輸出 UTF-8,但是老或者頑固的應(yīng)用是以默認(rèn)的代碼頁輸出文本的。
例如,日文系統(tǒng)傳統(tǒng)上使用 SHIFT-JIS 編碼方式。TinyXML 不能讀取 SHIFT-JIS 編碼的文本。一個(gè)好的編輯器可以打開 SHIFT-JIS 的文件并將其保存為 UTF-8 的編碼方式。
http://skew.org/xml/tutorial 對轉(zhuǎn)換編碼做了很好的介紹。
utf8test.xml 是一個(gè)包含英語、西班牙語、俄語和簡體中文的 XML 文件。utf8test.gif 是一個(gè)在 IE 中渲染的 XML 文件的屏幕截圖。注意如果你的電腦里沒有正確的字體,你不能看到輸出的 GIF 文件,即便你正確地將其解析。也要主要終端的西方代碼頁輸出,以至于 Print() 或者 printf() 不能正確地顯示文件。這不是 TinyXML 的 bug,而是操作系統(tǒng)的問題。沒有數(shù)據(jù)丟失或者被 TinyXML 破壞。終端不能渲染 UTF-8。
6。3 實(shí)體(Entities)
TinyXML 組織預(yù)定義的字符實(shí)體,即特殊字符。也就是:
& &
< <
> >
" "
' '
當(dāng) XML 文檔被讀取和轉(zhuǎn)換成 UTF-8 等同物時(shí),這些字符被辨識。比如這樣的 XML 文本:
Far & Away
當(dāng)從 TiXMLText 對象中使用 Value() 查詢 “Far & Away”。作為 & 符號寫回到 XML 流/文件。老的 TinyXML 版本保留字符實(shí)體,但是新版本將它們轉(zhuǎn)換為字符。
另外,任何字符都可以用它的 Unicode 指定:" " 或 " " 都可以指代非中斷空白字符。
6.4 打印(Printing)
TinyXML 可以以許多不同的方式打印輸出,這些方式既有優(yōu)勢也有限制。
1)。Print( FILE* ). 標(biāo)準(zhǔn) C 流,包括 C 文件和編制輸出。
漂亮的輸出,但是你不能對輸出選擇進(jìn)行控制。
輸出被指向 FILE 對象,所以在 TinyXML 代碼中沒有預(yù)先的內(nèi)存。
Print() 和 SaveFile()
2)。opeartor<<。輸出到 C++ 流。
繼承標(biāo)準(zhǔn) C++ 輸入輸出流
網(wǎng)絡(luò)打印,便于網(wǎng)絡(luò)傳輸和在 C++ 對象間傳遞 XML,但是難以閱讀。
3)。TiXmlPrinter。輸出到 std::string 或者 內(nèi)存緩沖區(qū)。
API 不簡潔
將來的打印選擇將被添加
將來的版本中,隨著打印被重定義和擴(kuò)展,打印可能改變。
6。5 流(Streams)
有 TIXML_USE_STL 的 TinyXML 支持 C++ 流(operator <<,>>),像 C(FILE*) 流似的。有一些你需要注意的不同。
1)。C 風(fēng)格輸出
以 FILE* 為基礎(chǔ)
Print(), SaveFile()
產(chǎn)生格式化輸出,伴隨大量的空白鍵,看可能便于閱讀。非常快速,容忍格式不好的 XML 文檔。例如,一個(gè)含有兩個(gè)根元素和兩個(gè)聲明的 XML 文檔仍然可以被打印。
2)。C 風(fēng)格輸入
建立在 FILE* 基礎(chǔ)上
Parse(), LoadFile()
快速的,格式任意。在你不需要 C++ 流時(shí)使用。
3)。C++ 風(fēng)格輸出
建立在 std::ostream 基礎(chǔ)上
operator<<
生成壓縮輸出,便于網(wǎng)絡(luò)傳輸而不是易于閱讀。依賴于你系統(tǒng)中的輸出流類的實(shí)現(xiàn),可能很很慢。XML 文檔必須有很好的格式:一個(gè)文檔應(yīng)該包含一個(gè)正確的根元素。額外的根層元素不能被流輸出。
4)。C++ 風(fēng)格輸入
建立在 std::istream 基礎(chǔ)上
operator>>
從流中讀取 XML,使它利于網(wǎng)絡(luò)傳輸。XML 文檔虛實(shí)完整的。TinyXML 假設(shè) XML 數(shù)據(jù)時(shí)完整的,當(dāng)其讀取了根元素。其他的有多個(gè)根元素的錯誤構(gòu)造不能被正確讀取。operator<< 比 Parse 慢,這與 STL 的實(shí)現(xiàn)和 TinyXML 的限制有關(guān)。
6。6 空白符(White space)
空白字符被保持還是被壓縮在不同的條件下并不統(tǒng)一。例如,用 '_' 代表一個(gè)空白符,對于 “Hello____world”。HTML 和一些 XML 解析器中,其被翻譯成 “Hello_world”。一些 XML 解析器將其保持不變“Hello___world”。另一些將 __Hello___world__ 轉(zhuǎn)換成 Hello___world。
這個(gè)問題還沒有被解決的令我滿意。TinyXML 支持前兩種方法。TiXmlBase::SetCondenseWhiteSpace( bool ) 設(shè)置期望的操作。默認(rèn)的是壓縮空白符。
如果你改變默認(rèn)的方式,你應(yīng)該在費(fèi)用解析 XML 數(shù)據(jù)的調(diào)用之前調(diào)用 TiXmlBase::SetCondenseWhiteSpace( bool )。我不推薦當(dāng)他已被建立了還去改變它。
6。7 處理(Handles)
用穩(wěn)定的方式瀏覽一個(gè) XML 文檔,檢測函數(shù)調(diào)用的返回值是不是 null 很重要。一個(gè)錯誤安全的實(shí)現(xiàn)產(chǎn)生的代碼像這樣一樣:
TiXmlElement* root = document.FirstChildElement( "Document" );
if ( root )
{
TiXmlElement* element = root->FirstChildElement( "Element" );
if ( element )
{
TiXmlElement* child = element->FirstChildElement( "Child" );
if ( child )
{
TiXmlElement* child2 = child->NextSiblingElement( "Child" );
if ( child2 )
{
// Finally do something useful.
Handles 可以把這些代碼清除。使用 TiXmlHandle 類,前面的這些代碼可以縮減為:
TiXmlHandle docHandle( &document );
TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
if ( child2 )
{
// do something useful
這種方式更容易處理。可以查看 TiXmlHandle 來獲取更多的信息。
6。8 行和列追蹤(Row and Column tracking)
能夠追蹤節(jié)點(diǎn)和屬性在源文件中的原始位置對于一些應(yīng)用是非常重要的。另外,知道解析錯誤發(fā)生在哪里可以及時(shí)地保存。
TinyXML 可以追蹤所有節(jié)點(diǎn)和屬性在文本文件中的行和列。TiXmlBase::Row() 和 TiXmlBase::Column() 函數(shù)返回節(jié)點(diǎn)在源文本文件中的位置。正確的制表符可以在 TiXmlDocument::SetTabSize() 中配置。
7。使用和安裝
編譯和運(yùn)行 xmltest
這里提供了 Linux 的 Makefile 文件和 Windows Visual C++ 下的 .dsw 文件。正常的編譯和運(yùn)行。它將要向你的硬盤寫入 demotest.xml 文件和向屏幕產(chǎn)生輸出。它還測試沿著 DOM 用不同的技術(shù)打印已發(fā)現(xiàn)的節(jié)點(diǎn)的數(shù)目。
Linux makefile 非常通用,可以在許多系統(tǒng)中運(yùn)行,它已經(jīng)在 mingw 和 MacOSX 中測試。你不需要運(yùn)行 'make depend'。這種依賴已經(jīng)被硬編碼。
7。1 Windows VC6 工程文件
tinyxml: tinyxml library, non-STL
tinyxmlSTL: tinyxml library, STL
tinyXmlTest: test app, non-STL
tinyXmlTestSTL: test app, STL
7。2 Makefile
在 makefile 文件中,你可以設(shè)置:
PROFILE, DEBUG 和 TINYXML_USE_STL。細(xì)節(jié)在 makefile 中。
在 tinyxml 文件夾中,鍵入 'make clean' 和 'make'。可執(zhí)行文件 'xmltest' 將被產(chǎn)生。
7。3 在應(yīng)用中使用
將 tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp 和 tinystr.h 添加到你的工程文件或 makefile 中。就是這樣!它應(yīng)該可以在任何相容的 C++ 系統(tǒng)中得到編譯。你不需要異常處理機(jī)制或運(yùn)行時(shí)類型識別(RTTI)。
8。TinyXML 怎樣工作(How TinyXML works)
一個(gè)來自可能是最好的開始方法。例如:
<?xml version="1.0" standalone=no>
<!-- Our to do list data -->
<ToDo>
<Item priority="1"> Go to the <bold>Toy store!</bold></Item>
<Item priority="2"> Do bills</Item>
</ToDo>
它不是一個(gè) To Do 列表,但是它將要這么做。讀取這個(gè)文件(demo.xml)你可以產(chǎn)生一個(gè)文檔,并解析它:
TiXmlDocument doc( "demo.xml" );
doc.LoadFile();
這樣就可以工作了。現(xiàn)在讓我們觀察一些行,并且他們是怎樣與 DOM 相關(guān)聯(lián)的。
<?xml version="1.0" standalone=no>
第一行是一個(gè)聲明,轉(zhuǎn)向 TiXmlDeclaration 類。它是這個(gè)文檔節(jié)點(diǎn)的第一個(gè)孩子。
這是 TinyXML 解析的唯一的直接/特殊的標(biāo)簽。一樣直接標(biāo)簽被存在 TiXmlUnknown 類中。這樣當(dāng)存儲到硬盤中時(shí)命令不會丟失。
<!-- Our to do list data -->
這是一個(gè)注釋。這個(gè)將生成一個(gè) TiXmlComment 對象。
<ToDo>
"ToDo" 標(biāo)簽定義一個(gè) TiXmlElement 對象。這個(gè)對象沒有任何屬性,但是它包含兩個(gè)元素。
<Item priority="1">
生成另一個(gè) TiXmlElement 對象,它是 "ToDo" 元素的孩子。這個(gè)元素有一個(gè)屬性,屬性名是 "priority",屬性值為 "1".
Go to the
這是一個(gè) TiXmlText 對象。這是一個(gè)葉子節(jié)點(diǎn),不能包含任何其他的節(jié)點(diǎn)。它是 "Item" TiXmlElement 對象的孩子。
<bold>
另一個(gè) TiXmlElement 對象,這是 "Item" 元素的孩子。
等。
觀察整個(gè)對象樹,你可以得到:
TiXmlDocument "demo.xml"
TiXmlDeclaration "version='1.0'" "standalone=no"
TiXmlComment " Our to do list data"
TiXmlElement "ToDo"
TiXmlElement "Item" Attribtutes: priority = 1
TiXmlText "Go to the "
TiXmlElement "bold"
TiXmlText "Toy store!"
TiXmlElement "Item" Attributes: priority=2
TiXmlText "Do bills"
9。文檔(Documentation)
文檔用 Doxygen 建立,使用的 'dox' 配置文件。
10。協(xié)議
TinyXML 是在 zlib 協(xié)議下發(fā)布的。
這個(gè)軟件提供了 "as-is",沒有任何明確的或隱含的保證。作者不詳任何的有本軟件產(chǎn)生的損害負(fù)責(zé)。
任何人可以使用本軟件已達(dá)到任何目的,包括商業(yè)應(yīng)用,可以修改它并重新發(fā)布,但是要服從一下的限制:
1)。這個(gè)軟件的起源不能被誤傳;你不能聲稱是你寫的這個(gè)最初軟件。如果你使用這個(gè)軟件在你的產(chǎn)品中,應(yīng)該在產(chǎn)品的文檔的文檔中有對這個(gè)軟件的感謝,但這不是必須的。
2)。修改源代碼必須明白的標(biāo)注清楚,不可以將其誤傳為原來的代碼。
3)。這個(gè)通知可以從任何源代碼的發(fā)布中不被刪除或修改。
11。參考資料(References)
World Wide Web 協(xié)會是 XML 的定義標(biāo)注主體,他們的網(wǎng)頁中包含了大量的信息。
定義說明書可以在 http://www.w3.org/TR/2004/REC-xml-20040204 找到。
我也推薦 Robert Eckstein 寫的 XML Pocket Reference 這本書,由 O'Reilly 出版社出版,你這個(gè)在這本書獲得全部入門的東西。
12。貢獻(xiàn)者,聯(lián)系,一個(gè)簡短的歷史(Contributors, Contacts, and a Brief History)
非常感謝每一位提出建議、錯誤、想法和鼓勵的人。它幫助并使得這個(gè)工程有趣。特別感謝那些在網(wǎng)頁上保持它一直充滿活力的貢獻(xiàn)者們。
太多的人攻陷發(fā)現(xiàn)的錯誤和想法,以至于我們在 changes.txt 文件中列出應(yīng)得的感謝。
TinyXML 最初是由 Lee Thomason 寫的。(文檔中的“我”。)Lee 在 Yves Berquin、Andraw Ellerton 和 TinyXML 社區(qū)的幫助下審查改動和發(fā)布最新的版本。
我們感謝你的建議,并非常想知道你是否使用 TinyXML。希望你喜歡它并且發(fā)現(xiàn)它很有用。
歡迎提出問題,發(fā)表評論和程序錯誤。你也可以聯(lián)系我們:
http://www.sourceforge.net/projects/tinyxml
Lee Thomason, Yves Berquin, Andrew Ellerton
posted on 2011-04-18 21:30
unixfy 閱讀(1224)
評論(0) 編輯 收藏 引用