boost I 容器与数据结构(五)

目录

十、property_tree

(一)处理xml

1.写xml、修改xml

2.解析xml

3.get()通过路径访问节点

4.get_child()获得含有多个子节点的节点对象

5.find()浅查找

6.get_optional()

7.获得注释及属性值

(二)处理Json

(三)处理ini

(四)处理info


十、property_tree

        property_tree 是一个保存了多个属性值的树形数据结构,它可以用类似路径的简单方式访问任意节点的属性,而且每个节点都可以用类似 STL 的风格遍历子节点。property_tree 特别适用于应用程序的配置数据处理,它可以解析 XML、JSON、INI 和 INFO这 4 种格式的文本数据,使用它能够减轻开发配置管理的工作。

boost I 容器与数据结构(五)

        property_tree库的核心类是 basic_ptree,它有两个重要的内部类型定义:self_type和 value_type 。这两个类型定义意味着 basic_ptree使用了组合模式,它是由多个 basic_ptree 复合而成的集合体,就像一个 std::list <key,basic_ptree> 。

  • self_type是basic_ptree模板实例化后自身的类型,它也是子节点的类型。
  • value_type 是节点的数据结构,它是一个 std::pair,含有节点的属性名(first)和节点自身(second)。

        同标准字符串类 basic_string 一样,通常我们不直接使用 basic_ptree ,而是使用预定义好的 typedef:ptree、 wptree 、 iptree 、 wiptree ,这些名字中的前缀 i 表示忽略大小写,前缀 w 表示支持宽字符。

(一)处理xml

1.写xml、修改xml

        property_tree可以使用write_xml( )写入配置信息,它有两种重载形式,可以接收文件名或输入输出流。它的操作具有对称性,使用模板成员函数 put( )可以修改属性树的节点值,如果子节点不存在就相当于新增节点,如果子节点存在则就地修改节点值。 put( )通常不需指定模板参数,因为属性值的类型可以自动推导。如果要向属性树中加入同名的新节点,需要使用add( )函数。

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
void StudyWidgets::TestPropertyTree()
{
    boost::property_tree::ptree write_pt;
    write_pt.put("info", "student info");
    write_pt.put("info.name", "Lisa");
    write_pt.put("info.age", 22);
    write_pt.put("info.subjects.subject", "Chinese");
    write_pt.add("info.subjects.subject", "Math");//向属性树中添加新节点
    write_pt.add("info.subjects.subject", "English");
    write_pt.put("info.teacher", "Tanasha");
    write_pt.put("info.message", "She know PI is 3.141592653");
    boost::property_tree::write_xml("./config1.xml", write_pt);
}
<?xml version="1.0" encoding="utf-8"?>
<info>student info
    <name>Lisa</name>
	<age>22</age>
	<subjects>
		<subject>Chinese</subject>
		<subject>Math</subject>
		<subject>English</subject>
	</subjects>
	<teacher>Tanasha</teacher>
	<message>She know PI is 3.141592653</message>
</info>

2.解析xml

        要解析xml配置文件,我们首先要用 read_xml( )函数解析 XML 并初始化 ptree ,它有两种重载形式,可以接收文件名或输入输出流。

void read_xml(const std::string &filename,
    Ptree &pt, 
    int flags = 0,
    const std::locale &loc = std::locale());

第三个参数flags是对xml中标签以外的文字进行操作的一个参数,它可以取值0、1、2、4,其中0表示不进行任何操作。

    //xml_parser_flags.hpp
    static const int no_concat_text  = 0x1;
    static const int no_comments     = 0x2;
    static const int trim_whitespace = 0x4;

第四个参数locale对象,它规定了数据格式,如日期、换行、编码等等,一般可以默认,详见C++ 标准库的 locale 类用法_LEE的专栏-CSDN博客_c++ locale

3.get()通过路径访问节点

        在初始化 ptree 后,我们可以用模板成员函数get ( ) 通过路径(默认使用点号"."作为路径分隔符)访问属性树内的节点,用模板参数指明获取属性的类型。ptree的 get ( )函数支持默认值的用法,在指定路径的同时可以指定默认值。如果属性树中不存在该属性,则使用默认值。由于默认值已经有类型信息,所以 get( )的返回值类型可以被自动推导出来,不必再加模板参数。

        property_tree 默认使用点号分隔路径,虽然不太符合操作系统和 XML 的习惯,但用它来表示有层次的属性还是很自然的。但有的时候,属性名中会出现点号, property_tree 也允许我们使用其他分隔符,如“ / ”。

4.get_child()获得含有多个子节点的节点对象

        对于有多个子节点的节点,我们就需要使用 get_child( )先获得子节点对象,再像使用标准容器一样用 begin( )和end( )遍历子节点。迭代器指向 ptree 的value_type,它的 second 成员是子节点自身,其值可以直接用 data( )或 get_value( )访问。

