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的一个例子
先来看一个简单的例子。
//// George John Reminder Don't forget the meeting!
代码分析:
(1)第一行是 XML 声明。它定义 XML 的版本(1.0)和所使用的编码(UTF-8字符集)。
(2)下一行描述文档的根元素(像在说:“本文档是一个便签”):
(3)接下来 4 行描述根元素的 4 个子元素(to,from,heading,body)。
(4)最后一行定义根元素的结尾: 。
以上是一个简单的XML文档。可以发现XML的语法很简单,标签没有被预定义,都是自己定义的标签。并且元素可以有子元素,这就形成了一个树形结构。
3、XML树结构
> XML 文档必须包含根元素,该元素是所有其他元素的父元素。
> 所有元素均可拥有 多个子元素。
> 所有元素均可拥有 文本内容和属性(类似 HTML 中)。
> 父、子以及同胞等术语用于描述元素之间的关系:父元素拥有子元素;相同层级上的子元素成为同胞(兄弟或姐妹)。
> XML 文档中的元素形成了一棵文档树的结构。这棵树从“根部”开始,并扩展到树的“枝叶”。
//// ..... ..... .......... ..... ..... .....
如下所示,一个树结构的实例:
它表示了XML中的一本书:
> 根元素是
> 并且
> category、lang均为元素的属性。
>
//// Everyday Italian Giada De Laurentiis 2005 30.00 Harry Potter J K. Rowling 2005 29.99 Learning XML Erik T. Ray 2003 39.95
4、语法规则
(1)XML 文档必须有根元素。
(2)XML 文档必须有结束标签。(
This is a paragraph.
) (3)XML 标签对大小写敏感。(标签
(4)XML 元素必须被正确的嵌套。
// This text is bold and italic This text is bold and italic //
(5)XML 属性值必须加引号。(单引号' '、双引号" " ,均可以)
////
4.1、注释
在 XML 中编写注释的语法与 HTML 的语法很相似:
// //
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 错误:
为了避免这个错误,请用实体引用来代替 "<" 字符:
在 XML 中,有 5 个预定义的实体引用:
< | < | 小于 |
> | > | 大于 |
& | & | 和号 |
' | ' | 单引号 |
" | " | 双引号 |
4.4、XML元素
XML 元素指的是从(且包括)开始标签,直到(且包括)结束标签的部分。
> 元素可包含:其他元素、文本、或者两者的混合物。
> 元素也可以拥有属性。
//// Harry Potter J K. Rowling 2005 29.99
在上例中:
在上例中,只有
4.5、XML属性
XML 元素可以在开始标签中包含属性,类似 HTML。属性 (Attribute) 提供关于元素的额外(附加)信息。
属性通常提供:不属于数据组成部分的信息。
在下面的例子中,文件类型与数据无关,但是对需要处理这个元素的软件来说却很重要。
PS:属性的值必须加引号(单引号、双引号,均可以)。
//computer.gif //
4.6、元素 vs. 属性
有时候属性和元素均可以提供相同的信息。
如下所示:
//Alice // female Alice
这样写虽然可以,但是这样的定义会造成数据的混乱,并且不易阅读(想获取数据信息,到底是访问属性还是元素?)
所以最好的做法是:
> 属性:用来提供不属于数据组成部分的信息。如图片格式、书籍分类、ID 索引等。
> 元素:用来描述数据信息。
4.7、元素的命名规则
XML 元素必须遵循以下命名规则:
> 名称可以含字母、数字以及其他的字符。
> 名称不能以数字或者标点符号开始。
> 名称不能以字符 “xml”(或者 XML、Xml)开始。
> 名称不能包含空格。
可使用任何名称,没有保留的字词。
XML元素的命名习惯:
> 使名称具有描述性。使用下划线的名称也很不错。
> 名称应当比较简短,比如:
> 避免 "-" 字符。如果按照这样的方式命名:"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文档如下:
//// Alice 20 Bob 30
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] 获取根元素XMLElement* root = doc->RootElement(); //[5] 获取子元素信息 //[5.1] 遍历root的子元素 , // 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的子元素 , 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(); // //[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->SetAttribute("id", "1111"); teacher->SetAttribute("id", "2222"); //[7] 创建子元素,并连接到 、 元素中,作为子节点 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] 创建文本内容,并添加到 、 元素中,作为文本内容 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); // //[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] 获取根元素XMLElement* root = doc->RootElement(); //[5] 获取子元素 、 XMLElement* student = root->FirstChildElement(); XMLElement* teacher = student->NextSiblingElement(); // //[6] 修改数据 //[6.1] 添加新元素 XMLElement* city = doc->NewElement("city"); XMLText* city_text = doc->NewText("北京"); city->LinkEndChild(city_text); student->LinkEndChild(city); //[6.2] 添加新属性 root->SetAttribute("type", "学校人群"); //[6.3] 修改元素名称 student->SetName("学生"); //[6.4] 修改属性值 student->SetAttribute("id", "9999"); //[6.5] 删除元素 root->DeleteChild(teacher); // //[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(); } // 新建 // 元素 XMLElement* NewElement(const char* name); // 注释 XMLComment* NewComment(const char* comment); // 文本内容 hello world XMLText* NewText(const char* text); // 声明 ... ?> // 如: 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); //
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
网页题目:Cocos数据篇[3.4](3)——XML数据操作-创新互联
网页网址:http://ybzwz.com/article/cespgi.html