1

I want to remove a node from a ptree which is based on xml:

<library>
    <booklist>
        <book id="10">
            <data title="t1"/>
        </book>
        <book id="10">
            <data title="t2"/>
        </book>
        <book id="10">
            <data title="t3"/>
        </book>
        <book id="20">
            <data title="t4"/>
        </book>
    </booklist>
</library>

I have an algorithm to find the right node which returns a pointer to the removing node. Also I have a pointer to the parent of the removing node. but the erase() will take an iterator (not a pointer). My question is how to remove the node using two pointers; a poiter to the removing node and another to the parent node.

void removeElement(const std::string addr, const std::string criteria, boost::property_tree::ptree &ptSource)
{
    boost::property_tree::ptree *ptParent = findParentPTree(addr, criteria, ptSource);   // Points to "library.booklist"
    boost::property_tree::ptree *ptRemove = findRemovePTree(addr, criteria, ptSource);   // eg the third <book> which contains the <data title="t3"/>

    // question: how to remove node ptRemove from ptSource?
}

Note that there are some examples using iterators, but it is not clear how should the iterator of removing node be found.

M.Kh.
  • 67
  • 1
  • 7
  • Out-Of-The-Box: consider not writing to the abstract `ptree` interface, but instead write some domain-specific wrappers, like this very similar example: https://stackoverflow.com/questions/45198739/iterate-through-multilevel-boost-tree/45201583#45201583 – sehe Oct 26 '17 at 13:33
  • For maximum relevance, here's that sample trivially translated to XML instead JSON http://coliru.stacked-crooked.com/a/af72134e9c1a18ab – sehe Oct 26 '17 at 13:44

1 Answers1

1

Indeed, there is no direct function to get an iterator from a value reference. So you'll have to write it yourself:

In this case it would appear you don't need it to be recursive so it's simpler:

Live On Coliru

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

using namespace boost::property_tree;

ptree::iterator child_iterator(ptree& within, ptree const& child) {
    for (auto it = within.begin(); it != within.end(); ++it)
        if (std::addressof(it->second) == std::addressof(child))
            return it;

    return within.end();
}

ptree* findParentPTree(std::string const, std::string const&, ptree const&);
ptree* findRemovePTree(std::string const, std::string const&, ptree const&);

void removeElement(const std::string& addr, const std::string& criteria, ptree &ptSource)
{
    ptree *ptParent = findParentPTree(addr, criteria, ptSource); // Points to "library.booklist"
    ptree *ptRemove = findRemovePTree(addr, criteria, ptSource); // eg the third <book> which contains the <data title="t3"/>

    auto it = child_iterator(*ptParent, *ptRemove);
    if (it != ptParent->end())
        ptParent->erase(it);
}
sehe
  • 374,641
  • 47
  • 450
  • 633