如何让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 &a : mygd) for(auto &b:a.second) /*Get the std::set*/ for(auto &the_map:b) /*get map from set*/
- 您希望我们能够神奇地逆向设计您的问题域和功能需求。?
也许你想要类似coliru.stacked-crooked.com/a/9160e5d0c0a18c7c 的东西——它既是有效的 XML,又是 ,它按 groupID 对资产进行分组。为此,我编写了一些有效的 XML。请参阅答案中的更新。
噢,我正要发布 cout 的数据啊以上是关于如何让boost属性树打印所有子树然后结束父树的主要内容,如果未能解决你的问题,请参考以下文章