本站文章均为李华明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学习-前后交互模式介绍

    在前后台交互模式的介绍中,实际上就是Store中Proxy相关的内容,比如Ajax提交. 所以详细的文档请参考: Ext学习-基础概念,核心思想介绍   中关于数据模型和MVC结构部分. 作者:sdj ...

  2. EXT--当defaultType与items的子组件默认xtype冲突时items的子组件的xtype为panel

    示例图 直接看下面示例代码: /** * 获取导入表单 * @returns {Ext.FormPanel} */ function getImportForm() { return new Ext. ...

  3. JavaScript高级---装饰者模式设计

    一.设计模式 javascript里面给我们提供了很多种设计模式: 工厂.桥.组合.门面.适配器.装饰者.享元.代理.观察者.命令.责任链 在前面我们实现了工厂模式和桥模式 工厂模式 : 核心:为了生 ...

  4. CSS reset--重置样式

    在一般我们写一个自己自定义的HTML的时候,我们会清除样式或者说重置样式 重置样式.清除浏览器默认样式,一切全部用自己的设置,并配置适合设计的基础样式 下面给出所有一般需要清除的样式: html,bo ...

  5. centos telnet --xinetd 服务

    telnet由于是明文传输,所以安全起见最好不要用telnet服务.但是由于telnet是一个比较方便的远程工具,在windows上是自带 的不需要安装客户端即可使用.如果telnet设置的比较复杂, ...

  6. How does database indexing work?

    When data is stored on disk based storage devices, it is stored as blocks of data. These blocks are ...

  7. (转)开源爬虫larbin分析

    转自风中之炎的博客:http://www.cnblogs.com/FengYan/archive/2012/02/04/2338630.html 1. larbin简介(百度百科) larbin是一种 ...

  8. Java注解全面解析

    1.基本语法 注解定义看起来很像接口的定义.事实上,与其他任何接口一样,注解也将会编译成class文件. @Target(ElementType.Method) @Retention(Retentio ...

  9. POJ1118 Lining Up

    快弄死我了 最后的原因是abs和fabs的区别... 说点收获:1.cmp函数返回的是int,所以不要直接返回double相减的结果2.define inf 1e9和eps 1e-93.在整数相除得到 ...

  10. ASP.NET并发处理

    http://blog.csdn.net/hliq5399/article/details/6280288