如何让boost属性树打印所有子树然后结束父树

Posted

技术标签:

【中文标题】如何让boost属性树打印所有子树然后结束父树【英文标题】:how to make boost property tree print all subtrees and then end parent tree 【发布时间】:2017-03-28 12:22:37 【问题描述】:

在下面的代码中,我试图遍历深度嵌套的地图,但我不确定属性树如何解释数据。

实际上是打印所有父树数据,然后开始打印子树

 #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
#include <fstream>

#include <boost/archive/xml_oarchive.hpp>
#include <string>
#include <iostream>
#include <map>
#include <map>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <iterator>
    using namespace boost::property_tree;
struct values

    std::string a;
    std::string b;
    values():a("milepost"),b("dummyval");
    values( std::string ab, std::string bc)
    
        a=ab;
        b=bc;

    ;

    bool operator<(const values& other) const 
         return (a< other.a && b < other.b) ;
         
    friend std::ostream& operator<<(std::ostream& os, const values& val);

;
std::ostream& operator<< (std::ostream& os , const values& val)

  os << val.a <<"\t"<< val.b;
  return os;


int main(int argc, const char * argv[]) 

    ptree pt;
    auto& list = pt.add_child("list", ptree);
    auto& assetlist = pt.add_child("assetlist", ptree);
    //Create set of types firstly
    std::set<std::string> types ;
    types.insert("et");
    types.insert("pt");

    typedef std::map< int,std::set<std::string> > myGroupsMap;
    typedef std::map<std::string,values>  myWsData;
    typedef std::map< std::string , std::set<myWsData> > myFinalData;
    typedef std::map< int,std::set<myFinalData> > myGroupData;

    myGroupsMap groupTypeMap;

    groupTypeMap.insert(std::make_pair(1, types) );


    groupTypeMap.insert(std::make_pair(2, types) );
    groupTypeMap.insert(std::make_pair(3, types) );
    groupTypeMap.insert(std::make_pair(4, types) );
    groupTypeMap.insert(std::make_pair(5, types) );

    //Create the object of structure
    values a,b,c;

    //Create map and insert the string and its corresponding structure
    myWsData et_Data1,pt_Data2;
    et_Data1.insert(std::make_pair("780256", a));
    et_Data1.insert(std::make_pair("780255", b));
    et_Data1.insert(std::make_pair("780254", c));

    pt_Data2.insert(std::make_pair("780256", a));
    pt_Data2.insert(std::make_pair("780255", b));
    pt_Data2.insert(std::make_pair("780254", c));

    std::set<myWsData> myet_pt_data;
    myet_pt_data.insert(et_Data1);
    myet_pt_data.insert(pt_Data2);

    myFinalData fd , fd1 , fd2 ;
    fd.insert(std::make_pair ("ET",myet_pt_data) );
    fd.insert(std::make_pair ("PT",myet_pt_data) );

    fd1.insert(std::make_pair ("ET",myet_pt_data) );
    fd1.insert(std::make_pair ("PT",myet_pt_data) );

    fd2.insert(std::make_pair ("ET",myet_pt_data) );
    fd2.insert(std::make_pair ("PT",myet_pt_data) );

    std::set<myFinalData> mfd;
    mfd.insert(fd);
    mfd.insert(fd1);
    mfd.insert(fd2);



    myGroupData mygd;
    mygd.insert(std::make_pair (1,mfd) );
    mygd.insert(std::make_pair (2,mfd) );
    mygd.insert(std::make_pair (3,mfd) );

  for (auto &a : mygd)
   
       for(auto &b:a.second)  //Get the std::set
       
            for(auto &the_map:b) //get map from set
            

                list.add("GroupId", a.first);

                list.add("GroupType",the_map.first);
                for(auto &the_set:the_map.second)
                
                    // the_map takes all values from the set
                    // the_map actual type is std::map<std::string,values>&
                    for (const auto& the_map : the_set)
                    
       // the_value takes all value of the current map (the_map)
       // the_value actual type is std::pair<std::string,values>&
                            assetlist.add("AssetId",the_map.first);

                            assetlist.add("Milepost",the_map.second.a);
                            assetlist.add("Dummy",the_map.second.b);

                            // list.add("value", map.first)

              //  .add("<xmlattr>.active", true);
                     
                
            
        
    


    xml_parser::write_xml(std::cout, pt);

    return 0;

