天天看點

實戰TinyXML

實戰TinyXML

作者:裕作

(出處:http://blog.csdn.net/KyosukeNo1)

這幾天在埋頭寫自己的3D檔案浏覽器(稍後釋出),突發奇想的要把自己的内部格式轉化成XML,于是,把以前在研究所時用過的ExPat翻了出來。 ExPat是基于事件的XML解釋器,速度挺快的,但結構方面有點不敢恭維--當年寫配置檔案的導出導入部分花了我足足1個星期!而且由于它是基于事件發生的次序(SAX),似乎有時會發生一些無法控制的情況--例如進入某Level後忘了記錄,結果……後面的程式全部死掉!這時想起同僚之前推薦的 TinyXML,結果……用了不到3小時就把我的檔案導出來了~~呵呵。在閱讀本文之前,請先看看我Blog裡轉貼的《TinyXML學習筆記》,相信它能給各位一個關于TinyXML的初步概念。

言歸正傳,本文目的在于補全之前《TinyXML學習》的不足,盡量把常用的示例代碼列出讓大家參考。此外,在本篇最後會給出一個完整的檔案讀寫例子,供讀者參考。

1. 程式設計環境的設定。建立一個項目,起名叫TestTXML。到http://sourceforge.net/projects/tinyxml/ 下載下傳TinyXML的官方例子,并編譯第一個Project tinyxml(注意,最好編譯Release的版本,代碼比較小。然後把生成的tinyxml.lib(如果是Debug版本,叫tinyxmld.lib)連同tinystr.h和tinyxml.h一起Copy到TestTXML項目的目錄中。在TestTXML項目裡的頭檔案加入對TinyXML的引用:

#pragma comment(lib,"tinyxml.lib") // 連結Library

#i nclude "tinyxml.h" // TinyXML的頭檔案

2. 建立一個XML檔案:

char* sFilePath = "ikk_doc.xml"; // 檔案名稱

TiXmlDocument xmlDoc( sFilePath ); // 建立一個XML檔案

TiXmlDeclaration Declaration( "1.0","gb2312", "yes" ); // 聲明XML的屬性

xmlDoc.InsertEndChild( Declaration ); // 寫入基本的XML頭結構

xmlDoc.SaveFile(); // 把XML檔案寫入硬碟

這時,在硬碟上的TestXML項目目錄裡,ikk_doc.xml檔案已經被建立出來了。

3. 在XML檔案裡插入Element

所謂的Element,就是在XML裡面的Tag,例如在<resume name=”裕作”>履歷内容</resume>中,“Resume”就是Element的名字,上述的整個字元串就是一個Element。在TinyXML裡,插入Element的步驟如下:

TiXmlElement* pElm = NULL;

pElm = new TiXmlElement( "resumes" ); //定義目前的子節點 pElmParent.InsertEndChild( *pElm ); // 把子節點插入父節點中

4. 在element裡插入屬性。在剛才例子中,name=”裕作”就是Resume的屬性,其中name是屬性的名字,”裕作”是屬性的值。在目前子節點内插入屬性的方法如下:

pElm->SetAttribute( "name", resume.sName );

5. 在XML裡插入文本。在<resume name=”裕作”>履歷内容</resume>中,“履歷内容”就是一段文本,事實上,在TinyXML裡,它是被當作一個Text類型的子節點來插入的。還而言之,就是在Resume的子節點中,插入這個Text子節點。插入例子如下:

TiXmlText* pText = NULL;

pText = new TiXmlText( "履歷内容" ); // 定義文本的内容

pElmChild->InsertEndChild( *pText ); //把text子節點插入父節點中

在具備了以上背景知識之後,我們已經可以用TinyXML讀寫一個XML檔案了。本文最後的程式将寫入,然後重新讀取一個XML檔案到我們的結構裡。這個XML檔案的内容如下:

<?xml version="1.0" encoding="GB2312" ?>

<resumes>

<resume name="裕作">

<gender>男</gender>

<age>26</age>

<skills num="2">

<skill level="99">程式設計</skill>

<skill level="1">吹牛</skill>

</skills>

</resume>

<resume name="裕作 The Great">

<gender>男</gender>

<age>0</age>

<skills num="1">

<skill level="100">程式設計</skill>

</skills>

</resume>

</resumes>

以下程式将建立ikk_doc.xml檔案,然後重新把内容讀取進記憶體:

#pragma comment(lib,"tinyxml.lib")

#i nclude "string.h"

#i nclude "stdio.h"

#i nclude "tinyxml.h"

#define XML_FILE "ikk_doc.xml"

#define NAME_LENGTH 256 // 名字類字元的配置設定長度

#define SAFE_DELETE(x) {if(x) delete x; x=NULL;} // 安全删除new配置設定出來的變量空間

#define SAFE_DELETE_ARRAY(x) {if(x) delete[] x; x=NULL;} // 安全删除new配置設定出來的數組空間

#define XML_HEADER "<?xml version=/"1.0/" encoding=/"GB2312/" ?>" // XML檔案頭的定義

typedef unsigned int uint32;

// 技能的結構

typedef struct skill_s {

uint32 nLevel; // 技能的程度

char sName[ NAME_LENGTH ]; // 技能的名稱

skill_s() {

nLevel = 0;

sName[0] = 0;

}

} skill_t;

// 履歷的結構

typedef struct resume_s {

char sName[ NAME_LENGTH ]; // 名字

bool isMan; // 是否男性

uint32 nAge; // 年齡

uint32 nNumSkill; // 技能的數目

skill_t* pSkill; // 技能的結構

resume_s() {

sName[0] = 0;

isMan = false;

nAge = 0;

nNumSkill = 0;

pSkill = NULL;

}

} resume_t;

void exportSkill( TiXmlElement* pElmParent, skill_t skill )

{

int i;

char sBuf[NAME_LENGTH]; // 一個臨時存放的字元串

TiXmlElement* pElm = NULL; // 一個指向Element的指針

TiXmlText* pText = NULL; // 一個指向Text的指針

pElm = new TiXmlElement( "skill" );

// 插入等級(以屬性形式)

sprintf( sBuf, "%d", skill.nLevel ); // 把Skill的登記變成字元串臨時存進sBuf裡

pElm->SetAttribute( "level", sBuf ); // 把等級插入Skill裡

// 插入技能名稱(以子Element形式)

pText = new TiXmlText( skill.sName ); // 建立一個Skill的子Element(一個Text形式的子元素)

pElm->InsertEndChild( *pText ); // 把這個Skill的子Element插入Skill