boost解析xml文件(读取)

昨天做了个解析xml文件的接口,百度了boost的接口,再结合自己踩过的坑,特做此记录。
先上代码,看看如何获取到xml文件节点属性和内容:
xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<root name="root"> 

        <strage name="asd" alias="13" classId="13.22">
                        data1   
                <id>12</id>   
                <name>"jack"</name>   
                <code>"0001"</code> 
        </strage> 

        <strage name="abbasd" alias="14" classId="14.22">
                        hello2
                <id >13</id>   
                <name>"toni"</name>   
                <code>"0002"</code> 
        </strage> 
        <strage name="assasd" alias="15" classId="15.44">
                   disk 333
                <id >14</id>   
                <name>"hate"</name>   
                <code>"0003"</code> 
        </strage> 
</root> 

代码如下:

#include <iostream>
using namespace std;

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using namespace boost::property_tree;

string& trim(string &s) 
{
	if (s.empty()) 
	{
		return s;
	}
	string blanks("\f\v\r\t\n ");
	s.erase(0, s.find_first_not_of(blanks));
	s.erase(s.find_last_not_of(blanks) + 1);
	return s;
}

int main(int argc, char **argv)
{
	ptree pt;
	const char *filename = "t.xml";
	read_xml(filename, pt);
	const ptree &strages = pt.get_child("root");
	for (auto it = strages.begin(); it != strages.end(); ++it)
	{
		if (it->first != "strage") {
			cout << it->first << endl;
			continue;
		}
		ptree strage = it->second;
		string &data = strage.data();
		data = trim(data);
		string name = strage.get<string>("<xmlattr>.name");
		int alias = strage.get<int>("<xmlattr>.alias");
		float classId = strage.get<float>("<xmlattr>.classId");
		printf("data: %s\nname: %s alias: %d classId: %f\n", data.c_str(), name.c_str(), alias, classId);
		const ptree& idChild = strage.get_child("id");
		const ptree& nameChild = strage.get_child("name");
		const ptree& codeChild = strage.get_child("code");
		const string& child_id = idChild.data();
		const string& child_name = nameChild.data();
		const string& child_code = codeChild.data();
		printf("id: %s name: %s code: %s\n", child_id.c_str(), child_name.c_str(), child_code.c_str());
	}
	return 0;
}

运行结果如下:

<xmlattr>
data: data1
name: asd alias: 13 classId: 13.220000
id: 12 name: "jack" code: "0001"
data: hello2
name: abbasd alias: 14 classId: 14.220000
id: 13 name: "toni" code: "0002"
data: disk 333
name: assasd alias: 15 classId: 15.440000
id: 14 name: "hate" code: "0003"

最大的坑:
在遍历子节点时,如果父节点本身带有属性,会多出一个的子节点,所以要判断一下子节点的first是否等于子节点的名称(<xxx 中的xxx,即标签名)。
第二个坑:
不用怀疑,当获取某个节点的内容时,由于xml的缩进换行美化效果,会造成内容前面或后面会有回车换行,甚至可能由于手动编辑过,会有我们看不到的制表符/t或空格,所以在获取内容时,往往需要去除两端空白。
第三个坑:
获取xml的某个节点的属性xmlattr时,如果该属性不存在,会抛异常,所以建议使用时给默认值可以避免抛出异常,如果属性必须存在,可以用try语句。

下面演示获取具体某个节点:

#include <iostream>
#include <string.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using namespace boost::property_tree;

using namespace std;


ptree *get_node_by_attr(ptree &nodes, const string label, const string attr, const string value)
{
        for (ptree::iterator it = nodes.begin(); it != nodes.end(); it++)
        {
                if (it->first != label)
                {
                        continue;
                }
                ptree &item = it->second;
                string name = item.get<string>(string("<xmlattr>.") + attr, "");
                if (name == value)
                {
                        return &item;
                }
        }
        return NULL;
}

string& trim(string &s) 
{
        if (s.empty()) 
        {
                return s;
        }
        string blanks("\f\v\r\t\n ");
        s.erase(0, s.find_first_not_of(blanks));
        s.erase(s.find_last_not_of(blanks) + 1);
        return s;
}

int main(int argc, char **argv)
{

        ptree pt;
        xml_parser::read_xml(string("t.xml"), pt, xml_parser::no_comments);
        ptree &child = pt.get_child("root");
        const string label = "strage";
        const string attr = "name";
        const string value = "abbasd";
        ptree *node = get_node_by_attr(child, label, attr, value);
        if (NULL == node)
        {
                cout << "没有name=" + attr + "的" + label + "节点" <<endl;
                return 0;
        }
        ptree& strage = *node;

        string &data = strage.data();
        data = trim(data);
        string name = strage.get<string>("<xmlattr>.name");
        int alias = strage.get<int>("<xmlattr>.alias");
        float classId = strage.get<float>("<xmlattr>.classId");
        printf("data: %s\nname: %s alias: %d classId: %f\n", data.c_str(), name.c_str(), alias, classId);
        const ptree& idChild = strage.get_child("id");
        const ptree& nameChild = strage.get_child("name");
        const ptree& codeChild = strage.get_child("code");
        const string& child_id = idChild.data();
        const string& child_name = nameChild.data();
        const string& child_code = codeChild.data();
        printf("id: %s name: %s code: %s\n", child_id.c_str(), child_name.c_str(), child_code.c_str());


        return 0;
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值