Marty Marty - 11 days ago 5
C++ Question

Boost C++ XML parsing

I am slightly familiar on how to parse XML with boost, if the XML has up to and including 3 levels. However, I am having trouble with the following example:

(Please ignore the slight lack of logic in the XML since this is an adaptation of something I cannot change. The structure is important)

<content>

<Room>
<RoomName>Livingroom</RoomName>
<Description>
<Color>Red</Color>
<Size>Small</Size>
</Description>
<Description>
<Color>Blue</Color>
<Size>Big</Size>
</Description>
</Room>

<Room>
<RoomName>Bathroom</RoomName>
<Description>
<Color>Green</Color>
<Size>Medium</Size>
</Description>
</Room>

</content>


I have tried this:

struct Room
{
std::string roomName;
std::string roomColor;
std::string roomSize;
};

void parseRoomsXml(){

boost::property_tree::ptree tree;
boost::property_tree::read_xml("./Rooms.xml", tree);
boost::property_tree::ptree formats = tree.get_child("content");

BOOST_FOREACH( boost::property_tree::ptree::value_type const& f, formats ) {
if( f.first == "Room" ) {
Room s;
s.roomName = f.second.get<std::string>("RoomName");
std::cout<<s.roomName<<std::endl;

const boost::property_tree::ptree & attributes = formats.get_child("Room");

BOOST_FOREACH( boost::property_tree::ptree::value_type const& v, attributes ) {
if (v.first == "Description"){
s.roomColor = v.second.get<std::string>("Color");
s.roomSize = v.second.get<std::string>("Size");
std::cout<< s.roomColor << " " <<s.roomSize;
}
}
}
}
}


The Result is that the first room is parsed correctly, but the second room has the Description of the first one:

=========================

Output:

Livingroom

Red Small

Blue Big

Bathroom

Red Small

Blue Big

========================

Expected result would be:

Livingroom

Red Small

Blue Big

Bathroom

Green Medium

===================================

Thanks in advance, any help would be appreciated, since I am trying to get used to boost.

Answer

The problem seems to be in this statement: const boost::property_tree::ptree & attributes = formats.get_child("Room");

You can iterate over the children using the following code:

BOOST_FOREACH(boost::property_tree::ptree::value_type &v,
    config.get_child("path.to.array_of_objects"))
{
    std::cout << "First data: " << v.first.data() << std::endl;
    boost::property_tree::ptree subtree = (boost::property_tree::ptree) v.second ;
    BOOST_FOREACH(boost::property_tree::ptree::value_type &vs,
        subtree)
    {
        std::cout << "Sub data: " << vs.first.data() << std::endl;
        color = vs.second.get<std::string>("Color");
        roomSize = vs.second.get<std::string>("Size");
    }
}
Comments