J'e
J'e

Reputation: 3716

recursively get complete key path to all values in a boost property tree

I'm reading an XML file into a boost::property_tree and trying to get the complete key path for every value.

  1. Does boost have a built in way to do this
  2. Were is the error in my recursion?

example input - my_file.xml

<foo>
    <bar>abc</bar>
    <baz>
        <buz>def</buz>
    </baz>
</foo>

desired result

"foo.bar"
"foo.baz.buz"

actual result (wrong)

"foo.bar"
"foo.bar.baz.buz"

code that doesn't quite work

void walk_ptree(boost::property_tree::ptree tree, std::unordered_set<std::string>& key_set, std::string parent_key)
{
    if (tree.empty())
    {
        key_set.insert(parent_key);
        return;
    }
    for (auto& it : tree)
    {
        // add a separator between key segments
        if (!parent_key.empty())
        {
            parent_key += ".";
        }
        parent_key += it.first;
        walk_ptree(it.second, key_set, parent_key);
    }
}

boost::property_tree::ptree prop_tree;
boost::property_tree::read_xml("my_file.xml", prop_tree);
std::unordered_set<std::string> key_set{};
walk_ptree(prop_tree, key_set, "");

Upvotes: 1

Views: 1018

Answers (1)

Alan Birtles
Alan Birtles

Reputation: 36389

Every iteration of your for loop adds to the parentKey value so it will have all the children's names in it by the end of the loop. Use a separate variable to hold the key name for each node:

void walk_ptree(const boost::property_tree::ptree& tree, std::unordered_set<std::string>& key_set, const std::string& parent_key)
{
    if (tree.empty())
    {
        key_set.insert(parent_key);
        return;
    }
    for (auto& it : tree)
    {
        std::string key = parent_key;
        // add a separator between key segments
        if (!key.empty())
        {
            key += ".";
        }
        key+= it.first;
        walk_ptree(it.second, key_set, key);
    }
}

Upvotes: 3

Related Questions