c++ - Get SubTag details of Tag [Boost Porperty_tree XML] -
i trying details of "subchapter" tag. not know how information inside tag.
my xml looks this:
<xml> <chapter> <name>first chapter</name> <link>xyz1</link> <chapter> <name>first sub-chapter</name> <link>xyz2</link> </chapter> </chapter> </xml>
now want information of second chapter tag... c++ looks this:
boost::property_tree::ptree pt; boost::property_tree::xml_parser::read_xml("file.xml", pt, boost::property_tree::xml_parser::trim_whitespace ); boost_foreach(const boost::property_tree::ptree::value_type& node, pt.get_child("xml")) { if( node.first == "chapter" ) { chapter chp; chp.name = node.second.get<std::string>("name"); chp.link = node.second.get<std::string>("link"); //boost::property_tree::ptree::value_type test = node.second.get<boost::property_tree::ptree::value_type>("chapter"); //chapter chp2; //chp2.name = test.second.get<std::string>("name"); //chp2.link = test.second.get<std::string>("link"); //chp.sub_chapters.push_back( chp2 ); m_chapters.push_back( chp ); } }
i tried can see commented lines. tried use boost_foreach. there way reach goal?
thanks help! greetz!
i'd use simple recursive find algorithm:
template <typename tree, typename out> out find_all_chapters(tree const& pt, out out) { using namespace boost::property_tree; boost_foreach(typename tree::value_type const& ch, pt) { if (ch.first == "chapter") { *out++ = chapter { ch.second.template get<std::string>("name"), ch.second.template get<std::string>("link") }; out = find_all_chapters(ch.second, out); } } return out; }
this assumes nested chapters appear inside other chapters (otherwise move recursive call out of if()
conditional block.)
you can use like
int main() { boost::property_tree::ptree pt; boost::property_tree::xml_parser::read_xml("file.xml", pt, boost::property_tree::xml_parser::trim_whitespace ); std::vector<chapter> m_chapters; find_all_chapters(pt.get_child("xml"), back_inserter(m_chapters)); (auto& ch : m_chapters) std::cout << "chapter '" << ch.name << "', link: '" << ch.link << "'\n"; }
and prints
chapter 'first chapter', link: 'xyz1' chapter 'first sub-chapter', link: 'xyz2'
full listing
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <boost/foreach.hpp> #include <iostream> struct chapter { std::string name, link; }; template <typename tree, typename out> out find_all_chapters(tree const& pt, out out) { using namespace boost::property_tree; boost_foreach(typename tree::value_type const& ch, pt) { if (ch.first == "chapter") { *out++ = chapter { ch.second.template get<std::string>("name"), ch.second.template get<std::string>("link") }; out = find_all_chapters(ch.second, out); } } return out; } int main() { boost::property_tree::ptree pt; boost::property_tree::xml_parser::read_xml("file.xml", pt, boost::property_tree::xml_parser::trim_whitespace ); std::vector<chapter> m_chapters; find_all_chapters(pt.get_child("xml"), back_inserter(m_chapters)); (auto& ch : m_chapters) std::cout << "chapter '" << ch.name << "', link: '" << ch.link << "'\n"; }
update
to comments, here's how i'd it:
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <boost/foreach.hpp> #include <iostream> struct chapter { std::string name, link; std::vector<chapter> sub_chapters; }; void find_all_chapters(boost::property_tree::ptree const& pt, chapter& into) { for(auto& ch : pt) { if (ch.first == "chapter") { into.sub_chapters.push_back({ ch.second.template get<std::string>("name"), ch.second.template get<std::string>("link"), {} }); find_all_chapters(ch.second, into.sub_chapters.back()); } } } void print(chapter const& book_or_chapter, std::string const& indent = "") { (auto& ch : book_or_chapter.sub_chapters) { std::cout << indent << " - chapter '" << ch.name << "', link: '" << ch.link << "'\n"; print(ch, " " + indent); } } int main() { boost::property_tree::ptree pt; boost::property_tree::xml_parser::read_xml(std::cin, pt, boost::property_tree::xml_parser::trim_whitespace ); chapter book; find_all_chapters(pt.get_child("xml"), book); print(book); }
with input xml like
<xml> <chapter> <name>first chapter</name> <link>xyz1</link> <chapter> <name>first sub-chapter</name> <link>xyz2</link> <chapter> <name>sub sub</name> <link>xyz3</link> <chapter> <name>sub sub sib</name> <link>xyz4</link> </chapter> </chapter> </chapter> </chapter> <chapter> <name>second chapter</name> <link>abc1</link> <chapter> <name>first sub-chapter</name> <link>abc2</link> </chapter> </chapter> </xml>
prints
- chapter 'first chapter', link: 'xyz1' - chapter 'first sub-chapter', link: 'xyz2' - chapter 'sub sub', link: 'xyz3' - chapter 'sub sub sib', link: 'xyz4' - chapter 'second chapter', link: 'abc1' - chapter 'first sub-chapter', link: 'abc2'
Comments
Post a Comment