From d1b566fc26389993702b573f0df50b7b2618b127 Mon Sep 17 00:00:00 2001 From: Tuan Anh Tran Date: Tue, 17 Sep 2019 09:46:59 +0700 Subject: [PATCH] feat: add remove_attributes() and remove_children() --- src/pugixml.cpp | 33 +++++++++++++++++++++++++++++++++ src/pugixml.hpp | 6 ++++++ tests/test_dom_modify.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 90c48b2..01e8c84 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -6059,6 +6059,23 @@ namespace pugi return true; } + PUGI__FN bool xml_node::remove_attributes() + { + for(pugi::xml_attribute a: this->attributes()) + { + if (!_root || !a._attr) return false; + if (!impl::is_attribute_of(a._attr, _root)) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + impl::destroy_attribute(a._attr, alloc); + } + this->_root->first_attribute = nullptr; + + return true; + } + PUGI__FN bool xml_node::remove_child(const char_t* name_) { return remove_child(child(name_)); @@ -6077,6 +6094,22 @@ namespace pugi return true; } + PUGI__FN bool xml_node::remove_children() + { + for (pugi::xml_node child: this->children()) + { + if (!_root || !child._root || child._root->parent != _root) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + impl::destroy_node(child._root, alloc); + } + this->_root->first_child = nullptr; + + return true; + } + PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) { // append_buffer is only valid for elements/documents diff --git a/src/pugixml.hpp b/src/pugixml.hpp index da8ff36..8986d2a 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -576,10 +576,16 @@ namespace pugi bool remove_attribute(const xml_attribute& a); bool remove_attribute(const char_t* name); + // Remove all attributes + bool remove_attributes(); + // Remove specified child bool remove_child(const xml_node& n); bool remove_child(const char_t* name); + // Remove all children + bool remove_children(); + // Parses buffer as an XML document fragment and appends all nodes as children of the current node. // Copies/converts the buffer, so it may be deleted or changed after the function returns. // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index 9696827..e0558d9 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -492,6 +492,18 @@ TEST_XML(dom_node_remove_attribute, "") +{ + xml_node node = doc.child(STR("node")); + xml_node child = node.child(STR("child")); + + CHECK(child.remove_attributes()); + CHECK_NODE(child, STR("")); + + CHECK(node.remove_attributes()); + CHECK_NODE(node, STR("")); +} + TEST_XML(dom_node_prepend_child, "foo") { CHECK(xml_node().prepend_child() == xml_node()); @@ -707,6 +719,18 @@ TEST_XML(dom_node_remove_child, "")); } +TEST_XML(dom_node_remove_children, "") +{ + xml_node node = doc.child(STR("node")); + xml_node child = node.child(STR("child")); + + CHECK(child.remove_children()); + CHECK_NODE(child, STR("")); + + CHECK(node.remove_children()); + CHECK_NODE(node, STR("")); +} + TEST_XML(dom_node_remove_child_complex, "") { CHECK(doc.child(STR("node")).remove_child(STR("n1")));