【iOS-cocos2d-X 游戏开发之九】Cocos2dx利用CCSAXParser解析xml数据

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

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

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


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

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

Himi封装的HXmlParse类:


  
  
  1. HXmlParse.h 
  2.   
  3. // 
  4. //  HXmlParse.h 
  5. //  HAnimation 
  6. // 
  7. //  Created by Himi on 12-3-22. 
  8. //  Copyright (c) 2012年 Augustimpression. All rights reserved. 
  9. // 
  10.   
  11. #ifndef HAnimation_HXmlParse_h 
  12. #define HAnimation_HXmlParse_h 
  13.   
  14. #include "cocos2d.h" 
  15. #include "CCSAXParser.h" 
  16. #include "CCObject.h" 
  17. #include "CCMutableDictionary.h" 
  18.   
  19. using namespace cocos2d; 
  20.   
  21. class CC_DLL HXmlParse :public CCObject, public CCSAXDelegator 
  22.   
  23. public
  24.   
  25.     static HXmlParse * parserWithFile(const char *tmxFile); 
  26.   
  27.     bool initHXmlParse(const char* xmlName); 
  28.   
  29.     //  使用 CCSAXDelegator 重写3个回调函数 
  30.   
  31.     void startElement(void *ctx, const char *name, const char **atts); 
  32.   
  33.     void endElement(void *ctx, const char *name); 
  34.   
  35.     void textHandler(void *ctx, const char *ch, int len); 
  36.   
  37.     std::string root_name;  
  38.   
  39.     bool isJumpHeadData; 
  40.   
  41.     CCMutableDictionary<std::string,CCString*> *mDic; 
  42.   
  43. private
  44.   
  45.     std::string startXmlElement;//用来记录每个key前字段 
  46.   
  47.     std::string endXmlElement;//用来记录每个key后字段 
  48.   
  49.     std::string currString;//记录每个value的值 
  50.   
  51. }; 
  52.   
  53. #endif  
  54. HXmlParse.cpp 
  55.   
  56. // 
  57. //  HXmlParse.cpp 
  58. //  HAnimation 
  59. // 
  60. //  Created by Himi on 12-3-22. 
  61. //  Copyright (c) 2012年 Augustimpression. All rights reserved. 
  62. // 
  63.   
  64. #include "HXmlParse.h" 
  65. #include "CCSAXParser.h" 
  66.   
  67. HXmlParse * HXmlParse::parserWithFile(const char *tmxFile) 
  68.     HXmlParse *pRet = new HXmlParse(); 
  69.     if(pRet->initHXmlParse(tmxFile)) 
  70.     { 
  71.         pRet->autorelease(); 
  72.         return pRet; 
  73.     } 
  74.     CC_SAFE_DELETE(pRet); 
  75.     return NULL; 
  76.   
  77. bool HXmlParse::initHXmlParse(const char* xmlName) 
  78.   
  79.   
  80.     mDic = new CCMutableDictionary<std::string,CCString*>(); 
  81.   
  82.     CCSAXParser _par;   
  83.   
  84.     if (false == _par.init("UTF-8") ) 
  85.   
  86.     { 
  87.         CCLog("-----请使用utf-8格式!"); 
  88.         return false
  89.     } 
  90.     _par.setDelegator(this); 
  91.     const char* _path =CCFileUtils::fullPathFromRelativePath(xmlName); 
  92.     return _par.parse(_path); 
  93.   
  94.   
  95. //回调函数 
  96.   
  97. void HXmlParse::startElement(void *ctx, const char *name, const char **atts) 
  98.   
  99. {    
  100.   
  101.     CC_UNUSED_PARAM(ctx); 
  102.   
  103.     startXmlElement = (char*)name; 
  104.     if(!isJumpHeadData){//跳过数据头 
  105.         CCLog("------跳过root name"); 
  106.         isJumpHeadData=true
  107.         root_name=startXmlElement; 
  108.         return
  109.     } 
  110.   
  111. //    CCLog("-startElement----%s",startXmlElement.c_str()); 
  112.   
  113.   
  114. void HXmlParse::endElement(void *ctx, const char *name) 
  115.   
  116.     CC_UNUSED_PARAM(ctx); 
  117.   
  118.     endXmlElement = (char*)name; 
  119.     if(endXmlElement==root_name){//数据尾 
  120.         CCLog("读取xml结束"); 
  121.         isJumpHeadData=false
  122.         root_name=""
  123.         return
  124.     } 
  125.   
  126. //    CCLog("-endElement----%s",endXmlElement.c_str()); 
  127. //键值对的结束字段 
  128. void HXmlParse::textHandler(void *ctx, const char *ch, int len) 
  129.   
  130.     CC_UNUSED_PARAM(ctx); 
  131.     currString=string((char*)ch,0,len); 
  132.     CCString *ccStr =new CCString();//备注3 
  133.     ccStr->m_sString=currString; 
  134.     if(root_name!=""){ 
  135.          mDic->setObject(ccStr,startXmlElement); 
  136.         CCLog("-----key:%s, value:%s",startXmlElement.c_str(),mDic->objectForKey(startXmlElement)->m_sString.c_str()); 
  137.     } 
  138.   
  139. //    CCLog("-textHandler----%s",currString.c_str()); 
  140.   
 

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


  
  
  1. //  使用 CCSAXDelegator 重写3个回调函数 
  2.   
  3.    void startElement(void *ctx, const char *name, const char **atts); 
  4.   
  5.    void endElement(void *ctx, const char *name); 
  6.   
  7.    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. bool setObject(_ValueT pObject, const _KeyT& key) 
  2.     { 
  3.         pair<CCObjectMapIter, bool > pr; 
  4.   
  5.         pr = m_Map.insert( Int_Pair(key, pObject) ); 
  6.   
  7.         if(pr.second == true
  8.         { 
  9.             pObject->retain(); 
  10.             return true
  11.         } 
  12.   
  13.         return false
  14.     } 
 

上面这个是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. #include "HXmlParse.h" 
  2.   
  3. HXmlParse::parserWithFile("himi.xml"); 
 

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

 

 









本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/841867,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
166 4
|
1月前
|
Java 开发工具 Android开发
Android与iOS开发环境搭建全解析####
本文深入探讨了Android与iOS两大移动操作系统的开发环境搭建流程,旨在为初学者及有一定基础的开发者提供详尽指南。我们将从开发工具的选择、环境配置到第一个简单应用的创建,一步步引导读者步入移动应用开发的殿堂。无论你是Android Studio的新手还是Xcode的探索者,本文都将为你扫清开发道路上的障碍,助你快速上手并享受跨平台移动开发的乐趣。 ####
|
1月前
|
消息中间件 存储 缓存
十万订单每秒热点数据架构优化实践深度解析
【11月更文挑战第20天】随着互联网技术的飞速发展,电子商务平台在高峰时段需要处理海量订单,这对系统的性能、稳定性和扩展性提出了极高的要求。尤其是在“双十一”、“618”等大型促销活动中,每秒需要处理数万甚至数十万笔订单,这对系统的热点数据处理能力构成了严峻挑战。本文将深入探讨如何优化架构以应对每秒十万订单级别的热点数据处理,从历史背景、功能点、业务场景、底层原理以及使用Java模拟示例等多个维度进行剖析。
55 8
|
1月前
|
数据采集 自然语言处理 搜索推荐
基于qwen2.5的长文本解析、数据预测与趋势分析、代码生成能力赋能esg报告分析
Qwen2.5是一款强大的生成式预训练语言模型,擅长自然语言理解和生成,支持长文本解析、数据预测、代码生成等复杂任务。Qwen-Long作为其变体,专为长上下文场景优化,适用于大型文档处理、知识图谱构建等。Qwen2.5在ESG报告解析、多Agent协作、数学模型生成等方面表现出色,提供灵活且高效的解决方案。
167 49
|
25天前
|
存储 安全 数据安全/隐私保护
深入解析iOS 14隐私保护功能:用户数据安全的新里程碑
随着数字时代的到来,个人隐私保护成为全球关注的焦点。苹果公司在最新的iOS 14系统中引入了一系列创新的隐私保护功能,旨在为用户提供更透明的数据使用信息和更强的控制权。本文将深入探讨iOS 14中的几项关键隐私功能,包括App跟踪透明性、简化的隐私设置以及增强的系统安全性,分析它们如何共同作用以提升用户的隐私保护水平。
79 3
|
26天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
26天前
|
XML JSON JavaScript
HttpGet 请求的响应处理:获取和解析数据
HttpGet 请求的响应处理:获取和解析数据
|
1月前
|
数据安全/隐私保护 iOS开发 开发者
iOS 14隐私保护新特性深度解析####
随着数字时代的到来,隐私保护已成为全球用户最为关注的问题之一。苹果在最新的iOS 14系统中引入了一系列创新功能,旨在增强用户的隐私和数据安全。本文将深入探讨iOS 14中的几大隐私保护新特性,包括App跟踪透明度、剪贴板访问通知和智能防追踪功能,分析这些功能如何提升用户隐私保护,并评估它们对开发者和用户体验的影响。 ####
|
1月前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
67 2
|
1月前
|
JavaScript API 开发工具
<大厂实战场景> ~ Flutter&鸿蒙next 解析后端返回的 HTML 数据详解
本文介绍了如何在 Flutter 中解析后端返回的 HTML 数据。首先解释了 HTML 解析的概念,然后详细介绍了使用 `http` 和 `html` 库的步骤,包括添加依赖、获取 HTML 数据、解析 HTML 内容和在 Flutter UI 中显示解析结果。通过具体的代码示例,展示了如何从 URL 获取 HTML 并提取特定信息,如链接列表。希望本文能帮助你在 Flutter 应用中更好地处理 HTML 数据。
122 1

推荐镜像

更多