缘起我的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

设定说明图解

6a702ae3fd4c60f5ac5c875c71b45e22.png

998c6ab5033a84c50be2b181ad1e89ed.png

如图所示,我在工程目录中创建了两个文件夹,在libxml中放了iconv跟libxml的.h文档

另外也创建了lib档,将所有的lib都放进去

226534d997f8a183d853525220aa9f46.png

48a3f199811a4bcdb4c675f447b39e44.png

然后再项目工程中设定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;

}

xmlDoc是一个struct,保存了一个xml的相关信息,例如文件名、文档类型、子节点等等;xmlDocPtr等于xmlDoc*,它搞成这个样子总让人以为是智能指针,其实不是,要手动删除的。

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<

}

//release

xmlFreeDoc(doc);

}

f4dc09e857226d7b42b9fe8b6d3596da.png

xmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。事实上它的定义是:xmlstring.hxmlNewDoc函数创建一个新的文档指针。

xmlNewNode可以创建一个新的节点

xmlDocSetRootElement可以将该节点设为根节点

xmlNewTextChild直接添加一个文本子节点

第二创建节点的方式是先创建新节点,然后用xmlAddChild将新节点加入上层节点。

xmlNewProp可以创建节点的属性

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<

cout<children)<

// 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;

}

在libxml中只需要针对XML_ELEMENT_NODE型态的节点进行搜索即可

xmlNodeGetContent可以取得节点的内文

xmlNodeSetContent可以设定节点的内文

可以透过xmlStrcmp来比较是否为要找的节点,xmlNodePtr的name属性则是节点名称,children则为内文节点

xmlUnlinkNode可以删除节点

237dab1aecaa2d6d8d320a84d6d64abc.png

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