本站文章均為[?李華明Himi?](http://www.himigame.com/about-himi)原創,轉載務必在明顯處注明:
轉載自[【黑米GameDev街區】](http://www.himigame.com/)?原文鏈接:?[http://www.himigame.com/iphone-cocos2dx/694.html](http://www.himigame.com/iphone-cocos2dx/694.html "【iOS-cocos2d-X")
[? 點擊訂閱 ?](http://list.qq.com/cgi-bin/qf_invite?id=acfc24e272cc4a26debf3b3866edb626a9ea3fc80fd8893c)?本博客最新動態!及時將最新博文通知您!
本章Himi給大家分享如何在Cocos2dX中解析xml數據;對于數據存取有很多方式,流文件,plist,xml等,那么為了跨平臺更好的支持,Himi想到之前寫的CCUserDefault 存儲數據一節,Cocos2dx自帶的存儲類,一旦存入數據都會以xml格式進行保存,適用于iOS、Android等平臺,所以這里Himi使用xml進行游戲的一些數據錄入 ?= =.. 另外一方面Himi本章節也是基于Cocos2dx引擎代碼進行的一次簡單對xml數據解析的封裝;
為了更保險的去考慮跨平臺,所以對于xml存儲這塊的解析,也做了些搜索,最后發現王哥(王哲-cocos2dx引擎作者)也有給我們提示過,內容如下:
~~~
cocos2dx里面集成了libxml2,ios上會調用sdk里面內置的,
android和win32上則帶了已經編譯好的靜態/動態庫。
你可以參考CCSAXParser里面的代碼來使用libxml2
~~~
那么既然如此,就對Cocos2dx引擎源碼的CCSAXParser類進行了剖析,那么這里Himi,先給出代碼,然后再詳細講解下:
Himi封裝的HXmlParse類:
~~~
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
~~~
~~~
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解析數據后將數據回調給如下三個函數:
~~~
// 使用 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,如下:
~~~
<?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的時候要注意此函數的兩個參數:
~~~
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類使用方法很簡單:
~~~
#include "HXmlParse.h"
HXmlParse::parserWithFile("himi.xml");
~~~
然后Himi為了證實此解析類在Android也可以正常運行,那么這里Himi將讀出的數據展示在畫面上,iOS運行截圖如下:
[](http://www.himigame.com/wp-content/uploads/2012/03/111112.png)
?
[](http://www.himigame.com/wp-content/uploads/2012/03/24.png)
- 前言
- 【Iphone 游戲開發】游戲引擎剖析
- [Object-C語言隨筆之一]Mac os 下搭建iOS開發環境
- [Object-C語言隨筆之二] 《NSLog》常用的打印調試語句與自動排版
- [Object-C語言隨筆之三] 類的創建和實例化以及函數的添加和調用!
- [Object-C語言隨筆之四]創建視圖并繪制簡單圖形
- 【iOS-Cocos2d游戲開發之一】搭建cocos2d游戲引擎環境HelloWorld!
- 【iOS-Cocos2d游戲開發之二】Cocos2D 游戲開發資源貼(教程以及源碼)
- 【iOS-Cocos2d游戲開發之三】CCScene切換的所有特效(28種)以及設置屏幕橫豎屏!
- 【iOS-Cocos2d游戲開發之四】獨自收集Cocos2d提供的字體!共57種(有對照的字體圖)
- 【iOS-Cocos2d游戲開發之五】多觸點與觸屏事件詳解(單一監聽、事件分發)【11月28日更新】
- 【iOS-Cocos2d游戲開發之六】對觸屏事件追加講解,解決無法觸發ccTouchMoved事件[重要!]
- 【iOS-Cocos2d游戲開發之七】在cocos2d中添加/刪除系統組件,并解決View設置透明會影響View中的其他組件的問題!【11月28日更新解決添加組件Cocos2d動畫停止播放的BUG】
- 【iOS-Cocos2d游戲開發之八】開啟高清(960*640)模式問題與解答、圖片適配以及設置iphone橫豎屏
- 【iOS-Cocos2d游戲開發之九】講解CCSpriteBatchNode與TP工具的&quot;.pvr.ccz&quot;,&quot;.plist&quot;共用的終極精靈優化及注意事項!
- 【iOS-Cocos2d游戲開發之十】添加粒子系統特效并解決粒子特效與Layer之間的坐標問題;
- 【iOS-Cocos2d游戲開發之十一】使用Box2d物理系統以及在cocos2d框架添加Box2d物理系統lib包的方法
- 【iOS-Cocos2d游戲開發之十二】淺析使用C++/C/OC進行iOS游戲混編出現“failed with exit”問題與小結;
- 【iOS-Cocos2d游戲開發之十三】CCSprite利用Bezier(貝塞爾)做拋物線動作并讓CCSprite同時播放兩個Action動作!
- 【iOS-Cocos2d游戲開發之十四】音頻/音效/視頻播放(利用Cocos2D-iPhone-Extensions嵌入Cocos2d進行視頻播放!)
- 【iOS-Cocos2d游戲開發之十五】詳解CCProgressTimer 進度條并修改cocos2d源碼實現“理想”游戲進度條!
- 【iOS-Cocos2d游戲開發之十六】添加本地通知(UILocalNotification)以及添加系統組件滾動視圖(UIScrollView)!【2011年11月15日更新】
- 【iOS-Cocos2d游戲開發之十七】靈活使用精靈可視區域(TextureRect)與錨點(anchorPoint),并結合可視區域與錨點制作進度條!
- 【iOS開發必備指南合集】申請企業級IDP、真機調試、游戲接入GameCenter 指南(實現仿官方的成就提示)、游戲接入OpenFeint指南;
- 【iOS-Cocos2d游戲開發之十八】解決滾屏背景/拼接地圖有黑邊(縫隙)/動畫播放出現毛邊以及禁止游戲中自動鎖屏問題!【2011年12月18日補充】
- 【iOS開發必收藏】詳解iOS應用程序內使用IAP/StoreKit付費、沙盒(SandBox)測試、創建測試賬號流程!【2012-12-11日更新獲取&quot;產品付費數量等于0的問題&quot;】
- 【iOS-cocos2d-X 游戲開發之一】在Mac下結合Xcode搭建Cocos2d-X開發環境!
- 【iOS-cocos2d-X 游戲開發之二】【必看篇】總結闡述Cocos2d-X與Cocos2d-iphone區別;
- 【iOS-Cocos2d游戲開發之十九】游戲數據存儲的四種常用方式NSKeyedArchiver/NSUserDefaults/Write寫入/SQLite3
- 【iOS-Cocos2d游戲開發之二十】精靈的基礎知識點總匯(位圖操作/貼圖更換/重排z軸等)以及利用CCSprite與CCLayerColor制作簡單遮蓋層!
- 【iOS-Cocos2d游戲開發之二十一 】自定義精靈類并為你的精靈設置攻擊幀(指定開始幀)以及擴展Cocos2d源碼的CCAnimation簡化動畫創建!
- 【iOS-Cocos2d游戲開發之二十二 】CCSpeed實現CCAnimate動畫進行時設置慢動作以及設置游戲加減速進行(塔防游戲必備)!
- 【iOS-cocos2d-X 游戲開發之三】Mac下配置Android NDK環境并搭建Cocos2d-x環境并Eclipse正常編譯運行Cocos2dX自帶TestsDemo項目!
- 【iOS-cocos2d-X 游戲開發之四】Cocos2dX創建Android NDK新項目并編譯導入Eclipse中正常運行!
- 【iOS-cocos2d-X 游戲開發之五】游戲存儲之Cocos2dX自帶CCUserDefault類詳解;
- 【iOS-cocos2d-X 游戲開發之六】使用Base64算法對Cocos2dX自帶CCUserDefault游戲存儲數據編碼!
- 【iOS-cocos2d-X 游戲開發之七】整合Cocos2dX的Android項目到Xcode項目中,Xcode編寫&amp;編譯代碼,Android導入打包運行即可!
- 【iOS-iap防護】驗證用戶付費收據!拒絕iap Cracker!拒絕iap Free!讓iphone越獄用戶無從下手!【2012年5月2日更新防護iap Free的方法】
- 【COCOS2DX-LUA 腳本開發之一】在Cocos2dX游戲中使用Lua腳本進行游戲開發(基礎篇)并介紹腳本在游戲中詳細用途!
- 【iOS-cocos2d-X 游戲開發之九】Cocos2dx利用CCSAXParser解析xml數據&amp;CCMutableDictionary使用與注意!
- 【iOS-cocos2d-X 游戲開發之十】自定義CCSprite/Layer/CCNode及靜態類模版&amp;自定義類細節說明&amp;Cocos2dx觸屏事件講解
- 【iOS-cocos2d-X 游戲開發之十一】New CCSprite()帶來的錯誤&amp;使用CCUserDefault及pvr.ccz在Cocos2dx中要注意!
- 【iOS-cocos2d-X 游戲開發之十二】自定義Cocos2dx搖桿(增強Joystick),增加搖桿跟隨用戶觸點作為搖桿坐標,讓搖桿不再死板!
- 【iOS-cocos2d-X 游戲開發之十三】詳細講解在Xcode中利用預編譯并通過Jni調用Android的Java層代碼(cocos2dx里訪問調用Android函數)!
- 【iOS-cocos2d-X 游戲開發之十四】Xcode中c++&amp;Object-C混編,詳細介紹如何在cocos2dx中訪問object函數以及Apple Api
- 【iOS-cocos2d-X 游戲開發之十五】Cocos2dx中響應Android的Back(返回)與Menu(小房子)事件&amp;&amp;Cocos2dx自動釋放粒子內存函數!
- 【iOS-cocos2d-X 游戲開發之十六】配置你的Cocos2dx項目編譯后的Android自動使用(-hd)高清圖&amp;設置Android自適應屏幕、縮放比例方法!
- 【Cocoa(mac) Application 開發系列之四】動作編輯器(Cocos2dx)制作流程詳解及附上響應鼠標滾軸事件、反轉坐標系、導入/創建資源目錄等知識點代碼!
- 【Cocos2d-X(2.x) 游戲開發系列之一】cocos2dx(v2.x)與(v1.x)的一些常用函數區別講解!在2.x版CCFileData類被去除等
- 【Cocos2d-X(2.x) 游戲開發系列之二】cocos2dx最新2.0.1版本跨平臺整合NDK+Xcode,Xcode編寫&amp;編譯代碼,Android導入打包運行即可!
- 【Cocos2dX(2.x)_Lua開發之三】★重要必看篇★在Lua中使用自定義精靈(Lua腳本與自創建類之間的訪問)及Lua基礎講解
- 【Cocos2d-X(2.x) 游戲開發系列之三】最新版本cocos2d&#173;2.0&#173;x&#173;2.0.2使用新資源加載策略!不再沿用-hd、-ipad、-ipadhd添加后綴方式
- 【Cocos2d-X(1.x 2.x) 修復篇】iOS6 中 libcurl.a 無法通過armv7s編譯以及iOS6中無法正常游戲橫屏的解決方法
- 【Cocos2d-X(1.x 2.x) 】iOS6與iphone5適相關設置隨筆(解決第三方類庫無法通過armv7s編譯的方法、添加Default-568h@2x.png)