1、概要介紹一下:
嘗試了tinyxml,rapidxml,libxml2等3中第3方庫,前兩者相對較為輕量級,libxml2非常完善,強大。
這是網上總結出來的優缺點:
1、tinyxml當節點內容的空而使用GetText()方法時候會出錯
2、rapidxml編碼問題不是特別好
3、libxml2對記憶體釋放要求較高,否則時常遇到core dump.
TinyXML是一個開源的解析XML的解析庫,能夠用於C++,能夠在Windows或Linux中編譯。這個解析庫的模型通過解析XML檔案,然後在記憶體中產生DOM模型,從而讓我們很方便的遍曆這棵XML樹。
DOM模型即文件物件模型,是將整個文檔分成多個元素(如書、章、節、段等),並利用樹型結構表示這些元素之間的循序關聯性以及嵌套內含項目關聯性。
先介紹一下在TinyXML中,根據XML的各種元素來定義了一些類:
TiXmlBase:整個TinyXML模型的基類。
TiXmlAttribute:對應於XML中的元素的屬性。
TiXmlNode:對應於DOM結構中的節點。
TiXmlComment:對應於XML中的注釋。
TiXmlDeclaration:對應於XML中的申明部分,即<?versiong="1.0" ?>。
TiXmlDocument:對應於XML的整個文檔。
TiXmlElement:對應於XML的元素。
TiXmlText:對應於XML的文字部分。
TiXmlUnknown:對應於XML的未知部分。
TiXmlHandler:定義了針對XML的一些操作。
tinyxml類圖:
那麼這些元素是如何對應的呢? 例如
<?xml version="1.0" encoding="utf-8"?>
<!– Our to do list data –>
<ToDo>
<Item priority="1"> Go to the <bold>Toy store!</bold></Item>
<Item priority="2"> Do bills</Item>
</ToDo>
整個對象樹:
TiXmlDocument "demo.xml"
TiXmlDeclaration version="1.0" encoding="utf-8"?>
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"
在tinyXML中,用FirstChild("名字")尋找節點時,調用FirstChild函數的節點與要尋找的節點必須成“父子關係”。
2、實現使用元素
如下是一個XML片段:
<Persons>
<Person ID="1">
<name>周星馳</name>
<age>40</age>
</Person>
<Person ID="2">
<name>白晶晶</name>
<age>30</age>
</Person>
</Persons>
一、讀取XML
//建立一個XML的文檔對象。
TiXmlDocument *myDocument = new TiXmlDocument("填上你的Xml檔案名稱");
myDocument->LoadFile();
//獲得根項目,即Persons。
TiXmlElement *RootElement = myDocument.RootElement();
//輸出根項目名稱,即輸出Persons
cout << RootElement->Value() << endl;
//獲得第一個Person節點。
TiXmlElement *FirstPerson = RootElement->FirstChildElement();
//獲得第一個Person的name節點和age節點和ID屬性。
TiXmlElement *NameElement = FirstPerson->FirstChildElement();
TiXmlElement *AgeElement = NameElement->NextSiblingElement();
TiXmlAttribute *IDAttribute = FirstPerson->FirstAttribute();
//輸出第一個Person的name內容,即周星馳;age內容,即40;ID屬性,即1。
cout << NameElement->FirstChild()->Value << endl;
cout << AgeElement->FirstChild()->Value << endl;
cout << IDAttribute->Value() << endl;
二、產生XML內容
//建立一個XML的文檔對象。
TiXmlDocument *myDocument = new TiXmlDocument();
//建立一個根項目並串連。
TiXmlElement *RootElement = new TiXmlElement("Persons");
myDocument->LinkEndChild(RootElement);
//建立一個Person元素並串連。
TiXmlElement *PersonElement = new TiXmlElement("Person");
RootElement->LinkEndChild(PersonElement);
//設定Person元素的屬性。
PersonElement->SetAttribute("ID", "1");
//建立name元素、age元素並串連。
TiXmlElement *NameElement = new TiXmlElement("name");
TiXmlElement *AgeElement = new TiXmlElement("age");
PersonElement->LinkEndChild(NameElement);
PersonElement->LinkEndChild(AgeElement);
//設定name元素和age元素的內容並串連。
TiXmlText *NameContent = new TiXmlText("周星馳");
TiXmlText *AgeContent = new TiXmlText("40");
NameElement->LinkEndChild(NameContent);
AgeElement->LinkEndChild(AgeContent);
//儲存到檔案
myDocument->SaveFile("要儲存的xml檔案名稱");
這樣,便建立了一個如下的xml檔案:
<Persons>
<Person ID="1">
<name>周星馳</name>
<age>40</age>
</Person>
</Persons>
3、舉例說明一下常見用法,以我當前做的項目取程式碼片段說明一下:
1、解析如下xml內容
<?xml version="1.0" encoding="utf-8"?>
<server ip = "" port = "" name = "" version = ""/>
核心解析代碼:
for (element = document.FirstChildElement(); element; element
= document.NextSiblingElement()) {
while (sAttr != NULL) {
name = sAttr->Name();
value = sAttr->Value();
if (xmlstr_compare("ip", name)) {
if ('0' <= value[0] && value[0] <= '9') {
bc.ip = xml_inet_addr(value);
} else {
bc.ip = IP_INADDR_ANY;
}
} else if (xmlstr_compare("port", name)) {
bc.port = atoi(value);
} else if (xmlstr_compare("name", name)) {
memcpy((void*) bc.name, value, 16);
} else if (xmlstr_compare("version", name)) {
memcpy((void*) bc.version, value, 16);
}
sAttr = sAttr->Next();
}
}
2、如下的內容解析
<?xml version="1.0" encoding="utf-8"?>
<request id="" type="addeventhub">
<item name="touchscreen" multed = "16" width="" height="" dpi="" componentid="1"/>
<item name="mouse" width="" height="" dpi="" componentid="2"/>
<item name="keyboard" componentid="3" />
<item name="dpad" componentid="4"/>
<item name="gamepad" componentid="5"/>
<item name="trackball" componentid="6"/>
</request>
核心解析代碼:
while (sAttr != NULL) {
name = sAttr->Name();
value = sAttr->Value();
...
sAttr = sAttr->Next();
}
itemelement = element->FirstChildElement();
while (itemelement != NULL) {
int itemNo = -1;
name = itemelement->GetText();
value = itemelement->Value();
itemAttr = itemelement->FirstAttribute();
while (itemAttr != NULL) {
name = itemAttr->Name();
value = itemAttr->Value();
...
itemAttr = itemAttr->Next();
}
}
3、如何拼包
有如下xml buff內容,如何進行拼包呢?
<?xml version="1.0" encoding="utf-8"?>
<server ip = "" port = "" name = "" version = ""/>
xml_udp_bc *xbc = (xml_udp_bc*)xml_param->param;
if(xml_param->head_flag == 1){
p += sprintf(p, xml_head);
}
p += sprintf(p, "<server ip = \" ");
p += sprintf(p, xml_iptostr(xbc->ip));
p += sprintf(p, "\"");
p += sprintf(p, " port = \"%d\"",xbc->port);
p += sprintf(p, " name = \"%s\"",xbc->name);
p += sprintf(p, " version = \"%s\"",xbc->version);
p += sprintf(p, "/>");
對於拼包的話可以使用xml,但具體項目中沒有使用這麼複雜的東東,所以直接以字串拼接好了
ok,簡單的使用了一下非常簡單!