cocos2d-x 2.2.6 之 .xml文件数据读取

  在编写读取.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();
    }
}

如果大家有什么更好的方法,希望给其建议,谢谢大家。

原文地址:https://www.cnblogs.com/SkyflyBird/p/5046378.html