您好,登錄后才能下訂單哦!
【嘮叨】
XML 即 可擴展標記語言,在游戲開發中,常用于保存游戲數據信息,如最高分、游戲等級等信息,和描述一些資源等。
加載動畫的plist文件、瓦片地圖編輯器到處的地圖格式tmx文件,實際上都是特定格式的xml文件。
另外 UserDefault 單例類保存的數據,也是存儲在xml文件中的。
Cocos2d-x 已經加入了 tinyxml2庫 用于xml的解析。3.x版本位于external/tinyxml2下。
本節要介紹的就是:如何使用 tinyxml2庫 來操作處理xml文件。
【參考】
http://www.w3school.com.cn/xml/index.asp (W3School)
http://cn.cocos2d-x.org/tutorial/show?id=1225 (【官方文檔】Cocos2d-x xml解析)
http://blog.csdn.net/w18767104183/article/details/28856829 (TinyXml 解析 XML)
【XML簡介】
摘自:http://www.w3school.com.cn/xml/index.asp
1、什么是XML?
> XML 指可擴展標記語言(EXtensible Markup Language)。
> XML 是一種標記語言,很類似 HTML。
> XML 的設計宗旨是:傳輸數據,而非顯示數據。
> XML 標簽沒有被預定義,您需要自行定義標簽。
> XML 被設計為具有自我描述性。
> XML 是 W3C 的推薦標準。
2、XML的一個例子
先來看一個簡單的例子。
// <?xml version="1.0" encoding="UTF-8"?> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note> //
代碼分析:
(1)第一行是 XML 聲明。它定義 XML 的版本(1.0)和所使用的編碼(UTF-8字符集)。
(2)下一行描述文檔的根元素(像在說:“本文檔是一個便簽”):<note> 。
(3)接下來 4 行描述根元素的 4 個子元素(to,from,heading,body)。
(4)最后一行定義根元素的結尾:</note> 。
以上是一個簡單的XML文檔。可以發現XML的語法很簡單,標簽沒有被預定義,都是自己定義的標簽。并且元素可以有子元素,這就形成了一個樹形結構。
3、XML樹結構
> XML 文檔必須包含根元素,該元素是所有其他元素的父元素。
> 所有元素均可擁有 多個子元素。
> 所有元素均可擁有 文本內容和屬性(類似 HTML 中)。
> 父、子以及同胞等術語用于描述元素之間的關系:父元素擁有子元素;相同層級上的子元素成為同胞(兄弟或姐妹)。
> XML 文檔中的元素形成了一棵文檔樹的結構。這棵樹從“根部”開始,并擴展到樹的“枝葉”。
// <root> <child1> <subchild1>.....</subchild1> <subchild2>.....</subchild2> ..... </child1> <child2> <subchild1>.....</subchild1> <subchild2>.....</subchild2> ..... </child2> ..... </root> //
如下所示,一個樹結構的實例:
它表示了XML中的一本書:
> 根元素是 <bookstore>。文檔中的所有 <book> 元素都被包含在 <bookstore> 中 。
> 并且<book> 元素也有 4 個子元素:<title>、< author>、<year>、<price> 。
> category、lang均為元素的屬性。
> <book>的4個子元素。
// <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="WEB"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore> //
4、語法規則
(1)XML 文檔必須有根元素。
(2)XML 文檔必須有結束標簽。( <p>This is a paragraph.</p> )
(3)XML 標簽對大小寫敏感。(標簽 <Letter> 與 <letter> 是不同的)
(4)XML 元素必須被正確的嵌套。
// <!-- 錯誤的嵌套 --> <b><i>This text is bold and italic</b></i> <!-- 正確的嵌套 --> <b><i>This text is bold and italic</i></b> //
(5)XML 屬性值必須加引號。(單引號' '、雙引號" " ,均可以)
// <note date="08/08/2008"> <note date='08/08/2008'> //
4.1、注釋
在 XML 中編寫注釋的語法與 HTML 的語法很相似:
// <!-- This is a comment --> //
4.2、保留空格
HTML會把多個連續的空格字符裁減(合并)為一個。
而在XML中,空格不會被刪節。
// content :Hello my name is David. HTML :Hello my name is David. XML :Hello my name is David. //
4.3、實體引用
在 XML 中,一些字符擁有特殊的意義。
如果你把字符 "<" 放在 XML 元素中,會發生錯誤,這是因為解析器會把它當作新元素的開始。
這樣會產生 XML 錯誤:
<message>if salary < 1000 then</message>
為了避免這個錯誤,請用實體引用來代替 "<" 字符:
<message>if salary < 1000 then</message>
在 XML 中,有 5 個預定義的實體引用:
< | < | 小于 |
> | > | 大于 |
& | & | 和號 |
' | ' | 單引號 |
" | " | 雙引號 |
4.4、XML元素
XML 元素指的是從(且包括)開始標簽,直到(且包括)結束標簽的部分。
> 元素可包含:其他元素、文本、或者兩者的混合物。
> 元素也可以擁有屬性。
// <bookstore> <book category="CHILDREN"> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore> //
在上例中:
<bookstore> 和 <book> 都擁有元素內容,因為它們包含了其他元素。
<author> 只有文本內容,因為它僅包含文本。
在上例中,只有 <book> 元素擁有屬性(category="CHILDREN")。
4.5、XML屬性
XML 元素可以在開始標簽中包含屬性,類似 HTML。屬性 (Attribute) 提供關于元素的額外(附加)信息。
屬性通常提供:不屬于數據組成部分的信息。
在下面的例子中,文件類型與數據無關,但是對需要處理這個元素的軟件來說卻很重要。
PS:屬性的值必須加引號(單引號、雙引號,均可以)。
// <file type="gif">computer.gif</file> //
4.6、元素 vs. 屬性
有時候屬性和元素均可以提供相同的信息。
如下所示:
// <person sex="female"> <name>Alice</name> </person> <person> <sex>female</sex> <name>Alice</name> </person> //
這樣寫雖然可以,但是這樣的定義會造成數據的混亂,并且不易閱讀(想獲取數據信息,到底是訪問屬性還是元素?)
所以最好的做法是:
> 屬性:用來提供不屬于數據組成部分的信息。如圖片格式、書籍分類、ID 索引等。
> 元素:用來描述數據信息。
4.7、元素的命名規則
XML 元素必須遵循以下命名規則:
> 名稱可以含字母、數字以及其他的字符。
> 名稱不能以數字或者標點符號開始。
> 名稱不能以字符 “xml”(或者 XML、Xml)開始。
> 名稱不能包含空格。
可使用任何名稱,沒有保留的字詞。
XML元素的命名習慣:
> 使名稱具有描述性。使用下劃線的名稱也很不錯。
> 名稱應當比較簡短,比如:<book_title>,而不是:<the_title_of_the_book>。
> 避免 "-" 字符。如果按照這樣的方式命名:"first-name",一些軟件會認為你需要提取第一個單詞。
> 避免 "." 字符。如果按照這樣的方式命名:"first.name",一些軟件會認為"name"是對象"first"的屬性。
> 避免 ":" 字符。冒號會被轉換為命名空間來使用。
【tinyxml2】
Cocos2d-x 已經加入了 tinyxml2庫 用于xml的解析。
3.x版本位于external/tinyxml2下。
0、相關類
XMLNode :表示一個節點,包含一般方法,如訪問自節點、兄弟節點、編輯自身、編輯子節點。
XMLDocument :表示整個XML文檔,不對應其中某個特定的節點。
XMLElement :表示元素節點,可以包含子節點XMLElement、和屬性XMLAttribute。
XMLAttribute :表示一個元素的屬性。
XMLText :表示文本節點。
XMLComment :表示注釋。
XMLDeclaration :表示聲明。
1、添加頭文件
// #include "tinyxml2/tinyxml2.h" using namespace tinyxml2; //
2、XML數據解析
XML文檔如下:
// <?xml version="1.0" encoding="UTF-8"?> <person> <student id="1111"> <name>Alice</name> <age>20</age> </student> <teacher id="2222"> <name>Bob</name> <age>30</age> </teacher> </person> //
XML解析使用舉例:
// //[0] 文件路徑 std::string path = "/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml"; //[1] 創建管理XML文檔的對象:XMLDocument XMLDocument* doc = new XMLDocument(); //[2] 解析xml文件 // 方式一: // Data data = FileUtils::getInstance()->getDataFromFile(path.c_str()); // XMLError errorID = doc->Parse((const char*)data.getBytes()); // 方式二: // std::string data = FileUtils::getInstance()->getStringFromFile(path.c_str()); // XMLError errorID = doc->Parse(data.c_str()); // 方式三: XMLError errorID = doc->LoadFile(path.c_str()); //[3] 判斷是否解析錯誤 if (errorID != 0) { CCLOG("Parse Error!"); return; } //[4] 獲取根元素 <person> XMLElement* root = doc->RootElement(); //[5] 獲取子元素信息 //[5.1] 遍歷root的子元素 <student> , <teacher> // FirstChildElement() : 獲取 root 的第一個子元素 // NextSiblingElement() : 獲取 chd 的下一個兄弟元素 for (XMLElement* chd = root->FirstChildElement(); chd; chd = chd->NextSiblingElement()) { //[5.2] 獲取子元素名稱 CCLOG("chd : %s", chd->Name()); //[5.3] 遍歷子元素的屬性 id // FirstAttribute() : 獲取 chd元素 的第一個屬性 // Next() : 獲取 chd元素的attr屬性 的下一個屬性 for (const XMLAttribute* attr = chd->FirstAttribute(); attr; attr = attr->Next()) { // Name() : 屬性名稱 // Value() : 屬性值 CCLOG("chd_attr : %s , %s", attr->Name(), attr->Value()); } // 也可以通過屬性名稱,來獲取屬性值 // CCLOG("id = %s", chd->Attribute("id")); //[5.4] 遍歷子元素chd的子元素 <name> , <age> for (XMLElement* e = chd->FirstChildElement(); e; e = e->NextSiblingElement()) { // 子元素e 為文本內容 // GetText() : 文本內容 CCLOG("e : %s , %s", e->Name(), e->GetText()); } } //[6] 釋放內存 delete doc; //
控制臺輸出結果:
3、XML數據存儲
以上面解析的XML文檔為例,我們通過代碼來生成相應的XML文檔,并保存到xml文件中。
生成XML文檔并保存,舉例:
// //[0] 文件路徑 std::string path = "/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml"; //[1] 創建管理XML文檔的對象:XMLDocument XMLDocument* doc = new XMLDocument(); // <!-- begin --> //[2] 創建XML聲明,并連接到XML文檔中 XMLDeclaration* declare = doc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\""); doc->LinkEndChild(declare); // 添加到文檔尾部 //[3] 創建注釋,并連接到XML文檔中 XMLComment* comment = doc->NewComment("this is xml comment"); doc->LinkEndChild(comment); //[4] 創建根節點,并連接到XML文檔 XMLElement* root = doc->NewElement("person"); doc->InsertEndChild(root); // 與LinkEndChild()功能相同 //[5] 創建兩個子元素,并連接到root元素中,作為root的子節點 XMLElement* student = doc->NewElement("student"); XMLElement* teacher = doc->NewElement("teacher"); root->LinkEndChild(student); // 添加到root子元素中 root->LinkEndChild(teacher); // 添加到root子元素中 //[6] 設置/添加 <student>、<teacher> 的屬性值 student->SetAttribute("id", "1111"); teacher->SetAttribute("id", "2222"); //[7] 創建子元素,并連接到<student>、<teacher>元素中,作為子節點 XMLElement* name1 = doc->NewElement("name"); XMLElement* name2 = doc->NewElement("name"); XMLElement* age1 = doc->NewElement("age"); XMLElement* age2 = doc->NewElement("age"); student->LinkEndChild(name1); student->LinkEndChild(age1); teacher->LinkEndChild(name2); teacher->LinkEndChild(age2); //[8] 創建文本內容,并添加到<name>、<age>元素中,作為文本內容 XMLText* name1_text = doc->NewText("Alice"); XMLText* name2_text = doc->NewText("Bob"); XMLText* age1_text = doc->NewText("20"); XMLText* age2_text = doc->NewText("30"); name1->LinkEndChild(name1_text); name2->LinkEndChild(name2_text); age1->LinkEndChild(age1_text); age2->LinkEndChild(age2_text); // <!-- ended --> //[9] 保存XMLDocument數據到XML文檔中 doc->SaveFile(path.c_str()); //[10] 釋放內存 delete doc; //
運行程序后,生成的XML文檔如下:
4、XML數據修改
以上面存儲的XML文檔為例,進行數據的修改操作。
原始XML文檔數據如下:
XML文檔數據修改,舉例:
// //[0] 文件路徑 std::string path = "/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml"; //[1] 創建管理XML文檔的對象:XMLDocument XMLDocument* doc = new XMLDocument(); //[2] 解析xml文件 XMLError errorID = doc->LoadFile(path.c_str()); //[3] 判斷是否解析錯誤 if (errorID != 0) { CCLOG("Parse Error!"); return; } //[4] 獲取根元素 <person> XMLElement* root = doc->RootElement(); //[5] 獲取子元素 <student>、<teacher> XMLElement* student = root->FirstChildElement(); XMLElement* teacher = student->NextSiblingElement(); // <!-- begin --> //[6] 修改數據 //[6.1] 添加新元素 <city> XMLElement* city = doc->NewElement("city"); XMLText* city_text = doc->NewText("北京"); city->LinkEndChild(city_text); student->LinkEndChild(city); //[6.2] 添加新屬性 <type> root->SetAttribute("type", "學校人群"); //[6.3] 修改元素名稱 student->SetName("學生"); //[6.4] 修改屬性值 student->SetAttribute("id", "9999"); //[6.5] 刪除元素 root->DeleteChild(teacher); // <!-- ended --> //[7] 保存XMLDocument修改后的數據,到XML文檔中 doc->SaveFile(path.c_str()); //[8] 釋放內存 delete doc; //
運行程序后,修改后的XML文檔如下:
【常用數據操作】
這里介紹一下常用的4個類的使用方法。
> XMLNode :表示一個節點,包含一般方法,如訪問自節點、兄弟節點、編輯自身、編輯子節點。
> XMLDocument :表示整個XML文檔,不對應其中某個特定的節點。
> XMLElement :表示元素節點,可以包含子節點XMLElement、和屬性XMLAttribute。
> XMLAttribute :表示一個元素的屬性。
1、XMLNode
表示一個節點,包含一般方法,如訪問自節點、兄弟節點、編輯自身、編輯子節點。
PS:它是 XMLDocument、XMLElement、XMLAttribute 的父類。
常用方法如下:
// // 獲得該XMLNode節點所在的XMLDocument文檔 XMLDocument* GetDocument(); // 獲取'value'值 // Document : 空 // Element : 元素名稱 // Comment : 注釋內容 // Text : 文本內容 const char* Value(); // 設置Node節點的value值 void SetValue(const char* val); // 獲取關聯節點 // 獲取父節點 XMLNode* Parent(); // 獲取第一個子節點,若沒有返回null // 獲取最后一個子節點,若沒有返回null // 獲取前一個兄弟節點 // 獲取下一個兄弟節點 XMLNode* FirstChild(); XMLNode* LastChild(); XMLNode* PreviousSibling(); XMLNode* NextSibling(); // 獲取第一個子元素 // 獲取最后一個子元素 // 獲取前一個兄弟元素 // 獲取下一個兄弟元素 XMLElement* FirstChildElement(); XMLElement* LastChildElement(); XMLElement* PreviousSiblingElement(); XMLElement* NextSiblingElement(); // 插入子節點 // 放在最前面 XMLNode* InsertFirstChild(XMLNode* addThis); // 放在最后面 XMLNode* InsertEndChild(XMLNode* addThis); XMLNode* LinkEndChild(XMLNode* addThis) { return InsertEndChild(addThis); } // 放在指定afterThis子節點的后面 XMLNode* InsertAfterChild(XMLNode* afterThis, XMLNode* addThis); // 刪除子節點 // 刪除所有子節點 void DeleteChildren(); // 刪除指定node子節點 void DeleteChild(XMLNode* node); //
2、XMLDocument
表示整個XML文檔,不對應其中某個特定的節點。
PS:父類為XMLNode,擁有父類所有的方法,這里不再贅述。
// // 解析xml串,需要先通過FileUtils類獲取xml文件的內容串 XMLError Parse(const char* xml); // 解析xml文件 XMLError LoadFile(const char* filename); // 將XMLDocument的xml內容保存到filename文件中 XMLError SaveFile(const char* filename); // 獲取根節點 XMLElement* RootElement() { return FirstChildElement(); } // 新建 // 元素 <a></a> XMLElement* NewElement(const char* name); // 注釋 <!-- ... --> XMLComment* NewComment(const char* comment); // 文本內容 hello world XMLText* NewText(const char* text); // 聲明 <? ... ?> // 如:<?xml version="1.0" encoding="UTF-8"?> XMLDeclaration* NewDeclaration(const char* text=0); // 刪除 // 刪除指定節點 void DeleteNode(XMLNode* node) { node->_parent->DeleteChild( node ); } //
3、XMLElement
表示元素節點,可以包含子節點XMLElement、和屬性XMLAttribute。
PS:父類為XMLNode,擁有父類所有的方法,這里不再贅述。
// // 獲取/設置 元素名稱,等價于Value const char* Name() { return Value(); } void SetName(const char* str) { SetValue( str, staticMem ); } // 獲取元素的文本內容,若沒有返回空 const char* GetText() const; // 獲取指定名稱屬性的屬性值 const char* Attribute(const char* name); // 字符串 bool BoolAttribute(const char* name); // bool int IntAttribute( const char* name ); // int unsigned UnsignedAttribute(const char* name); // unsigned int float FloatAttribute( const char* name ); // float double DoubleAttribute( const char* name ); // double // 獲取第一個屬性 const XMLAttribute* FirstAttribute(); // 獲取指定名稱屬性 const XMLAttribute* FindAttribute(const char* name); // 設置屬性 void SetAttribute(const char* name, const char* value); void SetAttribute(const char* name, bool value); void SetAttribute(const char* name, int value); void SetAttribute(const char* name, unsigned value); void SetAttribute(const char* name, double value); // 刪除指定屬性 void DeleteAttribute(const char* name); //
4、XMLAttribute
表示一個元素的屬性。
沒有父類。
常用方法如下:
// // 獲取屬性名稱 const char* Name(); // 獲取下一個屬性 // 該屬性對應的元素中,定義在該屬性后面的屬性 XMLAttribute* Next(); // 獲取屬性值 const char* Value(); bool BoolValue(); int IntValue(); unsigned int UnsignedValue(); float FloatValue(); double DoubleValue(); // 設置屬性值 void SetAttribute(const char *value); void SetAttribute(bool value); void SetAttribute(int value); void SetAttribute(unsigned int value); void SetAttribute(float value); void SetAttribute(double value); //
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。