最近换了cocos2d-x劳动节版,原来版本的CCUserDefault使用的是libxml2,劳动节版的使用了TinyXML2(貌似2.1.2就换了),有国外开发者说,他升级引擎后什么都没干,游戏在安卓上的加载时间从20秒缩短到了5秒。
因为CCUserDefault没有提供对节点属性的操作,所以我就简单写了一下针对节点内容以及节点属性的操作,简单封装,与大家分享下,基本该有的操作应该是全了【为了让读者方便使用,有两个方法是介绍使用的,你如果用本库,可以删除:createXMLFile();readXML()】,废话不多说,提供源码【目前只是简单使用,后期非逐渐完善,添加各种方法,对数据进行加密,就像《CCUserDefault加密》一文中的,可能表现为:《工具库:UtilTools》一文中的方式】……
FDTinyXML2.h
// // FDTinyXML2.h // RunnerEditor // // Created by firedragonpzy on 13-5-3. // // #ifndef __RunnerEditor__FDTinyXML2__ #define __RunnerEditor__FDTinyXML2__ #include "support/tinyxml2/tinyxml2.h" #include "cocos2d.h" #include "platform/CCFileUtils.h" #include "TempObject.h" #include "RConfig.h" #include <fstream> USING_NS_CC; using namespace tinyxml2; using namespace std; class FDTinyXML2 : public CCObject{ public: bool init(); CREATE_FUNC(FDTinyXML2); bool createXMLFile(); void readXML(); bool createXMLFileFromArray(CCArray *array,CCArray *array1); bool readXMLToArray(CCArray* &array,cocos2d::CCArray *&array1); private: string m_sFilePath; string m_sBackUpFilePath; bool isXMLFileExist(); bool backupXMLFile(); bool copyFile(const char*pszFile, const char* newFile); void groundNodeToArray(XMLElement *ground,CCArray *&array); void eleNodeToArray(XMLElement *ele,CCArray *&array1); }; #endif /* defined(__RunnerEditor__FDTinyXML2__) */
FDTinyXML2.cpp
// // FDTinyXML2.cpp // RunnerEditor // // Created by firedragonpzy on 13-5-3. // // #include "FDTinyXML2.h" // root name of xml #define FDTinyXML2_ROOT_NAME "firedragonpzy" #define XML_FILE_NAME "firedragonpzy.xml" #define XML_BACKUP_FILE_NAME "firedragonpzy.bak" #define XML_FIRST_NODE "grounds" #define XML_SECOND_NODE "barriers" bool FDTinyXML2::init() { if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)//if you don't { m_sFilePath = CCFileUtils::sharedFileUtils()->fullPathForFilename(XML_FILE_NAME); m_sBackUpFilePath = CCFileUtils::sharedFileUtils()->fullPathForFilename(XML_BACKUP_FILE_NAME); }else { m_sFilePath = CCFileUtils::sharedFileUtils()->getWritablePath() + XML_FILE_NAME; m_sBackUpFilePath = CCFileUtils::sharedFileUtils()->getWritablePath() + XML_BACKUP_FILE_NAME; } return true; } // This is a demo, if you use my lib,you can delete this method createXMLFile() bool FDTinyXML2::createXMLFile() { bool bRet = false; tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument(); if (NULL == pDoc) { return false; } tinyxml2::XMLDeclaration *pDeclaration = pDoc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\""); if (NULL == pDeclaration) { return false; } pDoc->LinkEndChild(pDeclaration); tinyxml2::XMLElement *pRootEle = pDoc->NewElement(FDTinyXML2_ROOT_NAME); if (NULL == pRootEle) { return false; } pDoc->LinkEndChild(pRootEle); tinyxml2::XMLElement *subGroundGrass = pDoc->NewElement("groundGrass"); tinyxml2::XMLText *content = pDoc->NewText("content:groudText"); subGroundGrass->LinkEndChild(content); pRootEle->LinkEndChild(subGroundGrass); tinyxml2::XMLElement *subGroundSoil = pDoc->NewElement("groundSoil"); subGroundSoil->SetAttribute("soil-attribute", "text:soil"); pRootEle->LinkEndChild(subGroundSoil); bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(m_sFilePath.c_str()); if (pDoc) { delete pDoc; } return bRet; } // This is a demo, if you use my lib,you can delete this method readXML() void FDTinyXML2::readXML() { tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument(); tinyxml2::XMLElement *rootNode = NULL; tinyxml2::XMLElement *curNode = NULL; const tinyxml2::XMLAttribute *curAttribute = NULL; do { unsigned long nSize; const char *pXmlBuffer = (const char*)CCFileUtils::sharedFileUtils()->getFileData(m_sFilePath.c_str(), "rb", &nSize); if (NULL == pXmlBuffer) { break; } pDoc->Parse(pXmlBuffer); rootNode = pDoc->RootElement(); if (NULL == rootNode) { break; } curNode = rootNode->FirstChildElement(); XMLElement *secondNode = curNode->NextSiblingElement(); CCLog("---------------Test------------------"); CCLog("GetText():%s",secondNode->GetText()); CCLog("Name():%s",secondNode->Name()); CCLog("Value():%s",secondNode->Value()); CCLog("---------------Test------------------"); curAttribute = curNode->FirstAttribute(); while (NULL != curNode) { CCLog("GetText():%s",curNode->GetText()); CCLog("Value():%s",curNode->Value()); while (NULL != curAttribute) { CCLog("curAttribute->Name():%s",curAttribute->Name()); CCLog("curAttribute->Value():%s",curAttribute->Value()); curAttribute = curAttribute->Next(); } curNode = curNode->NextSiblingElement(); if (curNode) { curAttribute = curNode->FirstAttribute(); } CCLog("---------------END----------------"); } if (pDoc) { delete pDoc; } } while (0); } // Determine if xml exists. bool FDTinyXML2::isXMLFileExist() { CCLog("%s",m_sFilePath.c_str()); FILE *fp = fopen(m_sFilePath.c_str(), "r"); bool bRet = false; if (fp) { bRet = true; fclose(fp); } return bRet; } bool FDTinyXML2::backupXMLFile() { bool bRet = false; if (isXMLFileExist()) { if (copyFile(m_sFilePath.c_str(), m_sBackUpFilePath.c_str())) { bRet = true; }else { bRet = false; } }else { bRet = false; CCLog("no file exists!"); } return bRet; } bool FDTinyXML2::copyFile(const char *pszFile, const char *newFile) { ifstream input; ofstream output; input.open(pszFile,ios::binary); if (input.fail()) { input.close(); output.close(); return false; } output.open(newFile,ios::binary); if (output.fail()) { input.close(); output.close(); return false; }else { output<<input.rdbuf(); output.close(); input.close(); return true; } } bool FDTinyXML2::createXMLFileFromArray(cocos2d::CCArray *array,CCArray *array1) { bool bRet = false; if (isXMLFileExist()) { if (remove(m_sFilePath.c_str())) { return false; } } XMLDocument *pDoc = new XMLDocument(); if (NULL == pDoc) { return false; } XMLDeclaration *pDeclaration = pDoc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\""); if (NULL == pDeclaration) { return false; } pDoc->LinkEndChild(pDeclaration); XMLElement *pRootEle = pDoc->NewElement(FDTinyXML2_ROOT_NAME); if (NULL == pRootEle) { return false; } pDoc->LinkEndChild(pRootEle); TempObject *tempObj = NULL; XMLElement *subElement = NULL; if (array ) { int count = array->count(); if (count > 0) { XMLElement *firstNode = pDoc->NewElement(XML_FIRST_NODE); if (NULL != firstNode) { pRootEle->LinkEndChild(firstNode); }else { return false; } for (int i = 0; i < count; i++) { tempObj = (TempObject*)array->objectAtIndex(i); GroundBarrierStruct groundStruct = tempObj->getGroundBarrier(); subElement = pDoc->NewElement(groundStruct.bType.c_str()); subElement->SetAttribute(XML_POSX, groundStruct.posx); subElement->SetAttribute(XML_POSY, groundStruct.posy); subElement->SetAttribute(XML_FLAG, groundStruct.flag); firstNode->LinkEndChild(subElement); } } } if (array1 ) { int count = array1->count(); if (count > 0) { XMLElement *secondNode = pDoc->NewElement(XML_SECOND_NODE); if (NULL != secondNode) { pRootEle->LinkEndChild(secondNode); }else { return false; } for (int i = 0; i < count; i++) { tempObj = (TempObject*)array1->objectAtIndex(i); EleBarrierStuct eleStruct = tempObj->getEleBarrier(); subElement = pDoc->NewElement(eleStruct.bType.c_str()); subElement->SetAttribute(XML_POSX, eleStruct.posx); subElement->SetAttribute(XML_POSY, eleStruct.posy); subElement->SetAttribute(XML_FLAG, eleStruct.flag); secondNode->LinkEndChild(subElement); } } } bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(m_sFilePath.c_str()); if (pDoc) { delete pDoc; } // this method usets to back up the file,if you don't need,you can delete. backupXMLFile(); return bRet; } bool FDTinyXML2::readXMLToArray(cocos2d::CCArray *&array,cocos2d::CCArray *&array1) { bool bRet = false; if (isXMLFileExist()) { do { XMLDocument *xmlDoc = new XMLDocument(); // const XMLAttribute *curAttribute = NULL; unsigned long nSize; const char* xmlBuffer = (const char*)CCFileUtils::sharedFileUtils()->getFileData(m_sFilePath.c_str(), "rb", &nSize); if (NULL == xmlBuffer) { return false; } xmlDoc->Parse(xmlBuffer); delete [] xmlBuffer; XMLElement *rootNode = xmlDoc->RootElement(); if (NULL == rootNode) { return false; } // first element XMLElement *firstNode = rootNode->FirstChildElement(); if (NULL == firstNode) { return false; } XMLElement *subFirstNode = firstNode->FirstChildElement(); if (NULL == subFirstNode) { return false; } if (strncmp(firstNode->Name(),XML_FIRST_NODE,strlen(XML_FIRST_NODE)) == 0) { groundNodeToArray(subFirstNode,array); }else if (strncmp(firstNode->Name(),XML_SECOND_NODE,strlen(XML_SECOND_NODE)) == 0) { eleNodeToArray(subFirstNode, array1); } // next element XMLElement *secondNode = firstNode->NextSiblingElement(); if (NULL == secondNode) { return true; } XMLElement *subSecondNode = secondNode->FirstChildElement(); if (NULL == subSecondNode) { return true; } if (strncmp(secondNode->Name(),XML_FIRST_NODE,strlen(XML_FIRST_NODE)) == 0) { groundNodeToArray(subSecondNode,array); }else if (strncmp(secondNode->Name(),XML_SECOND_NODE,strlen(XML_SECOND_NODE)) == 0) { eleNodeToArray(subSecondNode, array1); } } while (0); bRet = true; }else { bRet = false; } return bRet; } void FDTinyXML2::groundNodeToArray(XMLElement *ground,CCArray *&array) { const XMLAttribute *curAttribute = NULL; TempObject *obj = NULL; GroundBarrierStruct groundStruct; while (NULL != ground) { curAttribute = ground->FirstAttribute(); if (strncmp(curAttribute->Name(), XML_POSX,strlen(XML_POSX)) == 0) { groundStruct.posx = atof(curAttribute->Value()); } groundStruct.bType = ground->Name(); obj = TempObject::create(); while (NULL != curAttribute) { if (strncmp(curAttribute->Name(), XML_POSX,strlen(XML_POSX)) == 0) { groundStruct.posx = atof(curAttribute->Value()); }else if (strncmp(curAttribute->Name(), XML_POSY,strlen(XML_POSY)) == 0) { groundStruct.posy = atof(curAttribute->Value()); }else if (strncmp(curAttribute->Name(), XML_FLAG,strlen(XML_FLAG)) == 0) { groundStruct.flag = atoi(curAttribute->Value()); } obj->setGroundBarrier(groundStruct); curAttribute = curAttribute->Next(); } array->addObject(obj); ground = ground->NextSiblingElement(); } } void FDTinyXML2::eleNodeToArray(tinyxml2::XMLElement *ele, cocos2d::CCArray *&array1) { EleBarrierStuct eleStruct; TempObject *obj = NULL; const XMLAttribute *curAttribute = NULL; while (NULL != ele) { curAttribute = ele->FirstAttribute(); eleStruct.bType = ele->Name(); obj = TempObject::create(); while (NULL != curAttribute) { if (strncmp(curAttribute->Name(), XML_POSX,strlen(XML_POSX)) == 0) { eleStruct.posx = atof(curAttribute->Value()); }else if (strncmp(curAttribute->Name(), XML_POSY, strlen(XML_POSY)) == 0) { eleStruct.posy = atof(curAttribute->Value()); }else if (strncmp(curAttribute->Name(), XML_FLAG, strlen(XML_FLAG)) == 0) { eleStruct.flag = atoi(curAttribute->Value()); } obj->setEleBarrier(eleStruct); curAttribute = curAttribute->Next(); } array1->addObject(obj); ele = ele->NextSiblingElement(); } }
暂且提供这些,后续补充,忘大家多多提供宝贝意见……
注意事项:
在win中开发的时候:
1、使用XMLDocument的时候要添加tinyxml2命名空间,否则error:不明确的符号
2、目前来说tinyxml2还不能直接引用处理,需要自己include
2013、05、09【v1.0】
2013、05、10【v1.1】更新:
1、修改了读取的bug
2、调整了win上面文件存储的位置,v1.0存储在可读路径下,如果打包exe,无法获取xml文件。现在存储在Resouces路径下……
Demo下载链接:https://github.com/firedragonpzy/FD_Libs.git