输出(摘录):

<?xml version="1.0" encoding="utf-8"?>
<list>
<GroupId>1</GroupId>
<GroupType>ET</GroupType>
<GroupType>PT</GroupType>
<GroupId>2</GroupId>
<GroupType>ET</GroupType>
<GroupType>PT</GroupType>
<GroupId>3</GroupId>
<GroupType>ET</GroupType>
<GroupType>PT</GroupType>
</list>
<assetlist>
  <AssetId>780254</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780255</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780256</AssetId><Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
</assetlist>

预期输出(摘录)

<GroupId>1</GroupId>
<GroupType>ET</GroupType>
<assetlist>
  <AssetId>780254</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780255</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780256</AssetId><Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
</assetlist>
<GroupType>PT</GroupType>
<assetlist>
  <AssetId>780254</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780255</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780256</AssetId><Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
</assetlist>
<GroupId>2</GroupId>
<GroupType>ET</GroupType>
<assetlist>
  <AssetId>780254</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780255</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780256</AssetId><Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
</assetlist>
<GroupType>PT</GroupType>
<assetlist>
  <AssetId>780254</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780255</AssetId>
  <Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
  <AssetId>780256</AssetId><Milepost>milepost</Milepost>
  <Dummy>dummyval</Dummy>
</assetlist>

如何系统地添加它? 代码可以在http://coliru.stacked-crooked.com/a/763741c78d494654运行

谢谢 光辉

【问题讨论】:

【参考方案1】:

树包含它们的子树。打印父树在关闭父树之前打印子树。

您当前的输出和“预期”输出都是无效文档(只能有 1 个根元素)。

您需要将数据放入一棵树中,例如:

ptree pt;
auto& root = pt.add_child("root", ptree);
auto& list = root.add_child("list", ptree);
auto& assetlist = root.add_child("assetlist", ptree);

然后打印以下文档:

Live On Coliru

<?xml version="1.0" encoding="utf-8"?>
<root>
  <list>
    <GroupId>1</GroupId>
    <GroupType>ET</GroupType>
    <GroupId>1</GroupId>
    <GroupType>PT</GroupType>
    <GroupId>2</GroupId>
    <GroupType>ET</GroupType>
    <GroupId>2</GroupId>
    <GroupType>PT</GroupType>
    <GroupId>3</GroupId>
    <GroupType>ET</GroupType>
    <GroupId>3</GroupId>
    <GroupType>PT</GroupType>
  </list>
  <assetlist>
    <AssetId>780254</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780255</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780256</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780254</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780255</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780256</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780254</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780255</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780256</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780254</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780255</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780256</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780254</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780255</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780256</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780254</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780255</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
    <AssetId>780256</AssetId>
    <Milepost>milepost</Milepost>
    <Dummy>dummyval</Dummy>
  </assetlist>
</root>

这实际上是格式良好的 XML :)

更新给cmets

如果您想使用 grouptypes 对资产列表进行分组,您....需要编写代码来执行此操作吗?

Live On Coliru

ptree pt;
auto& list = pt.add_child("list", ptree);
//Create set of types firstly
std::set<std::string> types  "et", "pt" ;

typedef std::map<std::string,values>  myWsData;
typedef std::map< std::string , std::set<myWsData> > myFinalData;
typedef std::map< int,std::set<myFinalData> > myGroupData;

values a,b,c;

myWsData et_Data1   "780256", a ,  "780255", b ,  "780254", c  , 
         pt_Data2 = et_Data1;

std::set<myWsData> myet_pt_data  et_Data1, pt_Data2 ;

