Search code examples
c++boostboost-propertytree

boost property tree: How to delete the specified parameters of the node


<root>
    <stu id="1">
        <name>a</name>
    </stu>
    <stu id="2">
        <name>b</name>
    </stu>
    <stu id="3">
        <name>c</name>
    </stu>
</root>

I want to delete the id = 2 node. I use

boost::property_tree::ptree pt;
pt.erase(Node);

But this will remove all the Node


Solution

  • Assuming you didn't have problems deleting the attribute, here's fighting to the solution using Boost Property Tree:

    Live On Coliru

    #include <iostream>
    #include <boost/property_tree/xml_parser.hpp>
    
    using boost::property_tree::ptree;
    static auto const pretty = boost::property_tree::xml_writer_make_settings<std::string>(' ', 4);
    
    template <typename Tree>
    auto find_children(Tree& pt, std::string const& key) {
        std::vector<typename Tree::iterator> matches;
    
        for (auto it = pt.begin(); it != pt.end(); ++it)
            if (it->first == key)
                matches.push_back(it);
    
        return matches;
    }
    
    int main() {
        ptree pt;
        {
            std::istringstream iss(R"(<root><stu id="1"><name>a</name></stu><stu id="2"><name>b</name></stu><stu id="3"><name>c</name></stu></root>)");
            read_xml(iss, pt);
        }
    
        auto& root = pt.get_child("root");
    
        for (auto stu : find_children(root, "stu")) {
            if (2 == stu->second.get("<xmlattr>.id", -1)) {
                std::cout << "Debug: erasing studen " << stu->second.get("name", "N.N.") << "\n";
                root.erase(stu);
            }
        }
    
        write_xml(std::cout, pt, pretty);
    }
    

    Printing:

    Debug: erasing student b
    <?xml version="1.0" encoding="utf-8"?>
    <root>
        <stu id="1">
            <name>a</name>
        </stu>
        <stu id="3">
            <name>c</name>
        </stu>
    </root>
    

    Using An XML Library

    Of course, using an XML library is much easier:

    #include <iostream>
    #include <pugixml.hpp>
    
    int main() {
        pugi::xml_document doc;
        doc.load_string(R"(<root><stu id="1"><name>a</name></stu><stu id="2"><name>b</name></stu><stu id="3"><name>c</name></stu></root>)");
    
        for (auto& n : doc.select_nodes("//root/stu[@id=2]")) {
            auto node = n.node();
            node.parent().remove_child(node);
        }
    
        pugi::xml_writer_stream w(std::cout);
        doc.save(w);
    }