在编写读取.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();
}
}
如果大家有什么更好的方法,希望给其建议,谢谢大家。