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

相關文章
相關標籤/搜索