游戏开发中配置文件主要有ini个xml,xml用的更多些。
我用的较多的库是tinyXML,一般应用已足矣胜任,网上教程一大堆,就不写了。再次介绍另一个xml库,转载的其他人的blog的文章。
目前我公司开发的Nexus Engine的底层对象序列化使用了TinyXML来读写XML文件。TinyXML有两个不爽的地方,一是它的接口使用FILE*,另外一个是它对 wchar_t不能很好的支持。前阵子看Boost库的更新中多了一个PropertyTree,他在处理XML时用到了另外一个小的库 --RapidXML。既然间接的是Boost库的一部分,所以是值得一试的。于是找到其官方网站(http://rapidxml.sourceforge.net/ )研究了一番。一看之下,甚是满意,也推荐给大家看看!
首先就是速度,据它自己宣称比TinyXML快30到60倍 ,比Xerces DOM快50到100倍!详细的测试比较请见其用户手册(http://rapidxml.sourceforge.net/manual.html )的“4. Performance ”一节。
其次它的设计非常的简洁,只依赖于标准库中的几个基本的类。它的输入输出都是字符串,这样很好,一个库就应该关注自己核心的内容,做尽量少的事情。它的API其实和TinyXML倒是有几分相似,用过TinyXML的人应该很容易上手:
TinyXML主要接口类 RapidXML的主要接口类
class TiXmlDocument template
class xml_document
class TiXmlNode template
class xml_node
class TiXmlAttribute template
class xml_attribute
下面还是看一个具体的例子来体验一下,下面是TinyXML官方教程中创建XML文档的一段代码:
view plaincopy to clipboardprint?
void build_simple_doc( )
{
// Make xml: World
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
TiXmlElement * element = new TiXmlElement( "Hello" );
TiXmlText * text = new TiXmlText( "World" );
element->LinkEndChild( text );
doc.LinkEndChild( decl );
doc.LinkEndChild( element );
doc.SaveFile( "madeByHand.xml" );
}
void build_simple_doc( )
{
// Make xml: World
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
TiXmlElement * element = new TiXmlElement( "Hello" );
TiXmlText * text = new TiXmlText( "World" );
element->LinkEndChild( text );
doc.LinkEndChild( decl );
doc.LinkEndChild( element );
doc.SaveFile( "madeByHand.xml" );
}
下面是使用RapidXML实现类似功能的代码:
view plaincopy to clipboardprint?
void build_simple_doc_by_rapidxml()
{
xml_document<> doc;
xml_node<>* decl = doc.allocate_node(node_declaration);
xml_attribute<>* decl_ver =
doc.allocate_attribute("version", "1.0");
decl->append_attribute(decl_ver);
doc.append_node(decl);
xml_node<>* node =
doc.allocate_node(node_element, "Hello", "World");
doc.append_node(node);
string text;
rapidxml::print(std::back_inserter(text), doc, 0);
// write text to file by yourself
}
void build_simple_doc_by_rapidxml()
{
xml_document<> doc;
xml_node<>* decl = doc.allocate_node(node_declaration);
xml_attribute<>* decl_ver =
doc.allocate_attribute("version", "1.0");
decl->append_attribute(decl_ver);
doc.append_node(decl);
xml_node<>* node =
doc.allocate_node(node_element, "Hello", "World");
doc.append_node(node);
string text;
rapidxml::print(std::back_inserter(text), doc, 0);
// write text to file by yourself
}
下面是使用RapidXML分析XML的样例代码:
view plaincopy to clipboardprint?
void parse_doc_by_rapidxml(char* xml_doc)
{
xml_document<> doc; // character type defaults to char
doc.parse<0>(xml_doc); // 0 means default parse flags
xml_node<> *node = doc.first_node("Hello");
string node_val = node->value();
}
void parse_doc_by_rapidxml(char* xml_doc)
{
xml_document<> doc; // character type defaults to char
doc.parse<0>(xml_doc); // 0 means default parse flags
xml_node<> *node = doc.first_node("Hello");
string node_val = node->value();
}
首先上一个简单的xml写文件
如下:
#include < rapidxml / rapidxml.hpp >
#include < rapidxml / rapidxml_utils.hpp >
#include < rapidxml / rapidxml_print.hpp >
using namespace rapidxml;
int main()
{
xml_document <> doc;
xml_node <>* rot = doc.allocate_node(rapidxml::node_pi,doc.allocate_string( " xml version='1.0' encoding='utf-8' " ));
doc.append_node(rot);
xml_node <>* node = doc.allocate_node(node_element, " config " , " information " );
xml_node <>* color = doc.allocate_node(node_element, " color " ,NULL);
doc.append_node(node);
node -> append_node(color);
color -> append_node(doc.allocate_node(node_element, " red " , " 0.1 " ));
color -> append_node(doc.allocate_node(node_element, " green " , " 0.1 " ));
color -> append_node(doc.allocate_node(node_element, " blue " , " 0.1 " ));
color -> append_node(doc.allocate_node(node_element, " alpha " , " 1.0 " ));
xml_node <>* size = doc.allocate_node(node_element, " size " ,NULL);
size -> append_node(doc.allocate_node(node_element, " x " , " 640 " ));
size -> append_node(doc.allocate_node(node_element, " y " , " 480 " ));
node -> append_node(size);
xml_node <>* mode = doc.allocate_node(rapidxml::node_element, " mode " , " screen mode " );
mode -> append_attribute(doc.allocate_attribute( " fullscreen " , " false " ));
node -> append_node(mode);
std:: string text;
rapidxml::print(std::back_inserter(text), doc, 0 );
std::cout << text << std::endl;
std::ofstream out ( " config.xml " );
out << doc;
system( " PAUSE " );
return EXIT_SUCCESS;
}
生成的xml文件为:
< config >
< color >
< red > 0.1 </ red >
< green > 0.1 </ green >
< blue > 0.1 </ blue >
< alpha > 1.0 </ alpha >
</ color >
< size >
< x > 640 </ x >
< y > 480 </ y >
</ size >
< mode fullscreen ="false" > screen mode </ mode >
</ config >
说实话 感觉这个比较不错
希望更多的人使用它!
接上篇
本文主要涉及rapidxml读文件的操作
基本的步骤为
首先获取xml文件数据
然后分析数据
获取节点
获取属性
获取名字
获取值
...
代码如下:
#include < rapidxml / rapidxml.hpp >
#include < rapidxml / rapidxml_utils.hpp >
#include < rapidxml / rapidxml_print.hpp >
using namespace rapidxml;
int main()
{
file <> fdoc( " config.xml " );
std::cout << fdoc.data() << std::endl;
xml_document <> doc;
doc.parse < 0 > (fdoc.data());
std::cout << doc.name() << std::endl;
// ! 获取根节点
xml_node <>* root = doc.first_node();
std::cout << root -> name() << std::endl;
// ! 获取根节点第一个节点
xml_node <>* node1 = root -> first_node();
std::cout << node1 -> name() << std::endl;
xml_node <>* node11 = node1 -> first_node();
std::cout << node11 -> name() << std::endl;
std::cout << node11 -> value() << std::endl;
// ! 修改之后再次保存
xml_node <>* size = root -> first_node( " size " );
size -> append_node(doc.allocate_node(node_element, " w " , " 0 " ));
size -> append_node(doc.allocate_node(node_element, " h " , " 0 " ));
std:: string text;
rapidxml::print(std::back_inserter(text),doc, 0 );
std::cout << text << std::endl;
std::ofstream out ( " config.xml " );
out << doc;
system( " PAUSE " );
return EXIT_SUCCESS;
}
生成的xml为:
< config >
< color >
< red > 0.1 </ red >
< green > 0.1 </ green >
< blue > 0.1 </ blue >
< alpha > 1.0 </ alpha >
</ color >
< size >
< x > 640 </ x >
< y > 480 </ y >
</ size >
< mode fullscreen ="false" > screen mode </ mode >
</ config >
需要说明的是rapidxml明显有一个bug
那就是append_node(doc.allocate_node(node_element,"h","0"));的时候并不考虑该对象是否存在!
经过这2篇 基本上就可以使用xml了
当然这里并没有涉及异常处理