<?xml version="1.0" encoding="utf-8"?>
<info>student info
	<!-- this is a note -->
	<name id="1">Lisa</name>
	<age>22</age>
	<subjects>
		<subject>Chinese</subject>
		<subject>Math</subject>
		<subject>English</subject>
	</subjects>
	<teacher language="English">Tanasha</teacher>
	<message>
	<![CDATA[10<100]]>
	</message>
	<NO.1>She knew the PI was 3.141592653</NO.1>
</info>
    boost::property_tree::ptree pt;
    boost::property_tree::read_xml("./config.xml", pt, 4);
    //get()通过路径访问属性树内的节点
    std::string name = pt.get<std::string>("info.name");
    int age = pt.get<int>("info.age");
    std::cout << "name:" << name << ",age:" << age << std::endl;//name:Lisa,age:22
    //get()支持默认值
    std::string sex = pt.get<std::string>("info.sex", "女");
    std::cout << "sex:" << sex << std::endl;                    //sex:女
    //get_child()获得含有多个子节点的节点对象
    auto subjects = pt.get_child("info.subjects");
    //遍历:方法一
    for (auto& child : subjects)
    {
        std::cout << child.second.get_value<std::string>() << std::endl;
    }
    //方法二
    for (auto item = subjects.begin(); item != subjects.end(); item++)
    {
        std::cout << item->second.data() << std::endl;
    }
    try {
        //NO.1:She know PI is 3.141592653
        std::cout << "NO.1:" << pt1.get<std::string>(boost::property_tree::ptree::path_type("info/NO.1", '/')) << std::endl;
    }
    catch (std::exception e)
    {
        std::cout << e.what() << std::endl;//
    }

5.find()浅查找

        我们也可通过find( )成员函数来查找某个节点的值,但是find( )只支持浅层次查找,不能实现深层次的查找。

    //find()查找某个节点,浅层次,不支持深度查找
    auto item = pt.find("info");
    std::cout << "info:" << item->second.data() << std::endl;//student info

6.get_optional()

        get()函数有三种形式,除了前面的基本形式和默认值形式,还有一种get_optional,它也是默认值形式的用法 , 但它使用了 optional 库来包装返回值 , 如果 get 失败则 optional对象是无效的。

    auto teacher = pt.get_optional<std::string>("teacher");//应该是info.teacher
    if (teacher.is_initialized())
    {
        std::cout << teacher.get() << std::endl;
    }
    else {
        std::cout << "teacher not exist" << std::endl;//teacher not exist
    }

7.获得注释及属性值

        property_tree 本身没有实现 XML 解析器,而是使用非 Boost 的开源项目 rapidxml ,因此,property_tree 使用 rapidxml 将所有的 XML 节点转换为属性树对应的节点,节点的标签名是属性名,节点的内容是属性值。节点的属性保存在该节点的<xmlattr>下级节点,注释保存在<xmlcomment>中,节点的文本内容(如CDATA ) 保存在 <xmItext> 中。

    boost::property_tree::ptree pt1;
    boost::property_tree::read_xml("./config.xml", pt1);
    try {
        std::cout << "注释:" << pt1.get<std::string>("info.<xmlcomment>") << std::endl;
        std::cout << "id:" << pt1.get<std::string>("info.name.<xmlattr>.id") << std::endl;
        std::cout << "teacher language:" << pt1.get<std::string>("info.teacher.<xmlattr>.language") << std::endl;
        std::cout << "CDATA:" << pt1.get<std::string>("info.message") << std::endl;
    }
    catch (std::exception e)
    {
        std::cout << e.what() << std::endl;
    }

//注释: this is a note
//id:1
//teacher language:English
//CDATA:
//        10<100

(二)处理Json

        JSON ( JavaScript Object Notation ) 也是一种常用的数据交换格式,它的结构简单紧凑,它类似XML但没有那么多的“繁文缛节”。

#include <boost/property_tree/json_parser.hpp>

(三)处理ini

        INI格式是 Windows 操作系统下非常流行的一种配置数据的格式,它曾经被广泛应用,但它较 XML 和JSON有些不足:不支持多级层次,只有简单的key / value 形式,不能表达复杂的配置,所以其他格式的配置数据可能无法转换成 INI 格式。

#include <boost/property_tree/ini_parser.hpp>

(四)处理info

        INFO格式是 property_tree 的专用格式,它比 XML简洁,其风格类似 JSON ,但 INFO 带有许多 C ++ 的特征,如 # include 语句、斜杠字符转义等,特别适合 C ++ 程序员使用。

#include <boost/property_tree/info_parser.hpp>

上一篇:Centos下安装boost(笨蛋版)


下一篇:下载安装boost