Cocos2d-x数据篇03:XML数据操作

前端之家收集整理的这篇文章主要介绍了Cocos2d-x数据篇03:XML数据操作前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

【前言】

XML即可扩展标记语言,在游戏开发中,常用于保存游戏数据信息,如最高分、游戏等级等信息,和描述一些资源等。加载动画的plist文件瓦片地图编辑器到处的地图格式tmx文件,实际上都是特定格式的xml文件另外 UserDefault 单例类保存的数据,也是存储在xml文件中的。Cocos2d-x 已经加入了 tinyxml2库 用于xml的解析。3.x版本位于external/tinyxml2下。

本节要介绍的就是:如何使用tinyxml2库来操作处理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的一个例子

先来看一个简单的例子。

1
2
3
4
5
6
7
8
9
//
<?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 文档中的元素形成了一棵文档树的结构。这棵树从“根部”开始,并扩展到树的“枝叶”。

9
10
11
12
13
14
15
<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个子元素。

15
16
17
18
19
20
21
22
<bookstore>
<bookcategory= "COOKING" >
<title>EverydayItalian</title>
<author>GiadaDeLaurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
"CHILDREN" >
<title>HarryPotter</title>
<author>JK.Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
"WEB" >
<title>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 元素必须被正确的嵌套。

6
<!--错误的嵌套-->
<b><i>Thistextisboldanditalic</b></i>
<!--正确的嵌套-->
<b><i>Thistextisboldanditalic</i></b>
(5)XML 属性值必须加引号。(单引号' '、双引号" " ,均可以)

4
<notedate= "08/08/2008" >
'08/08/2008' >
4.1、注释

在 XML 中编写注释的语法与 HTML 的语法很相似:

3
<!--Thisisacomment-->
4.2、保留空格

HTML会把多个连续的空格字符裁减(合并)为一个。

而在XML中,空格不会被删节。

5
content:HellomynameisDavid.
HTML:HellomynameisDavid.
XML:HellomynameisDavid.
4.3、实体引用

在 XML 中,一些字符拥有特殊的意义。

如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。

这样会产生 XML 错误

1
<message> if salary<1000then</message>

为了避免这个错误,请用实体引用来代替 "<" 字符:

salary&lt;1000then</message>

在 XML 中,有 5 个预定义的实体引用:

4.4、XML元素

XML 元素指的是从(且包括)开始标签,直到(且包括)结束标签的部分。

> 元素可包含:其他元素、文本、或者两者的混合物。

> 元素也可以拥有属性

@H_502_501@ 10
<title>HarryPotter</title>
<author>JK.Rowling</author>
<price>29.99</price>
</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"
using namespace tinyxml2;
2、XML数据解析

XML文档如下:

13
<person>
<studentid= "1111" >
<name>Alice</name>
<age>20</age>
</student>
<teacherid= "2222" >
<name>Bob</name>
<age>30</age>
</teacher>
</person>
XML解析使用举例:

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//
//[0]文件路径
std::stringpath= "/soft/cocos2d-x-3.4/projects/Demo34/Resources/testXML.xml" ;
//[1]创建管理XML文档的对象:XMLDocument
XMLDocument*doc= new XMLDocument();
//[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]判断是否解析错误
(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]获取子元素名称
"chd:%s" ,chd->Name());
//[5.3]遍历子元素的属性id
//FirstAttribute():获取chd元素的第一个属性
//Next():获取chd元素的attr属性的下一个属性
( const XMLAttribute*attr=chd->FirstAttribute();attr;attr=attr->Next()){
//Name():属性名称
//Value():属性
"chd_attr:%s,%s" }
//也可以通过属性名称,来获取属性
//CCLOG("id=%s",chd->Attribute("id"));
//[5.4]遍历子元素chd的子元素<name>,<age>
(XMLElement*e=chd->FirstChildElement();e;e=e->NextSiblingElement()){
//子元素e为文本内容
//GetText():文本内容
"e:%s,e->Name(),e->GetText());
}
}
//[6]释放内存
delete doc;
控制台输出结果:

3、XML数据存储

以上面解析的XML文档为例,我们通过代码生成相应的XML文档,并保存到xml文件中。

生成XML文档并保存,举例:

48
49
50
51
52
53
54
55
56
;
//[1]创建管理XML文档的对象:XMLDocument
XMLDocument();
//<!--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" );
teacher->SetAttribute( );
//[7]创建子元素,并连接到<student>、<teacher>元素中,作为子节点
XMLElement*name1=doc->NewElement( "name" );
XMLElement*name2=doc->NewElement( );
XMLElement*age1=doc->NewElement( "age" );
XMLElement*age2=doc->NewElement( );
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]释放内存
doc;
运行程序后,生成的XML文档如下:

