简介
cocos2dx 3.2读写XML使用的是tinyxml2库。tinyxml2是一个轻量的解析XML的开源库,C++编写,跨平台,内存占用很小。解析文件时,在内存中生成DOM模型,即文档对象模型,遍历这颗树读取想要的数据。
UserDefault类是一个引擎封装好的XML读取类,但是使用这个类读写的XML的文件名固定为UserDefault.xml,并且不能灵活定义文档结构。所以对有特殊XML需求的项目中,就不太适用了。而如果在项目中直接使用tinyxml2库,感觉还不是很方便,所以基于tinyxml2又封装了一个XMLManager类,使用起来更方便,并且能够灵活创建、读取不同结构的XML文件。
XMLManager类同时提供了一个中文资源国际化的方法,一般小项目可能会用到,把中文存到XML文件中读取。
类图
代码
头文件:
/* * WWXMLManager.h * * Created on: 2014年5月20日 * Author: wly */ #ifndef _WWXMLMANAGER_H_ #define _WWXMLMANAGER_H_ #include "cocos2d.h" //#include "tinyxml2.h" #include "tinyxml2/tinyxml2.h" /* * 属性类,这里属性是只读的,修改请使用WWXMLNode类 * <express name="test" value="nothing">This is a test!</express> * name 和 value 就是结点的属性 */ class WWXMLAttribute { public: WWXMLAttribute(const tinyxml2::XMLAttribute *pXMLAttribute); ~WWXMLAttribute(); //下一个属性值 WWXMLAttribute next(); //获取属性名称 const char* getName(); //获取string类型属性值 const char* value(); //获取int类型属性值 int intValue(); //获取bool类型属性值 bool boolValue(); //获取float类型属性值 float floatValue(); //获取double类型属性值 double doubleValue(); //返回是否是空 bool isNULL(); private: //文档属性对象 const tinyxml2::XMLAttribute *m_pXMLAttribute; }; /* * 节点类,封装对节点的各种操作. * 如下类型节点 * <example name="ok",flag="1">text</example> * * example是 nodeName * name和flag是attribute * text是 nodeValue */ class WWXMLNode { public: WWXMLNode(tinyxml2::XMLElement *pXMLElem); WWXMLNode(tinyxml2::XMLElement *pXMLElem,tinyxml2::XMLDocument *pXMLDocument); ~WWXMLNode(); //增加子节点 WWXMLNode addChildNode(const char* name); //查找子节点,默认返回第一个子节点 WWXMLNode findChildNode(const char* name = NULL); //查找下一个兄弟节点,默认返回下面第一个兄弟节点 WWXMLNode findSlibingNode(const char* name =NULL); //查找上一个兄弟节点,默认返回上面第一个兄弟节点 WWXMLNode preSlibingNode(const char* name = NULL); //设置节点属性值 void setAttributeValue(const char* name,const char* value); //获取指定的属性值 const char* getAttributeValue(const char* name); //删除一个指定名称的属性值 void deleteAttribute(const char* name); //设置节点名称 void setNodeName(const char* name); //获取节点名称 const char* getNodeName(); //设置节点值 void setNodeValue(const char* value); //获取节点值 const char* getNodeValue(); //获取属性,默认返回第一个属性 WWXMLAttribute firstAttribute(const char* name = NULL); //删除本节点 void removeSelf(); //删除所有子节点 void removeAllChildNode(); //是否是空节点 bool isNULL(); private: tinyxml2::XMLDocument *m_pXMLDocument; tinyxml2::XMLElement *m_pXMLElem; }; /* * XML管理类,使用tinyxml2封装了操作xml的细节,需要配合WWXMLNode类使用。 * 封装了CCUserDefault提供的功能 * * example: * WWXMLManager myXML; * myXML.createXMLFile("myXML.xml","TestXMLManager"); * WWXMLNode itemNode = myXML.getXMLRootNode().addChildNode("item"); * itemNode.setAttributeValue("flag","true"); * myXML.saveXMLFile(); */ class WWXMLManager { public: WWXMLManager(); WWXMLManager(const char* strXMLPath); ~WWXMLManager(void); //加载xml文件,utf-8格式文件 bool loadXMLFile(const char* strXmlPath); //获取xml文件根目录值 const char* getXMLRootKeyValue(); //获取根结点 WWXMLNode getXMLRootNode(); //创建xml文件,默认为utf-8编码 bool createXMLFile(const char* strFileName,const char* rootNode="root"); //保存文件,修改后需要调用此方法 bool saveXMLFile(); /* * 以下方法适用于引擎提供的默认XML文件,可使用getXMLFilePath获取文件路径 * 对应于CCUserDefault类 */ public: //根据key获取bool的值,当key值不存在时,返回defaultValue static bool getDefaultXMLBoolForKey(const char* pKey); static bool getDefaultXMLBoolForKey(const char* pKey,bool defaultValue); static int getDefaultXMLIntegerForKey(const char* pKey); static int getDefaultXMLIntegerForKey(const char* pKey,int defaultValue); static float getDefaultXMLFloatForKey(const char* pKey); static float getDefaultXMLFloatForKey(const char* pKey,float defaultValue); static double getDefaultXMLDoubleForKey(const char* pKey); static double getDefaultXMLDoubleForKey(const char* pKey,double defaultValue); static std::string getDefaultXMLStringForKey(const char* pKey); static std::string getDefaultXMLStringForKey(const char* pKey,const std::string & defaultValue); //根据key值以bool设置值 static void setDefaultXMLBoolForKey(const char* pKey,bool value); static void setDefaultXMLIntegerForKey(const char* pKey,int value); static void setDefaultXMLFloatForKey(const char* pKey,float value); static void setDefaultXMLDoubleForKey(const char* pKey,double value); static void setDefaultXMLStringForKey(const char* pKey,const std::string & value); static void purgeSharedUserDefault(); //获取默认的XML文件路径 const static std::string& getDefaultXMLFilePath(); //xml文件是否存在 static bool isXmlFileExist(const char* strFilePath); /* * 说明:获取项目的字符串资源,类似如下的文件格式 * 参数:键值,段名值。 * 例子: * <?xml version="1.0" encoding="utf-8"?> * <resources> * <HallScene> * <string name="Str_app_name">项目名称</string> * <string name="Str_chujiRoom">初级房</string> * </HallScene> * <GameScene> * <string name="Str_app_name">项目名称</string> * </GameScene> * </resources> * */ static std::string getWWStringFromXML(const std::string &strKey,const std::string &strSection); private: tinyxml2::XMLDocument *m_pXMLDocument; //文件路径,每次load时改变 std::string m_strXMLFilePath; }; #endif
/* * WWXMLManager.h * * Created on: 2014年5月20日 * Author: wly */ #include "WWXMLManager.h" #include "../WWMacros.h" #include "WW_GBK_TO_UTF8.h" USING_NS_CC; WWXMLAttribute::WWXMLAttribute(const tinyxml2::XMLAttribute *pXMLAttribute): m_pXMLAttribute(pXMLAttribute) { } WWXMLAttribute::~WWXMLAttribute() { } WWXMLAttribute WWXMLAttribute::next() { if (m_pXMLAttribute) { return m_pXMLAttribute->Next(); } return NULL; } const char* WWXMLAttribute::getName() { if (m_pXMLAttribute) { const char* pName = m_pXMLAttribute->Name(); if (pName) { return pName; } } return ""; } const char* WWXMLAttribute::value() { if (m_pXMLAttribute) { const char* pValue = m_pXMLAttribute->Value(); if (pValue) { return pValue; } } return ""; } int WWXMLAttribute::intValue() { if (m_pXMLAttribute) { return m_pXMLAttribute->IntValue(); } return -1; } bool WWXMLAttribute::boolValue() { if (m_pXMLAttribute) { return m_pXMLAttribute->BoolValue(); } return false; } float WWXMLAttribute::floatValue() { if (m_pXMLAttribute) { return m_pXMLAttribute->FloatValue(); } return -1; } double WWXMLAttribute::doubleValue() { if (m_pXMLAttribute) { return m_pXMLAttribute->DoubleValue(); } return -1; } bool WWXMLAttribute::isNULL() { return NULL == m_pXMLAttribute; } WWXMLNode::WWXMLNode(tinyxml2::XMLElement *pElem): m_pXMLElem(pElem),m_pXMLDocument(NULL) { } WWXMLNode::WWXMLNode(tinyxml2::XMLElement *pElem,tinyxml2::XMLDocument *pDocument): m_pXMLElem(pElem),m_pXMLDocument(pDocument) { } WWXMLNode::~WWXMLNode() { } WWXMLNode WWXMLNode::addChildNode(const char* name) { if (m_pXMLElem && m_pXMLDocument) { tinyxml2::XMLElement *pElem = m_pXMLDocument->NewElement(name); if (pElem) { m_pXMLElem->LinkEndChild(pElem); WWXMLNode node(pElem,m_pXMLDocument); return node; } } return NULL; } WWXMLNode WWXMLNode::findChildNode(const char* name /* = NULL */) { if (m_pXMLElem && m_pXMLDocument) { if (NULL == name) { WWXMLNode node(m_pXMLElem->FirstChildElement(),m_pXMLDocument); return node; } else { WWXMLNode node(m_pXMLElem->FirstChildElement(name),m_pXMLDocument); return node; } } return NULL; } WWXMLNode WWXMLNode::findSlibingNode(const char* name /* =NULL */) { if (m_pXMLElem && m_pXMLDocument) { if (NULL == name) { WWXMLNode node(m_pXMLElem->NextSiblingElement(),m_pXMLDocument); return node; } else { WWXMLNode node(m_pXMLElem->NextSiblingElement(name),m_pXMLDocument); return node; } } return NULL; } WWXMLNode WWXMLNode::preSlibingNode(const char* name /* =NULL */) { if (m_pXMLElem && m_pXMLDocument) { if (NULL == name) { WWXMLNode node(m_pXMLElem->PrevIoUsSiblingElement(),m_pXMLDocument); return node; } else { WWXMLNode node(m_pXMLElem->PrevIoUsSiblingElement(name),m_pXMLDocument); return node; } } return NULL; } void WWXMLNode::setAttributeValue(const char* name,const char* value) { if (m_pXMLElem && NULL != name) { m_pXMLElem->SetAttribute(name,value); } } const char* WWXMLNode::getAttributeValue(const char* name) { if (m_pXMLElem && NULL != name) { const char* pName = m_pXMLElem->Attribute(name); if (NULL == pName) { return ""; } return pName; } return ""; } void WWXMLNode::deleteAttribute(const char* name) { if (m_pXMLElem) { m_pXMLElem->DeleteAttribute(name); } } void WWXMLNode::setNodeName(const char* name) { if (m_pXMLElem && NULL != name) { m_pXMLElem->SetName(name); } } const char* WWXMLNode::getNodeName() { if (m_pXMLElem) { const char* pName = m_pXMLElem->Name(); if (NULL == pName) { return ""; } return pName; } return ""; } void WWXMLNode::setNodeValue(const char* value) { if (m_pXMLElem && m_pXMLDocument) { tinyxml2::XMLText *pText = m_pXMLDocument->NewText(value); m_pXMLElem->LinkEndChild(pText); } } const char* WWXMLNode::getNodeValue() { if (m_pXMLElem) { const char* pValue = m_pXMLElem->GetText(); if (NULL == pValue) { return ""; } return pValue; } return ""; } WWXMLAttribute WWXMLNode::firstAttribute(const char* name /*= NULL*/) { if (m_pXMLElem) { if (NULL == name) { return m_pXMLElem->FirstAttribute(); } else { WWXMLAttribute attribute = m_pXMLElem->FirstAttribute(); while (!attribute.isNULL()) { if (strcmp(name,attribute.getName()) == 0) { return attribute; } attribute = attribute.next(); } } } return NULL; } void WWXMLNode::removeSelf() { if (m_pXMLElem) { if (m_pXMLElem->Parent()) { m_pXMLElem->Parent()->DeleteChild((tinyxml2::XMLNode*)m_pXMLElem); } } } void WWXMLNode::removeAllChildNode() { if (m_pXMLElem) { m_pXMLElem->DeleteChildren(); } } bool WWXMLNode::isNULL() { return m_pXMLElem == NULL; } WWXMLManager::WWXMLManager(): m_pXMLDocument(NULL),m_strXMLFilePath("") { } WWXMLManager::WWXMLManager(const char* strXMLPath): m_pXMLDocument(NULL),m_strXMLFilePath(strXMLPath) { loadXMLFile(strXMLPath); } WWXMLManager::~WWXMLManager(void) { if (m_pXMLDocument) { delete m_pXMLDocument; } } bool WWXMLManager::loadXMLFile(const char* strXmlPath) { //加载同一文件时,直接返回 if (strcmp(m_strXMLFilePath.c_str(),strXmlPath) == 0) { return true; } m_strXMLFilePath = strXmlPath; //首先置空,防止重复加载 if (m_pXMLDocument) { delete m_pXMLDocument; m_pXMLDocument = NULL; } m_pXMLDocument = new tinyxml2::XMLDocument(); if (NULL == m_pXMLDocument) { return false; } //使用文件内容加载,直接加载可能会有兼容性问题,字符流内存需要手动释放 std::string strXmlBuffer = CCFileUtils::getInstance()->getStringFromFile(strXmlPath); if (strXmlBuffer.empty()) { CCLOG("WWXMLManager::%s file data is empty!",strXmlPath); return false; } //解析XML字符流 if (tinyxml2::XML_SUCCESS != m_pXMLDocument->Parse(strXmlBuffer.c_str(),strXmlBuffer.length())) { CCLOG("WWXMLManager::%s Parse data error!",strXmlPath); return false; } return true; } const char* WWXMLManager::getXMLRootKeyValue() { if (m_pXMLDocument) { return getXMLRootNode().getNodeName(); } return ""; } WWXMLNode WWXMLManager::getXMLRootNode() { if (m_pXMLDocument) { WWXMLNode node(m_pXMLDocument->RootElement(),m_pXMLDocument); return node; } return NULL; } bool WWXMLManager::createXMLFile(const char* strFileName,const char* rootNode/* ="root" */) { //利用tinyxml2方法创建xml文件 tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument(); if (NULL == pDoc) { return false; } bool bRet = false; do { tinyxml2::XMLDeclaration *pDeclaration = pDoc->NewDeclaration(NULL); if (NULL == pDeclaration) { bRet = false; break; } pDoc->LinkEndChild(pDeclaration); tinyxml2::XMLElement *pRootEle = pDoc->NewElement(rootNode); if (NULL == pRootEle) { bRet = false; break; } pDoc->LinkEndChild(pRootEle); if (tinyxml2::XML_SUCCESS != pDoc->SaveFile(strFileName)) { bRet = false; break; } bRet = true; } while (0); if(pDoc) { delete pDoc; } //创建成功后加载 loadXMLFile(strFileName); return bRet; } bool WWXMLManager::saveXMLFile() { if (m_pXMLDocument) { if (tinyxml2::XML_SUCCESS != m_pXMLDocument->SaveFile(m_strXMLFilePath.c_str())) { return false; } } return true; } bool WWXMLManager::getDefaultXMLBoolForKey(const char* pKey) { return CCUserDefault::getInstance()->getBoolForKey(pKey); } bool WWXMLManager::getDefaultXMLBoolForKey(const char* pKey,bool defaultValue) { return CCUserDefault::getInstance()->getBoolForKey(pKey,defaultValue); } int WWXMLManager::getDefaultXMLIntegerForKey(const char* pKey) { return CCUserDefault::getInstance()->getIntegerForKey(pKey); } int WWXMLManager::getDefaultXMLIntegerForKey(const char* pKey,int defaultValue) { return CCUserDefault::getInstance()->getIntegerForKey(pKey,defaultValue); } float WWXMLManager::getDefaultXMLFloatForKey(const char* pKey) { return CCUserDefault::getInstance()->getFloatForKey(pKey); } float WWXMLManager::getDefaultXMLFloatForKey(const char* pKey,float defaultValue) { return CCUserDefault::getInstance()->getFloatForKey(pKey,defaultValue); } double WWXMLManager::getDefaultXMLDoubleForKey(const char* pKey) { return CCUserDefault::getInstance()->getDoubleForKey(pKey); } double WWXMLManager::getDefaultXMLDoubleForKey(const char* pKey,double defaultValue) { return CCUserDefault::getInstance()->getDoubleForKey(pKey,defaultValue); } std::string WWXMLManager::getDefaultXMLStringForKey(const char* pKey) { return CCUserDefault::getInstance()->getStringForKey(pKey); } std::string WWXMLManager::getDefaultXMLStringForKey(const char* pKey,const std::string & defaultValue) { return CCUserDefault::getInstance()->getStringForKey(pKey,defaultValue); } void WWXMLManager::setDefaultXMLBoolForKey(const char* pKey,bool value) { CCUserDefault::getInstance()->setBoolForKey(pKey,value); } void WWXMLManager::setDefaultXMLIntegerForKey(const char* pKey,int value) { CCUserDefault::getInstance()->setIntegerForKey(pKey,value); } void WWXMLManager::setDefaultXMLFloatForKey(const char* pKey,float value) { CCUserDefault::getInstance()->setFloatForKey(pKey,value); } void WWXMLManager::setDefaultXMLDoubleForKey(const char* pKey,double value) { CCUserDefault::getInstance()->setDoubleForKey(pKey,value); } void WWXMLManager::setDefaultXMLStringForKey(const char* pKey,const std::string & value) { CCUserDefault::getInstance()->setStringForKey(pKey,value); } void WWXMLManager::purgeSharedUserDefault() { CCUserDefault::getInstance()->destroyInstance(); } const std::string& WWXMLManager::getDefaultXMLFilePath() { return CCUserDefault::getInstance()->getXMLFilePath(); } bool WWXMLManager::isXmlFileExist(const char* strFilePath) { FILE *fp = fopen(strFilePath,"r"); bool bRet = false; if (fp) { bRet = true; fclose(fp); } return bRet; } std::string WWXMLManager::getWWStringFromXML(const std::string &strKey,const std::string &strSection) { if (strKey.empty() || strSection.empty()) { CCLOG("key or section is empty!"); return ""; } //加载XML文件 WWXMLManager myXML; if (!myXML.loadXMLFile(WWSTRING_XML_PATH.c_str())) { CCLOG("load string resource error!"); return ""; } //循环获取节点名为stirng,属性名为name,属性值为strKey的节点 WWXMLNode node = myXML.getXMLRootNode().findChildNode(strSection.c_str()); if (!node.isNULL()) { WWXMLNode childNode = node.findChildNode("string"); while (!childNode.isNULL()) { if (strcmp(childNode.firstAttribute("name").value(),strKey.c_str()) == 0) { std::string strResult = childNode.getNodeValue(); //win32,模拟器上显示需要转换成gbk编码 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) GBKToUTF8(strResult,"GBK","UTF-8"); #endif return strResult; } childNode = childNode.findSlibingNode("string"); } } return ""; }