Search code examples
c++boostboost-propertytree

Boost ptree iteration over two nodes


i have an xml like this

<examples>
<example>
<test name="img">testme</test>
<test name="img1">testme1</test>
<test name="img1">testme2</test>
</example>
<example>
<test name="text">testme</test>
<test name="text">testme1</test>
<test name="text">testme2</test>
</example>
</examples>

I tried this code it extracts only first example node

ptree ptree;
        read_xml(doc_path, ptree);

        BOOST_FOREACH(ptree::value_type & value, ptree.get_child("examples.example")){
           cout<<value.second.get("<xmlattr>.name", "")<<endl;
           cout<<value.second.data()<<endl;

}


Solution

  • The ptree.equal_range method has the behavior you are looking for. Note, I've got several pieces of C++11 in there - you'll need a modern compiler.

    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/xml_parser.hpp>
    #include <sstream>
    
    const char xml[] = R"(<examples>
    <example>
    <test name="img">testme</test>
    <test name="img1">testme1</test>
    <test name="img1">testme2</test>
    </example>
    <example>
    <test name="text">testme</test>
    <test name="text">testme1</test>
    <test name="text">testme2</test>
    </example>
    </examples>)";
    
    
    int main(int argc, char **argv)
    {
    
        boost::property_tree::ptree ptree;
        std::istringstream xml_str(xml);
        read_xml(xml_str, ptree);
    
        auto example_range = ptree.get_child("examples").equal_range("example");
    
        for( auto it = example_range.first; it != example_range.second; ++it )
        {
            auto test_range = it->second.equal_range("test");
            for( auto test_it = test_range.first; test_it != test_range.second; ++test_it )
            {
                std::cout << test_it->second.get("<xmlattr>.name","") <<std::endl;
                std::cout << test_it->second.data() << std::endl;
            }
        }
    
        return 0;
    }