在日常的开发系统中,不可避免的会解析配置文件,因为使用配置文件更直观,而且修改配置文件就不用再编译代码,当工程很大的时候,编译代码会是一件很痛苦的事。不同的需求的配置文件不同,Boost提供了一个property_tree来解析.xml,.ini,.json,.info四种格式配置文件。
.xml文件
.xml现在已经被广泛应用到数据交换格式,并且property_tree是树形结构,和.xml文件格式很相近。基本格式是<attribute> value </attribute>
,属性包含属性值的形式。现在以学生信息举例。
<conf>
<school> scu </school>
<person>
<name> freehyan </name>
<sex> male </sex>
<age> 22 </age>
</person>
</conf>
property_tree 源码浅析
template <typename Key, typename Data, typename KeyCompare>
class basic_ptree
{
public:
typedef basic_ptree<Key, Data, KeyCompare> self_type;
typedef std::pair<const Key, self_type> value_type;
basic_ptree();
basic_ptree& operator=(const self_type & );
//...
data_type& data();
template<typename Type> Type get(const path_type &) const;
self_type& get_child(const path_type &);
self_type& put_child(const path_type &, const self_type &);
self_type& add_child(const path_type &, const self_type &);
//...
}
property_tree的核心类是basic_tree,内部重新定义了两个重要类型self_type, value_type。self_type是模板实例化的自身类型,而value_type是节点的数据结构,本质是std::pair,含有节点的属性名和本身。最后几个函数是获取,添加等操作,注意源码内容不止于此。basic_tree不能直接使用,通常使用的是 typedef basic_ptree<std::string, std::string> ptree;
读取.xml
Boost中property_tree内部使用的是小巧开源xml解析器–rapidxml。读取配置文件是通过read_xml函数,当节点不存在的时候,会抛出异常。
- 在初始化ptree后,可以使用get()通过路径访问属性树内节点,用模板参数指明获取属性的类型。路径分隔符是(.),小数点的样子。
如:pt.get<std::string>("conf.theme")
- ptree的get()函数支持缺省值的用法,即如果属性不存在,则使用缺省值。由于缺省值已经有类型信息,因此get()的返回值类型可以自动推导,所以不必再加模板参数。
如:pt.get("conf.theme", 100);
- 访问有多个属性值的子节点,比如第一部分中的person就是这样的子节点。可以通过迭代器的方式访问获取值。
auto child = pt.get_child("conf.person");
for (auto& x : child)
{
std::cout << x.first;
std::cout << x.second.get_value<std::string>() << std::endl;
}
for (auto pos=child.begin(); pos != child.end(); pos++)
{
std::cout << pos->second.get_value<std::string>() << std::endl;
}
写入.xml
有读就有写,property_tree也支持写入配置信息,从源码中就可以看出相应的函数,使用模板函数put()可以修改属性树的节点值,如果节点不存在就新增节点,如果存在就修改属性值。不过通常put()不需要指定模板参数,因为和缺省值读取一样,写入也可以自行推导。
pt.put("conf.theme", "black theme");
boost::property_tree::write_xml("abc.xml", pt);
更多用法
其实basic_tree的语法很像stl容器,所以大部分的函数api对其也适用,因为它就像std::list<std::string, boost::property_tree::ptree>
,比如可以使用find函数。
属性树的标签名是属性名,内容是属性值。节点的属性保存在节点<xmlattr>
的下级节点,注释保存在<xmlcomment>
中。
<conf>
<!-- comment -->
<theme id = "1001"> black theme </theme>
</conf>
boost::property_tree::ptree pt;
boost::property_tree::read_xml("abc.xml", pt);
std::cout << pt.get<std::string>("conf.<xmlcomment>") << std::endl;
std::cout << pt.get<int>("conf.theme.<xmlattr>.id") << std::endl;
参考
【1】 Boost 程序库完全开发指南,书籍
【2】http://www.cnblogs.com/qicosmos/p/3555668.html
【3】http://www.boost.org/doc/libs/1_60_0/doc/html/property_tree.html