本站文章均为李华明Himi原创,转载务必在明显处注明:
转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/iphone-cocos2dx/694.html

          ☞ 点击订阅 ☜
 本博客最新动态!及时将最新博文通知您!

本章Himi给大家分享如何在Cocos2dX中解析xml数据;对于数据存取有很多方式,流文件,plist,xml等,那么为了跨平台更好的支持,Himi想到之前写的CCUserDefault 存储数据一节,Cocos2dx自带的存储类,一旦存入数据都会以xml格式进行保存,适用于iOS、Android等平台,所以这里Himi使用xml进行游戏的一些数据录入  = =.. 另外一方面Himi本章节也是基于Cocos2dx引擎代码进行的一次简单对xml数据解析的封装;

为了更保险的去考虑跨平台,所以对于xml存储这块的解析,也做了些搜索,最后发现王哥(王哲-cocos2dx引擎作者)也有给我们提示过,内容如下:

1
2
3
cocos2dx里面集成了libxml2,ios上会调用sdk里面内置的,
android和win32上则带了已经编译好的静态/动态库。
你可以参考CCSAXParser里面的代码来使用libxml2

那么既然如此,就对Cocos2dx引擎源码的CCSAXParser类进行了剖析,那么这里Himi,先给出代码,然后再详细讲解下:

Himi封装的HXmlParse类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
49
50
51
52
53
54
HXmlParse.h
 
//
//  HXmlParse.h
//  HAnimation
//
//  Created by Himi on 12-3-22.
//  Copyright (c) 2012年 Augustimpression. All rights reserved.
//
 
#ifndef HAnimation_HXmlParse_h
#define HAnimation_HXmlParse_h
 
#include "cocos2d.h"
#include "CCSAXParser.h"
#include "CCObject.h"
#include "CCMutableDictionary.h"
 
using namespace cocos2d;
 
class CC_DLL HXmlParse :public CCObject, public CCSAXDelegator
{
 
public:
 
    static HXmlParse * parserWithFile(const char *tmxFile);
 
    bool initHXmlParse(const char* xmlName);
 
    //  使用 CCSAXDelegator 重写3个回调函数
 
    void startElement(void *ctx, const char *name, const char **atts);
 
    void endElement(void *ctx, const char *name);
 
    void textHandler(void *ctx, const char *ch, int len);
 
    std::string root_name;
 
    bool isJumpHeadData;
 
    CCMutableDictionary<std::string,CCString*> *mDic;
 
private:
 
    std::string startXmlElement;//用来记录每个key前字段
 
    std::string endXmlElement;//用来记录每个key后字段
 
    std::string currString;//记录每个value的值
 
};
 
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
HXmlParse.cpp
 
//
//  HXmlParse.cpp
//  HAnimation
//
//  Created by Himi on 12-3-22.
//  Copyright (c) 2012年 Augustimpression. All rights reserved.
//
 
#include "HXmlParse.h"
#include "CCSAXParser.h"
 
HXmlParse * HXmlParse::parserWithFile(const char *tmxFile)
{
    HXmlParse *pRet = new HXmlParse();
    if(pRet->initHXmlParse(tmxFile))
    {
        pRet->autorelease();
        return pRet;
    }
    CC_SAFE_DELETE(pRet);
    return NULL;
}
 
bool HXmlParse::initHXmlParse(const char* xmlName)
 
{
 
    mDic = new CCMutableDictionary<std::string,CCString*>();
 
    CCSAXParser _par; 
 
    if (false == _par.init("UTF-8") )
 
    {
        CCLog("-----请使用utf-8格式!");
        return false;
    }
    _par.setDelegator(this);
    const char* _path =CCFileUtils::fullPathFromRelativePath(xmlName);
    return _par.parse(_path);
 
}
 
//回调函数
 
void HXmlParse::startElement(void *ctx, const char *name, const char **atts)
 
{  
 
    CC_UNUSED_PARAM(ctx);
 
    startXmlElement = (char*)name;
    if(!isJumpHeadData){//跳过数据头
        CCLog("------跳过root name");
        isJumpHeadData=true;
        root_name=startXmlElement;
        return;
    }
 
//    CCLog("-startElement----%s",startXmlElement.c_str());
 
}
 
void HXmlParse::endElement(void *ctx, const char *name)
 
