我的CloudBox需要一个跨平台的方案来解决iOS上以及Android上的xml档案读取问题
因为游戏总是需要储存一些设定值,或是过关存档之类的
但又不能轻易的使用iOS内建提供的或著是Java内建提供的函数,这样整起来会很麻烦
而且思考到以后增加新的平台,会有不小的困扰,最后决定就用libxml
libxml又是可以在windows环境下使用的,因此直接用visual studio也可以轻易尝试学习API如何使用
操作系统: Windows XP
IDE工具: Visual Studio 2008
工程类型: Visual C++ Win32 Console Application
lib及.h档下载连结
http://xmlsoft.org/sources/win32/
dll下载连结
http://www.dll-files.com/dllindex/dll-files.shtml?iconv
http://www.dll-files.com/dllindex/dll-files.shtml?zlib1
http://www.dll-files.com/dllindex/dll-files.shtml?libxml2
如图所示,我在工程目录中创建了两个文件夹,在libxml中放了iconv跟libxml的.h文档
另外也创建了lib档,将所有的lib都放进去
然后再项目工程中设定libaray的文件路经跟include的文件路径
1. 读取XML文档
xmlDocPtr doc; xmlNodePtr root; // load an exist xml file. doc = xmlParseFile("test.xml"); if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. \n"); return 0; } // get root root = xmlDocGetRootElement(doc); if (root == NULL) { fprintf(stderr,"empty document\n"); xmlFreeDoc(doc); return 0; }
xmlParseFile函数以默认方式读入一个UTF-8格式的文档,并返回文档指针。
xmlReadFile函数读入一个带有某种编码的xml文档,并返回文档指针;细节见libxml2参考手册。
xmlFreeDoc 释放文档指针。xmlDocGetRootElement函数得到根节点curNode
2.建立XML文档
void CreateNewXMLDemo() { // create xml document xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0"); xmlNodePtr root = xmlNewNode(NULL,BAD_CAST"root"); //set root xmlDocSetRootElement(doc,root); //add node xmlNewTextChild(root, NULL, BAD_CAST "newNode1", BAD_CAST "newNode1 content"); xmlNewTextChild(root, NULL, BAD_CAST "newNode2", BAD_CAST "newNode2 content"); xmlNewTextChild(root, NULL, BAD_CAST "newNode3", BAD_CAST "newNode3 content"); //create node and add content xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2"); xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT"); xmlAddChild(root,node); xmlAddChild(node,content); // add attribute xmlNewProp(node,BAD_CAST"attribute",BAD_CAST "yes"); //create son and grandson node = xmlNewNode(NULL, BAD_CAST "son"); xmlAddChild(root,node); xmlNewTextChild(node, NULL, BAD_CAST "grandson", BAD_CAST "grandson content"); xmlNodePtr grandson = xmlNewNode(NULL, BAD_CAST "grandson2"); xmlAddChild(node,grandson); xmlAddChild(grandson, xmlNewText(BAD_CAST "This is a grandson2 node")); //save xml int nRel = xmlSaveFile("test3.xml",doc); if (nRel != -1) { cout<<"create a xml:"<<nRel<<"bytes"<<endl; } //release xmlFreeDoc(doc); }
xmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。事实上它的定义是:xmlstring.h
xmlNewDoc函数创建一个新的文档指针。
xmlNewNode可以创建一个新的节点
xmlDocSetRootElement可以将该节点设为根节点
xmlNewTextChild直接添加一个文本子节点
第二创建节点的方式是先创建新节点,然后用xmlAddChild将新节点加入上层节点。
xmlSaveFile可以将xml存档
因为总是要在xmlChar*和char*之间进行类型转换,所以定义了一个宏BAD_CAST,其定义如下:xmlstring.h
#define BAD_CAST (xmlChar *)
3.遍历节点,修改与删除
xmlNodePtr head = root->children->next; while(head != NULL) { if(head->type == XML_ELEMENT_NODE) { cout<<"Name:"<<head->name<<endl; cout<<"Content:"<<xmlNodeGetContent(head->children)<<endl; // update test05 if ((!xmlStrcmp(head->name, (const xmlChar *)"test05"))) { xmlNodeSetContent(head->children,(const xmlChar *)"orz05"); } // remove node if (!xmlStrcmp(head->name, BAD_CAST "test07")) { xmlNodePtr tempNode; tempNode = head->next; xmlUnlinkNode(head); xmlFreeNode(head); head = tempNode; continue; } } head = head->next; }
xmlNodeGetContent可以取得节点的内文
xmlNodeSetContent可以设定节点的内文
可以透过xmlStrcmp来比较是否为要找的节点,xmlNodePtr的name属性则是节点名称,children则为内文节点
xmlUnlinkNode可以删除节点