myFinalData fd , fd1 = fd, fd2 = fd;

std::set<myFinalData> mfd 
      "ET", myet_pt_data ,  "PT", myet_pt_data  ,
      "ET", myet_pt_data ,  "PT", myet_pt_data  ,
      "ET", myet_pt_data ,  "PT", myet_pt_data   ;
mfd.insert(fd);
mfd.insert(fd1);
mfd.insert(fd2);

myGroupData mygd;
mygd.insert(std::make_pair (1,mfd) );
mygd.insert(std::make_pair (2,mfd) );
mygd.insert(std::make_pair (3,mfd) );

for (auto &a : mygd)

    for(auto &b:a.second)  //Get the std::set
    
        for(auto &the_map:b) //get map from set
        
            auto& group = list.add_child("group", );

            group.add("<xmlattr>.GroupId", a.first);
            group.add("GroupType",the_map.first);

            auto& assetlist = group.add_child("assetlist", ptree);

            for(auto &the_set:the_map.second)
            
                // the_map takes all values from the set
                // the_map actual type is std::map<std::string,values>&
                for (const auto& the_map : the_set)
                
                    // the_value takes all value of the current map (the_map)
                    // the_value actual type is std::pair<std::string,values>&
                    assetlist.add("AssetId",the_map.first);

                    assetlist.add("Milepost",the_map.second.a);
                    assetlist.add("Dummy",the_map.second.b);

                    // assetlist.add("value", map.first)

                    //  .add("<xmlattr>.active", true);
                
            

        
    


xml_parser::write_xml(std::cout, pt);

打印:

<?xml version="1.0" encoding="utf-8"?>
<list>
  <group GroupId="1">
    <GroupType>ET</GroupType>
    <assetlist>
      <AssetId>780254</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780255</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780256</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
    </assetlist>
  </group>
  <group GroupId="1">
    <GroupType>PT</GroupType>
    <assetlist>
      <AssetId>780254</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780255</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780256</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
    </assetlist>
  </group>
  <group GroupId="2">
    <GroupType>ET</GroupType>
    <assetlist>
      <AssetId>780254</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780255</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780256</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
    </assetlist>
  </group>
  <group GroupId="2">
    <GroupType>PT</GroupType>
    <assetlist>
      <AssetId>780254</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780255</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780256</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
    </assetlist>
  </group>
  <group GroupId="3">
    <GroupType>ET</GroupType>
    <assetlist>
      <AssetId>780254</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780255</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780256</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
    </assetlist>
  </group>
  <group GroupId="3">
    <GroupType>PT</GroupType>
    <assetlist>
      <AssetId>780254</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780255</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
      <AssetId>780256</AssetId>
      <Milepost>milepost</Milepost>
      <Dummy>dummyval</Dummy>
    </assetlist>
  </group>
</list>

【讨论】:

哎呀,那不符合我的要求,每个组 id 都有一个组类型和它的资产列表,这不是那种打印方式。 Ex 如果我们有 cout 而不是添加函数,它会完全按照我需要的方式打印值 什么? ...也许(a)你可以让问题更清楚(b)你可以写你知道你需要的代码。 for (auto &amp;a : mygd) for(auto &amp;b:a.second) /*Get the std::set*/ for(auto &amp;the_map:b) /*get map from set*/ - 您希望我们能够神奇地逆向设计您的问题域和功能需求。? 也许你想要类似coliru.stacked-crooked.com/a/9160e5d0c0a18c7c 的东西——它既是有效的 XML,又是 ,它按 groupID 对资产进行分组。为此,我编写了一些有效的 XML。请参阅答案中的更新 噢,我正要发布 cout 的数据啊

以上是关于如何让boost属性树打印所有子树然后结束父树的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer:树的子结构

使用 boost 属性树遍历 json 属性键和值

如何包含特定 TreeView 节点的复选框?

打印 boost 属性树生成的 xml

P2922 [USACO08DEC]秘密消息Secret Message

回溯法