boost.property_tree的高级用法(大家没见过的操做)

版权声明:本文为博主原创文章,未经博主容许不得转载。web

前一阵写项目,终于将这个boost下的xml读取类完成了,因为网上对property_trees的讲解不多,最多也就到get_child这个层面,因此我写起来很困难,前先后后用了两个星期左右吧,后来发现property_trees要是用好了操做特别骚,并且思路还挺简单的。spa

目前网上基本上都是在教你读这样的xmlcode

<root>  
 <delfile>  
  <filenum> 35 </filenum>  
  <paths>  
   <path>   
    <pathname>/tmp/tmp0/</pathname>  
    <before_hours> 0 </before_hours>  
   </path>     
 </delfile>  
 <backup>  
  <backuptime> 23:59 </backuptime>  
 </backup>  
</root>  

这样的xml很low,没有任何的信息。通常的xml都是这样的orm

<?xml version="1.0" encoding="utf-8"?>
<root>
    <Item name="project" desc="">
        <ChildItem name="project1" desc="file size" datatype="int">600</ChildItem>
        <ChildItem name="project2" desc="file size" datatype="int">353</ChildItem>
        <ChildItem name="project3" desc="file size" datatype="int">756</ChildItem>
        <ChildItem name="project4" desc="file size" datatype="int">888</ChildItem>
    </Item>
</Config>

像这样的xml才有价值,可是这里全部的child都同样,而且包含不少的属性,咱们怎么去读取value呢?xml

0X01 遍历方法一

经过遍历读取到map里,再从map中赛选数据blog

ptree m_pt;
string strAttrName
BOOST_FOREACH(ptree::value_type
&v1, m_pt.get_child(L"root")) { if (v1.first == L"Item") { strAttrName=v1.second.get<string>(L"<xmlattr>.name"); }
}

这样咱们就经过FOREACH遍历出来第一层xml的属性的值“project”,属性是('<xmlattr>')注释是('<xmlcomment>')
那么想在遍历出第二层的属性一样在里面再来一层FOREACH,可是这一层FOREACH要继承上面第一层的value_type的值继承

BOOST_FOREACH(wptree::value_type &v2, v1.second)
            {
                if (v2.first == L"ChildItem")
                {
                     string strChildAttrName = v2.second.get<wstring>(L"<xmlattr>.name");
              //取属性
} }

取值直接用date()就行,value_type有两个方法,第一个方法是first()取得是节点名例如Item ”,而第二个方法date()取的是节点的属性或者是value。utf-8

string value = v2.second.data();

最后将两个循环出来的值分别插入两个map里ci

ptree m_pt;
string strAttrName;
BOOST_FOREACH(ptree::value_type &v1, m_pt.get_child(L"root"))
{
    if (v1.first == L"Item")
    {
          strAttrName=v1.second.get<string>(L"<xmlattr>.name");
    }
       BOOST_FOREACH(wptree::value_type &v2, v1.second)
            {
                if (v2.first == L"ChildItem")
                {
                     string strChildAttrName = v2.second.get<wstring>(L"<xmlattr>.name");//取属性
                     string value = v2.second.data();
                    map1.insert(pair<string, string>(strChildAttrName, value )
                }
            }
                    m_map2.insert(pair < string, map<string, string>>(strAttrName, map1));
}                                             

最后map2就是你获得的xml树,固然你也能够多得到一些属性放进去,并作一些处理。get

 

0X02 遍历方法二

若是嫌FOREACH效率过低,你也能够用for循环来遍历xml树

首先咱们要是用到for循环的话,必须用到ptree中的find()方法,可是find()方法无法深刻查找,什么叫没法深刻查找?就是说你套了两层xml(就像个人例子同样)他就没法查找了,因此咱们必须先将最外一层节点去掉

ptree pt;
pt = pt.get_child(L"root");

将节点指向本身,这样就能够去掉最外一层节点。之后须要遍历查找

for (wptree::assoc_iterator iter = pt.find(L"Item"); iter != pt.not_found() && !bfind; ++iter)
{
          auto strAttrName = iter->second.get<wstring>(L"<xmlattr>.name");
}    

这样能够遍历出在外层的节点的属性

第二层节点经过第一层节点的迭代器来来迭代

for (wptree::assoc_iterator iter2 = iter->second.find(L"ChildItem"); iter2 != iter->second.not_found(); ++iter2)
{ auto strChildAttrName
= iter2->second.get<wstring>(L"<xmlattr>.name");
}

 具体实现

for (wptree::assoc_iterator iter = pt.find(L"Item"); iter != pt.not_found() && !bfind; ++iter)
{
       auto strAttrName = iter->second.get<string>(L"<xmlattr>.name");
    for (wptree::assoc_iterator iter2 = iter->second.find(L"ChildItem"); iter2 != iter->second.not_found(); ++iter2)
       {
          auto strChildAttrName = iter2->second.get<string>(L"<xmlattr>.name");          
    } }

以后分别输出、修改值、或者存入xml中均可以,可是由于最外层的节点已经删除了,因此咱们还得吧最外层的节点找回来

ptree pt1;
pt = pt.get_child(L"Config");
........
.......
pt1.add_child(L"Config", pt);
m_pt.clear();
m_pt = pt1;

必须再建一个ptree,这样加节点的时候才不会乱。

 

0X03 增长节点

增长就特别好说了

vector<string> vect_str;  
    vector<string>::iterator it;  
  
    vect_str.push_back("111111");  
    vect_str.push_back("222222");  
    vect_str.push_back("333333");  
    vect_str.push_back("444444");  

 for (it = vect_str.begin(); it != vect_str.end(); it++) { //迭代vector  
        data.put("<xmlattr>.key",it->data());  
        info.add_child("data",data);  
        data.clear() ;  
    }  
    pt.add_child("root.output.info",info)

放入map或者vactor里都行,以后遍历增长

 

0X04 删除节点

删除也同样,遍历以后删除节点。

ptree& persons = pt.get_child("root.persons");
for(auto it = persons.begin(); it != persons.end();) 
{
if(it->second.get<string>("name") == "dad") it = persons.erase(it); else ++it; }

0X05 修改值

改也很简单,遍历出所要改的值在节点,直接赋值而后再写回去就好了。

iter2->second.put_value(value);

 

0X06 抛出异常

增删改查都说完了,再说说异常吧,property_tree的异常分两种,一种是路径错误,一种是值错误很好判断,异常直接告诉你哪一个属性等有问题

try
    {    
        .......
    }
    catch (boost::property_tree::ptree_bad_path& e)
    {
        m_error = e.what();
        return false;
    }
    catch (boost::property_tree::ptree_bad_data& e)
    {
        m_error =e.what();
        return false;
    }

 

 研究了一个月,我敢说property_tree这个类库我用的国内最熟233333

相关文章
相关标签/搜索