Reputation: 24661
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 erase
ing the remaining. However is there any easier/shorter way of getting there?
Upvotes: 5
Views: 3587
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
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