在编写读取.xml文件的功能时,参考网上的资料各种问题,所以不才写出以下测试用例,供程序新人作为参考使用吧。
(1) 创建UTF-8格式的.xml,命名为Item.xml,数据如下(已加注释,如果若要使用,请去掉注释):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Item> <ItemId>1</ItemId> // 物品ID <ItemType>1</ItemType> // 物品类型:装备,材料,消耗品 <Name>天马流星锤</Name> // 物品名字 <ItemState>你想砸谁,就砸谁</ItemState> // 物品描述 <power>10</power> // 力量加成 <useLevel>10</useLevel> // 使用最小等级限制 <StrengthLev>10</StrengthLev> // 强化最大等级限制 <Speed>1.0</Speed> // 速度加成 <price>300</price> // 出售价格 </Item> <Item> <ItemId>3</ItemId> <ItemType>1</ItemType> <Name>青龙炎月刀</Name> <ItemState>听着名字就霸气</ItemState> <power>10</power> <useLevel>20</useLevel> <StrengthLev>30</StrengthLev> <Speed>3.0</Speed> <price>600</price> </Item> </Root>
(2) 接下来,创建头文件,如XmlItem.h,代码如下:
#ifndef __XML_ITEM_H__ #define __XML_ITEM_H__ #include "cocos2d.h" #include "support/tinyxml2/tinyxml2.h" USING_NS_CC; using namespace std; /* 解析物品文件:Item.xml */ // 物品 typedef struct sItem { int Id; // ID int type; // 类型:装备,材料,消耗品 string name; // 名字 string state; // 描述 int useMinLev; // 使用最小等级限制 int StrengthMaxLev; // 强化最大等级限制 int power; // 力量加成 int speed; // 速度加成 int sprice; // 价格 }ITEMDATA; // 物品数据类
// 编写的缘故:是由于个人已经习惯使用std::map来存储数据,然而鉴于cocos2d-x的内存管理机制且推荐cocos2d-x自带的CCDictionary进行
// 存储,但是CCDictionary::setObject(CCObject* pObject, intptr_t key)使用CCObject* pObject对象,所以该类要继承CCNode class Item : public cocos2d::CCNode { public: Item(); void CleanItemData(); public: ITEMDATA data; }; // 文件解析类 class XmlItem : public cocos2d::CCNode { public: XmlItem(); ~XmlItem(); static XmlItem* GetInstance(); void AnalyticItemXml(const char* fileName); // 解析Item.xml文件 private: static XmlItem* m_pInstance; CCDictionary* m_pDicItem; }; #endif
(3) 剩下的不用多说,来编写XmlItem.cpp,代码如下:
#include "XmlItem.h" /////// Item Item::Item() { CleanItemData(); } void Item::CleanItemData() { memset(&data,0x00,sizeof(data)); } //////文件解析 XmlItem* XmlItem::m_pInstance = NULL; XmlItem::XmlItem() { m_pDicItem = CCDictionary::create(); m_pDicItem->retain(); // 需要添加,否则会导致崩溃,不信,可以注释掉试试 } XmlItem::~XmlItem() { CC_SAFE_DELETE(m_pDicItem); } XmlItem* XmlItem::GetInstance() { if(m_pInstance == NULL) { m_pInstance = new XmlItem(); } return m_pInstance; } void XmlItem::AnalyticItemXml( const char* fileName ) { std::string filepath = CCFileUtils::sharedFileUtils()->fullPathForFilename(fileName); tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument(); tinyxml2::XMLError errorId = pDoc->LoadFile(filepath.c_str()); if(errorId != 0) { CCLOG("xml anlyatic error: %s",fileName); return; } // 获取根元素 tinyxml2::XMLElement *pElement = pDoc->RootElement(); // 获取第一个子节点 tinyxml2::XMLElement *rootElement = pElement->FirstChildElement(); while(rootElement != NULL) { Item* pItem = new Item(); // 获取节点的子级 tinyxml2::XMLNode *pCurNode = rootElement->FirstChild(); while(pCurNode != NULL) { // 查阅资料说,使用pCurNode->ToElement->GetText() 这样不安全,会导致内存泄露,但至今仍没有找到更好的方法,见谅 if(!strcmp(pCurNode->Value(),"ItemType")) pItem->data.type = atoi(pCurNode->ToElement()->GetText()); else if(!strcmp(pCurNode->Value(),"ItemId")) pItem->data.Id = atoi(pCurNode->ToElement()->GetText()); else if(!strcmp(pCurNode->Value(),"Name")) pItem->data.name = pCurNode->ToElement()->GetText(); else if(!strcmp(pCurNode->Value(),"ItemState")) pItem->data.state = pCurNode->ToElement()->GetText(); else if(!strcmp(pCurNode->Value(),"power")) pItem->data.power = atoi(pCurNode->ToElement()->GetText()); else if(!strcmp(pCurNode->Value(),"price")) pItem->data.sprice = atoi(pCurNode->ToElement()->GetText()); // 获取该节点的下一子级 pCurNode = pCurNode->NextSibling(); } m_pDicItem->setObject(pItem,pItem->data.Id); // 进入下一个节点 rootElement = rootElement->NextSiblingElement(); } }
如果大家有什么更好的方法,希望给其建议,谢谢大家。