Cocos数据篇[3.4](3) ――XML数据操作
【唠叨】 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://www.52php.cn/article/p-elwdclzu-kt.html(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的一个例子 先来看一个简单的例子。 // <?xmlversion="1.0"encoding="UTF-8"?> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don'tforgetthemeeting!</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> <bookcategory="COOKING"> <titlelang="en">EverydayItalian</title> <author>GiadaDeLaurentiis</author> <year>2005</year> <price>30.00</price> </book> <bookcategory="CHILDREN"> <titlelang="en">HarryPotter</title> <author>JK.Rowling</author> <year>2005</year> <price>29.99</price> </book> <bookcategory="WEB"> <titlelang="en">LearningXML</title> <author>ErikT.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>Thistextisboldanditalic</b></i> <!--正确的嵌套--> <b><i>Thistextisboldanditalic</i></b> // (5)XML 属性值必须加引号。(单引号' '、双引号" " ,均可以) // <notedate="08/08/2008"> <notedate='08/08/2008'> // 4.1、注释 在 XML 中编写注释的语法与 HTML 的语法很相似: // <!--Thisisacomment--> // 4.2、保留空格 HTML会把多个连续的空格字符裁减(合并)为一个。 而在XML中,空格不会被删节。 // content:HellomynameisDavid. HTML:HellomynameisDavid. XML:HellomynameisDavid. // 4.3、实体引用 在 XML 中,一些字符拥有特殊的意义。 如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。 这样会产生 XML 错误: <message>if salary < 1000 then</message> 为了避免这个错误,请用实体引用来代替 "<" 字符: <message>if salary < 1000 then</message> 在 XML 中,有 5 个预定义的实体引用:
4.4、XML元素 XML 元素指的是从(且包括)开始标签,直到(且包括)结束标签的部分。 > 元素可包含:其他元素、文本、或者两者的混合物。 > 元素也可以拥有属性。 // <bookstore> <bookcategory="CHILDREN"> <title>HarryPotter</title> <author>JK.Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore> // 在上例中: <bookstore> 和 <book> 都拥有元素内容,因为它们包含了其他元素。 <author> 只有文本内容,因为它仅包含文本。 在上例中,只有 <book> 元素拥有属性(category="CHILDREN")。 4.5、XML属性 XML 元素可以在开始标签中包含属性,类似 HTML。属性 (Attribute) 提供关于元素的额外(附加)信息。 属性通常提供:不属于数据组成部分的信息。 在下面的例子中,文件类型与数据无关,但是对需要处理这个元素的软件来说却很重要。 PS:属性的值必须加引号(单引号、双引号,均可以)。 // <filetype="gif">computer.gif</file> // 4.6、元素 vs. 属性 有时候属性和元素均可以提供相同的信息。 如下所示: // <personsex="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" usingnamespacetinyxml2; // 2、XML数据解析 XML文档如下: // <?xmlversion="1.0"encoding="UTF-8"?> <person> <studentid="1111"> <name>Alice</name> <age>20</age> </student> <teacherid="2222"> <name>Bob</name> <age>30</age> </teacher> </person> // XML解析使用举例: // //[0]文件路径 std::stringpath="/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml"; //[1]创建管理XML文档的对象:XMLDocument XMLDocument*doc=newXMLDocument(); //[2]解析xml文件 //方式一: //Datadata=FileUtils::getInstance()->getDataFromFile(path.c_str()); //XMLErrorerrorID=doc->Parse((constchar*)data.getBytes()); //方式二: //std::stringdata=FileUtils::getInstance()->getStringFromFile(path.c_str()); //XMLErrorerrorID=doc->Parse(data.c_str()); //方式三: XMLErrorerrorID=doc->LoadFile(path.c_str()); //[3]判断是否解析错误 if(errorID!=0){ CCLOG("ParseError!"); 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(constXMLAttribute*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,e->Name(),e->GetText()); } } //[6]释放内存 deletedoc; // 控制台输出结果: 3、XML数据存储 以上面解析的XML文档为例,我们通过代码来生成相应的XML文档,并保存到xml文件中。 生成XML文档并保存,举例: // //[0]文件路径 std::stringpath="/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml"; //[1]创建管理XML文档的对象:XMLDocument XMLDocument*doc=newXMLDocument(); //<!--begin--> //[2]创建XML声明,并连接到XML文档中 XMLDeclaration*declare=doc->NewDeclaration("xmlversion="1.0"encoding="UTF-8""); doc->LinkEndChild(declare);//添加到文档尾部 //[3]创建注释,并连接到XML文档中 XMLComment*comment=doc->NewComment("thisisxmlcomment"); 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]释放内存 deletedoc; // 运行程序后,生成的XML文档如下: 4、XML数据修改 以上面存储的XML文档为例,进行数据的修改操作。 原始XML文档数据如下: XML文档数据修改,举例: // //[0]文件路径 std::stringpath="/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml"; //[1]创建管理XML文档的对象:XMLDocument XMLDocument*doc=newXMLDocument(); //[2]解析xml文件 XMLErrorerrorID=doc->LoadFile(path.c_str()); //[3]判断是否解析错误 if(errorID!=0){ CCLOG("ParseError!"); 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]释放内存 deletedoc; // 运行程序后,修改后的XML文档如下: 【常用数据操作】 这里介绍一下常用的4个类的使用方法。 > XMLNode :表示一个节点,包含一般方法,如访问自节点、兄弟节点、编辑自身、编辑子节点。 > XMLDocument :表示整个XML文档,不对应其中某个特定的节点。 > XMLElement :表示元素节点,可以包含子节点XMLElement、和属性XMLAttribute。 > XMLAttribute :表示一个元素的属性。 1、XMLNode 表示一个节点,包含一般方法,如访问自节点、兄弟节点、编辑自身、编辑子节点。 PS:它是 XMLDocument、XMLElement、XMLAttribute 的父类。 常用方法如下: // //获得该XMLNode节点所在的XMLDocument文档 XMLDocument*GetDocument(); //获取'value'值 // Document:空 // Element:元素名称 // Comment:注释内容 // Text:文本内容 constchar*Value(); //设置Node节点的value值 voidSetValue(constchar*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){returnInsertEndChild(addThis);} //放在指定afterThis子节点的后面 XMLNode*InsertAfterChild(XMLNode*afterThis,XMLNode*addThis); //删除子节点 //删除所有子节点 voidDeleteChildren(); //删除指定node子节点 voidDeleteChild(XMLNode*node); // 2、XMLDocument 表示整个XML文档,不对应其中某个特定的节点。 PS:父类为XMLNode,拥有父类所有的方法,这里不再赘述。 // //解析xml串,需要先通过FileUtils类获取xml文件的内容串 XMLErrorParse(constchar*xml); //解析xml文件 XMLErrorLoadFile(constchar*filename); //将XMLDocument的xml内容保存到filename文件中 XMLErrorSaveFile(constchar*filename); //获取根节点 XMLElement*RootElement(){returnFirstChildElement();} //新建 //元素<a></a> XMLElement*NewElement(constchar*name); //注释<!--...--> XMLComment*NewComment(constchar*comment); //文本内容helloworld XMLText*NewText(constchar*text); //声明<?...?> // 如:<?xmlversion="1.0"encoding="UTF-8"?> XMLDeclaration*NewDeclaration(constchar*text=0); //删除 //删除指定节点 voidDeleteNode(XMLNode*node){node->_parent->DeleteChild(node);} // 3、XMLElement 表示元素节点,可以包含子节点XMLElement、和属性XMLAttribute。 PS:父类为XMLNode,拥有父类所有的方法,这里不再赘述。 // //获取/设置元素名称,等价于Value constchar*Name(){returnValue();} voidSetName(constchar*str){SetValue(str,staticMem);} //获取元素的文本内容,若没有返回空 constchar*GetText()const; //获取指定名称属性的属性值 constchar*Attribute(constchar*name);//字符串 boolBoolAttribute(constchar*name);//bool intIntAttribute(constchar*name);//int unsignedUnsignedAttribute(constchar*name);//unsignedint floatFloatAttribute(constchar*name);//float doubleDoubleAttribute(constchar*name);//double //获取第一个属性 constXMLAttribute*FirstAttribute(); //获取指定名称属性 constXMLAttribute*FindAttribute(constchar*name); //设置属性 voidSetAttribute(constchar*name,constchar*value); voidSetAttribute(constchar*name,boolvalue); voidSetAttribute(constchar*name,intvalue); voidSetAttribute(constchar*name,unsignedvalue); voidSetAttribute(constchar*name,doublevalue); //删除指定属性 voidDeleteAttribute(constchar*name); // 4、XMLAttribute 表示一个元素的属性。 没有父类。 常用方法如下: // //获取属性名称 constchar*Name(); //获取下一个属性 //该属性对应的元素中,定义在该属性后面的属性 XMLAttribute*Next(); //获取属性值 constchar*Value(); boolBoolValue(); intIntValue(); unsignedintUnsignedValue(); floatFloatValue(); doubleDoubleValue(); //设置属性值 voidSetAttribute(constchar*value); voidSetAttribute(boolvalue); voidSetAttribute(intvalue); voidSetAttribute(unsignedintvalue); voidSetAttribute(floatvalue); voidSetAttribute(doublevalue); // (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |