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://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的一个例子
先来看一个简单的例子。
//<?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文档的对象:XMLDocumentXMLDocument*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,%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文档的对象:XMLDocumentXMLDocument*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文档的对象:XMLDocumentXMLDocument*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);//文本内容helloworldXMLText*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,拥有父类所有的方法,这里不再赘述。
////获取/设置元素名称,等价于Valueconstchar*Name(){returnValue();}voidSetName(constchar*str){SetValue(str,staticMem);}//获取元素的文本内容,若没有返回空constchar*GetText()const;//获取指定名称属性的属性值constchar*Attribute(constchar*name);//字符串boolBoolAttribute(constchar*name);//boolintIntAttribute(constchar*name);//intunsignedUnsignedAttribute(constchar*name);//unsignedintfloatFloatAttribute(constchar*name);//floatdoubleDoubleAttribute(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);//
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。