Question

I have just discovered boost::property_tree, which seems the perfect answer to my problem. I wrote a small test program to extract specific data from an xml file. I have used the example provided in the documentation as a guide. The xml file: test.xml:

<section>
    <GROUP>
        <g_name>ABC</g_name>
        <fields>
            <row>
                <name>A</name>
                <datatype>string</datatype>
                <field_size>6</field_size>
                <value>ABC</value>
            </row>
            <row>
                <name>B</name>
                <datatype>integer</datatype>
                <field_size>5</field_size>
                <value>00107</value>
            </row>
            <row>
                <name>C</name>
                <datatype>string</datatype>
                <field_size>20</field_size>
                <value>LOTS OF LETTERS     </value>
            </row>
        </fields>
    </GROUP>
    <GROUP>
        <g_name>CDE</g_name>
        <fields>
            <row>
                <name>A</name>
                <datatype>string</datatype>
                <field_size>6</field_size>
                <value>CDE</value>
            </row>
            <row>
                <name>B</name>
                <datatype>integer</datatype>
                <field_size>5</field_size>
                <value>00100</value>
            </row>
            <row>
                <name>F</name>
                <datatype>integer</datatype>
                <field_size>4</field_size>
                <value>1970</value>
            </row>
        </fields>
    </GROUP>
</section>

The code:

        using boost::property_tree::ptree;
        struct t_collection
        {
            ptree pt;
            void load(const std::string &filename);
            void print();
        };
        void t_collection::load(const std::string &filename)
        {
            read_xml(filename, pt);
        }
        void t_collection::print()
        {
                BOOST_FOREACH(ptree::value_type &v, pt.get_child("section.GROUP"))
BOOST_FOREACH(ptree::value_type &v, pt.get_child("section.GROUP"))
{
    printf("X: %s->", v.second.data().c_str());
    //prints X: ABC ->
    BOOST_FOREACH(ptree::value_type &w, pt.get_child("section.GROUP.fields.row"))
        printf("%s\n", w.second.data().c_str());
    //prints A, string, 6, ABC - that is good for first iteration but there should be 3 iterations here
}
//then prints X: and just "" and repeats the set from the first one 
        }
        int main()
        {
            try
            {
                t_collection t1;
                t1.load("test.xml");
                t1.print();
            }
            catch (std::exception &e)
            {
                std::cout << "Error: " << e.what() << "\n";
            }
            return 0;
        } 

Note: I am trying to extract the values (ABC and the inner values, like A - string - 6 - ABC, for each GROUP - and each set of "row", which I will process and then output in a different format). Please see comment in code for something I tried.
So far the best result was with: (contents inside print():

BOOST_FOREACH(ptree::value_type &z, pt.get_child("section"))
    //BOOST_FOREACH(ptree::value_type &v, pt.get_child("section.GROUP"))
        {
            printf("X: %s->", pt.get<std::string>("section.GROUP.g_mame", "default").c_str());
            //prints X: ABC ->
            BOOST_FOREACH(ptree::value_type &w, pt.get_child("section.GROUP.fields.row"))
            {
                printf("%s\n", pt.get<std::string>("section.GROUP.fields.row.name", "name").c_str());
                printf("%s\n", pt.get<std::string>("section.GROUP.fields.row.datatype", "type").c_str());
                printf("%s\n", pt.get<std::string>("section.GROUP.fields.row.field_size", "size").c_str());
                printf("%s\n", pt.get<std::string>("section.GROUP.fields.row.value", "value").c_str());
            }
        }
        //prints x: default->A, string, 6, ABC (3 times) then repeat identically

I can't get the data from more than one record ! Please help, give me a suggestion - what am I doing wrong ?
Thank you.

Was it helpful?

Solution

You are missing a level in your iteration. You need to iterate over the elements that have multiple children with the same name.

std::pair<ptree::const_assoc_iterator, ptree::const_assoc_iterator>
    r(pt.get_child("section").equal_range("GROUP"));

for (ptree::const_assoc_iterator i(r.first); i != r.second; ++i) {
    // Do something with each group.
}

Repeat as appropriate as you descend the tree.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top