4、XML数据修改

以上面存储的XML文档为例,进行数据的修改操作。

原始XML文档数据如下:

XML文档数据修改,举例:

38
//[2]解析xml文件
XMLErrorerrorID=doc->LoadFile(path.c_str());
//[3]判断是否解析错误
(errorID!=0){
);
;
}
//[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]修改属性
"9999" );
//[6.5]删除元素
root->DeleteChild(teacher);
//<!--ended-->
//[7]保存XMLDocument修改后的数据,到XML文档中
doc->SaveFile(path.c_str());
//[8]释放内存
doc;
运行程序后,修改后的XML文档如下:

【常用数据操作】

这里介绍一下常用的4个类的使用方法

> XMLNode :表示一个节点,包含一般方法,如访问自节点、兄弟节点、编辑自身、编辑子节点。

> XMLDocument :表示整个XML文档,不对应其中某个特定的节点。

> XMLElement :表示元素节点,可以包含子节点XMLElement、和属性XMLAttribute。

> XMLAttribute :表示一个元素的属性

1、XMLNode

表示一个节点,包含一般方法,如访问自节点、兄弟节点、编辑自身、编辑子节点。

PS:它是 XMLDocument、XMLElement、XMLAttribute 的父类

常用方法如下:

44
//获得该XMLNode节点所在的XMLDocument文档
XMLDocument*GetDocument();
//获取'value'值
//Document:空
//Element:元素名称
//Comment:注释内容
//Text:文本内容
const char *Value();
//设置Node节点的value值
void SetValue( *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){ InsertEndChild(addThis);}
//放在指定afterThis子节点的后面
XMLNode*InsertAfterChild(XMLNode*afterThis,XMLNode*addThis);
//删除子节点
//删除所有子节点
DeleteChildren();
//删除指定node子节点
DeleteChild(XMLNode*node);
2、XMLDocument

表示整个XML文档,不对应其中某个特定的节点。

PS:父类为XMLNode,拥有父类所有的方法,这里不再赘述。

23
//解析xml串,需要先通过FileUtils类获取xml文件内容
XMLErrorParse( *xml);
//解析xml文件
XMLErrorLoadFile( *filename);
//将XMLDocument的xml内容保存到filename文件
XMLErrorSaveFile( *filename);
//获取根节点
XMLElement*RootElement(){ FirstChildElement();}
//新建
//元素<a></a>
XMLElement*NewElement( *name);
//注释<!--...-->
XMLComment*NewComment( *comment);
//文本内容helloworld
XMLText*NewText( *text);
//声明<?...?>
//如:<?xmlversion="1.0"encoding="UTF-8"?>
XMLDeclaration*NewDeclaration( *text=0);
//删除
//删除指定节点
DeleteNode(XMLNode*node){node->_parent->DeleteChild(node);}
3、XMLElement

表示元素节点,可以包含子节点XMLElement、和属性XMLAttribute。

26
//获取/设置元素名称,等价于Value
*Name(){ Value();}
SetName( *str){SetValue(str,staticMem);}
//获取元素的文本内容,若没有返回空
*GetText() ;
//获取指定名称属性属性
*Attribute( *name); //字符串
bool BoolAttribute( //bool
int IntAttribute( //int
unsignedUnsignedAttribute( //unsignedint
float FloatAttribute( //float
double DoubleAttribute( //double
//获取第一个属性
XMLAttribute*FirstAttribute();
XMLAttribute*FindAttribute( *name);
//设置属性
SetAttribute( *name, *value);
value);
value);
value);
//删除指定属性
DeleteAttribute( *name);
4、XMLAttribute

表示一个元素的属性

没有父类

21
//获取属性名称
*Name();
//获取下一个属性
//该属性对应的元素中,定义在该属性后面的属性
XMLAttribute*Next();
*Value();
BoolValue();
IntValue();
unsigned UnsignedValue();
FloatValue();
DoubleValue();
//设置属性
*value);
SetAttribute( value);
value);
SetAttribute(unsigned value);
value);
value);
【参考】

http://www.w3school.com.cn/xml/index.asp(W3School)

http://cn.cocos2d-x.org/tutorial/show?id=1225(【官方文档】Cocos2d-x xml解析)

http://www.jb51.cc/article/p-elwdclzu-kt.html(TinyXml 解析 XML)

猜你在找的Cocos2d-x相关文章