P-Gn
P-Gn

Reputation: 24661

Boost's property tree: deleting a child knowing its path

Is there an easy to delete a child (and its eventual subchildren) from a property tree that is known via its path?

The following

auto child = ptree.get_child(path);
child.clear();

does not actually remove the child, but only its content.

The erase member function takes an iterator or a key. I don't know of an easy way to find the iterator corresponding to a path, without having to iterate through the tree.

One could find the "root" children by by splitting the path at dot characters, and eraseing the remaining. However is there any easier/shorter way of getting there?

Upvotes: 5

Views: 3587

Answers (2)

Michał Jaroń
Michał Jaroń

Reputation: 624

Basing on Marste answer, below is the full implementation:


#include <string>
#include <boost/property_tree/ptree.hpp>

// Headers required by ptree_to_json helper function:
#include <sstream>
#include <boost/property_tree/json_parser.hpp>

// Headers required by main() example only:
#include <iostream>

std::size_t erase_by_path(boost::property_tree::ptree& root, const std::string& path)
{
    if (root.get_child_optional(path) == boost::none) // If given child doesn't exist.
    {
        return 0; // Return 0 children removed.
    }

    const std::string::size_type lastDot = path.find_last_of('.');
    if (lastDot == std::string::npos) // This is a direct child.
    {
        return root.erase(path);
    }
    else // This is a nested child.
    {
        const std::string parentPath = path.substr(0, lastDot);
        const std::string directKey = path.substr(lastDot + 1);
        return root.get_child(parentPath).erase(directKey);
    }
}

// Converts property tree to the JSon string.
std::string ptree_to_json(const boost::property_tree::ptree& root)
{
    std::stringstream ss;
    boost::property_tree::json_parser::write_json(ss, root);
    return ss.str();
}

// Sample usage.
int main()
{
    using ptree = boost::property_tree::ptree;

    // This is a top-level node.
    ptree root;

    // Initialze "b" and insert it to the root.
    {
        ptree b;
        b.put("x", "delete-me-please");
        b.put("y", "keep-me-please");
        root.put_child("b", b);
    }

    std::cout << "Before remove call: " << ptree_to_json(root) << std::endl;

    std::cout << "Removing b.x node." << std::endl;
    const std::size_t removedCount = erase_by_path(root, "b.x");
    std::cout << "After remove call: " << ptree_to_json(root) << std::endl;
    std::cout << "Removed count: " << removedCount << std::endl;

    return 0;
}

Sample output:

Before remove call: {
    "b": {
        "x": "delete-me-please",
        "y": "keep-me-please"
    }
}

Removing b.x node.
After remove call: {
    "b": {
        "y": "keep-me-please"
    }
}

Removed count: 1

Upvotes: 0

Marste
Marste

Reputation: 679

You could do this:ptree.get_child("path.to").erase("child"); Note that this deletes ALL nodes named "child" within the path "path.to" and their subchildren.

Upvotes: 6

Related Questions