Open
Description
最近对libxml2的C++访问接口做了一层浅浅的封装,使得实际用起来比较方便。
测试用例
#include "xmlparser.h"
#include <string>
#include <iostream>
#include <sstream>
#include <map>
using namespace std;
class stFoo
{
public:
stFoo()
{
itemList.clear();
}
std::string toStr()
{
std::ostringstream os;
os << "index=" << index << std::endl;
os << "index2=" << index2 << std::endl;
for (const auto& item : itemList)
{
os << "item: id=" << item.first << " name=" << item.second << std::endl;
}
return os.str();
}
int32_t index {0};
float index2 {0.0};
std::map<int32_t,std::string> itemList;
};
bool loadConfig()
{
stFoo foo;
XmlParser xml;
if (!xml.initFile("test.xml")) return false;
XmlNode root = xml.getRootNode("config");
if (!root.valid())
{
printf("parse config failed\n");
return false;
}
std::string configname = "";
root.getStr("name", configname);
cout << configname << endl;
//parse node_a
XmlNode nodeA = root.getChild("node_a");
if (!nodeA.valid())
return false;
nodeA.getNum("index", foo.index);
nodeA.getNum("index2", foo.index2);
for (XmlNode item = nodeA.getChild("item"); item.valid(); ++item)
{
int id = 0;
item.getNum("id", id);
std::string name = "";
item.getStr("name", name);
foo.itemList[id] = name;
}
cout << foo.toStr() << endl;
return true;
}
int main()
{
loadConfig();
}
这里实际上主要把xmlNodePtr封装在XmlNode里,我们获取节点信息可以直接通过XmlNode。
获取指定名字的子节点: XmlNode.getChild(str);
获取相同名字的兄弟节点: ++XmlNode;
可以发现,我们要遍历节点的话可以通过父节点调用getChild(),配置++XmlNode实现。
在解析XmlNode属性的时候,我们通过传引用的方式去获取值:
xml.getNum("id", int_value);
xml.getNum("tax", double_value);
之前考虑过另外一种取值方式:
int_value = xml.getNum<int>("id");
double_value = xml.getNum<double>("tax");
其实两种方式内部实现都一样,都是用模板实现,之所以采用按引用取值(方法一),其一是因为按引用取值省去了临时变量以及赋值过程,一定程度上提高效率(虽然这种基本类型的开销并不大);其二是为了减少取值与类型的耦合,试想如果int_value由int类型改变为float,那么方法一的取值过程可以不变,但方法二的解析代码就得变为:
xml.getNum<float>("id", int_value);
恩,如果你改变了int_value的类型,而忘了该这里的解析代码呢,其结果可能就不是你想要的了。
注意
这个轻量级的解析接口实际上只有xml解析功能,不能生成xml,不支持解析Time(可以根据需要定制),不过使用起来还算方便。代码放在这里