{
    CC_UNUSED_PARAM(ctx);
 
    endXmlElement = (char*)name;
    if(endXmlElement==root_name){//数据尾
        CCLog("读取xml结束");
        isJumpHeadData=false;
        root_name="";
        return;
    }
 
//    CCLog("-endElement----%s",endXmlElement.c_str());
}
//键值对的结束字段
void HXmlParse::textHandler(void *ctx, const char *ch, int len)
{
 
    CC_UNUSED_PARAM(ctx);
    currString=string((char*)ch,0,len);
    CCString *ccStr =new CCString();//备注3
    ccStr->m_sString=currString;
    if(root_name!=""){
         mDic->setObject(ccStr,startXmlElement);
        CCLog("-----key:%s, value:%s",startXmlElement.c_str(),mDic->objectForKey(startXmlElement)->m_sString.c_str());
    }
 
//    CCLog("-textHandler----%s",currString.c_str());
 
}

OK,代码呢我们先从.h中来说,首先我们使用CCSAXDelegator,为了让CCSAXParser解析数据后将数据回调给如下三个函数:

1
2
3
4
5
6
7
//  使用 CCSAXDelegator 重写3个回调函数
 
   void startElement(void *ctx, const char *name, const char **atts);
 
   void endElement(void *ctx, const char *name);
 
   void textHandler(void *ctx, const char *ch, int len);

startElement   函数解析的是xml的每个key前字段

textHandler  函数解析出来的是xml每个key对应的value值

endElement   函数解析出来的是xml的每个key后字段

这里Himi随便写了一个xml来做测试,himi.xml,如下:

1
<?xml version="1.0" encoding="utf-8"?><himiTestData><key1>1000</key1><key2>娃哈哈</key2><key3>82.3</key3><key4>4000</key4><key5>himi</key5><key6>true</key6></himiTestData>

那么CCSAXParser类解析第一次回调 startElement 是读取的是root name(xml数据头标识名称->“<himiTestData>”),然后才读取正式数据key和value,最后读取的也是xml数据尾标识名称“</himiTestData>”

当然在Himi封装的HXmlParse类中对于数据标识的读取都跳过了,使用变量isJumpHeadData来处理的;

其他的都很容易没有什么可说的,主要要说还有一点就是关于CCMutableDictionary的使用,对于此类主要结构是形成map&NSMutableDictionary类似是个键值对容器,key-value;那么使用时候要注意4点:

1.  比如Himi解析数据后都会默认将key和value数据存放在CCMutableDictionary中,那么这里我肯定传入的是两个string,但是细心的童鞋会发现代码中第二个并不是std::string,而是CCString对象,嗯 没错,CCMutableDictionary要求传入的是CCObject对象而不是基本类型!CCString中有m_sString这个属性,所以转换起来也是很方便的;

2. 使用CCMutableDictionary进行添加数据setObject的时候要注意此函数的两个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool setObject(_ValueT pObject, const _KeyT& key)
    {
        pair<CCObjectMapIter, bool > pr;
 
        pr = m_Map.insert( Int_Pair(key, pObject) );
 
        if(pr.second == true)
        {
            pObject->retain();
            return true;
        }
 
        return false;
    }

上面这个是cocos2dx引擎中源码中setObject函数实现代码,这里可以很清晰的看到,第一个参数表示《CCObject》,第二个参数才是《Key》!这点对于之前做过java开发的我来说比较郁闷,因为一般都是key在第一个参数。。。。。

3. 请大家仔细看HXmlParse.cpp类中的备注3 ,当你使用CCMutableDictionary的setObject函数的时候,务必要注意,此函数的存入的CCObject参数,引擎中实现代码是对你这个CCObject进行retain()的一个内存地址引用!也就是说这里不要使用一个成员变量来使用,否则你从CCMutableDictionary取出来的数据全部是你最后一个CCObject数据!

4. CCMutableDictionary是cocos2d-x自己封装的类,功能类似NSMutableDictionary。但是Himi通过测试发现!它有一点和NSMutableDictionary是不一样的。NSMutableDictionary的setObjectForKey方法是:如果发现这个key已经存在于字典中的时候,它会自动用新的object覆盖掉原有的object。而CCMutableDictionary由于它是使用map实现的字典功能,而在map里面,如果key已存在,是不会用新的object覆盖掉原有object的。在使用CCMutableDictionary的时候需要特别注意这一点。

HXmlParse解析xml类使用方法很简单:

1
2
3
#include "HXmlParse.h"
 
HXmlParse::parserWithFile("himi.xml");

然后Himi为了证实此解析类在Android也可以正常运行,那么这里Himi将读出的数据展示在画面上,iOS运行截图如下:

【iOS-cocos2d-X 游戏开发之九】Cocos2dx利用CCSAXParser解析xml数据&CCMutableDictionary使用与注意!的更多相关文章

  1. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  2. iOS解析XML数据

    iOS中解析XML数据的类是  NSXMLParser,详细使用方法如下: 假设现在在内存中有XML的二进制数据对象(NSData):data(该数据可能来自网络,也可能是本地的文件数据),设置NSX ...

  3. 【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法

    众所周知,Cocos2d-x是一款不错的开源引擎,但是在Cocos2d-x中直接使用中文是无法正确显示的.比如下面的情况: 解决这个问题常用的有三种方法:1.通过转换为UTF-8编码来显示.2.使用i ...

  4. iOS开发网络篇之Web Service和XML数据解析

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  5. IOS 解析XML数据

    ●  什么是XML ●  全称是Extensible Markup Language,译作“可扩展标记语言” ●  跟JSON一样,也是常用的一种用于交互的数据格式 ●  一般也叫XML文档(XML ...

  6. cocos2d-x游戏开发 跑酷(九) 源代码下载及小结

    这个东西零零碎碎写了一个礼拜吧. 事实上也没多少东西在里面.文章后附下载地址 博客地址:http://blog.csdn.net/dawn_moon 由于我没用过chipmunk,并且它是面向过程的东 ...

  7. Android开发探秘之三:利用jsoup解析HTML页面

    这节主要是讲解jsoup解析HTML页面.由于在android开发过程中,不可避免的涉及到web页面的抓取,解析,展示等等,所以,在这里我主要展示下利用jsoup jar包来抓取cnbeta.com网 ...

  8. [SAP ABAP开发技术总结]ABAP读写、解析XML文件

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. iOS 详解NSXMLParser方法解析XML数据方法

    前一篇文章已经介绍了如何通过URL从网络上获取xml数据.下面介绍如何将获取到的数据进行解析. 下面先看看xml的数据格式吧! <?xml version="1.0" enc ...

随机推荐

  1. Ext学习-基础组件介绍

    1.目标    学习对象获取,组件基础,事件模型以及学习ExtJS中的基础组件的应用. 2.内容   1.对象获取   2.组件原理以及基础   3.事件模型   4.常用组件的介绍 3.学习步骤 1 ...

  2. 【BZOJ】【1022】【SHOI2008】小约翰的游戏John

    博弈论 一看题,哇这不是Nim游戏么= =直接异或起来……啊咧怎么不对? 这道题是[Anti-Nim],普通的Nim是取走最后一个就赢,这题是取走最后一个输…… 做法参见 2009年贾志豪论文< ...

  3. 【UVA】【11762】Race to 1(得到1)

    数学期望/马尔可夫过程 DP/记忆化搜索 刘汝佳老师白书上的例题…… //UVA 11762 #include<vector> #include<cstdio> #includ ...

  4. 2013 Asia Regional Changchun

    Hard Code http://acm.hdu.edu.cn/showproblem.php?pid=4813 #include<cstdio> ]; int main(){ int t ...

  5. memcached+memadmin

    一.安装apache yum install httpd 二.安装php yum install php* 三.apache配置 vi /etc/httpd/conf/httpd.conf 添加Add ...

  6. Gitlab安装和使用相关信息

    Gitlab是利用 Ruby on Rails 一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目.它拥有与Github类似的功能,能够浏览源代码,管理 ...

  7. java基础知识回顾之java Thread类学习(九)--wait和notify区别

    wait和sleep区别:  相同点:调用wait,sleep方法都可以是线程进入阻塞状态,让出cpu的执行权. 不同点:1.sleep必须指定时间,但是wait方法可以指定时间,也可以不指定时间. ...

  8. IP地址总结

    1.网际协议IP : 网际协议 IP 是 TCP/IP 体系中两个最主要的协议之一.与 IP 协议配套使用的还有四个协议: 地址解析协议 ARP (Address Resolution Protoco ...

  9. 通过快捷键及cmd命令注销系统

    公司的外网内网是隔离的 外网的远程电脑屏幕一半卡那了,页面注销键正好在卡死的那一半屏幕上,用以下简单方法注销远程重新连接,问题解决了. 1.通过快捷键win+r打开“运行...” 2.输入CMD 回车 ...

  10. ARM CPU与Intel x86 CPU性能比较

    Qualcomm ARM CPU与Intel x86 CPU性能比较 随着移动互联网时代的到来,Qualcomm(高通).Texas Instruments(德州仪器)等基于ARM架构的CPU受到越来 ...