From 5800b1958cfb055fe1fb30461cbf73fb50e59e12 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 10 Oct 2014 21:38:50 +0100 Subject: [PATCH] Sort out xmlns stuff. --- src/cxml.cc | 33 +++++++++++++++++++++++++++++---- src/cxml.h | 16 ++++++++++++++-- test/ref/c.xml | 4 ++++ test/tests.cc | 13 +++++++++++++ 4 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 test/ref/c.xml diff --git a/src/cxml.cc b/src/cxml.cc index 3285fe6..8bfb923 100644 --- a/src/cxml.cc +++ b/src/cxml.cc @@ -79,7 +79,11 @@ cxml::Node::write (xmlpp::Node* parent) const node->add_child_text (_content); } - for (list >::const_iterator i = _attributes.begin(); i != _attributes.end(); ++i) { + for (KeyValueList::const_iterator i = _namespace_declarations.begin(); i != _namespace_declarations.end(); ++i) { + node->set_namespace_declaration (i->first, i->second); + } + + for (KeyValueList::const_iterator i = _attributes.begin(); i != _attributes.end(); ++i) { node->set_attribute (i->first, i->second); } @@ -183,7 +187,7 @@ cxml::Node::ignore_child (string name) const string cxml::Node::string_attribute (string name) const { - list >::const_iterator i = _attributes.begin (); + KeyValueList::const_iterator i = _attributes.begin (); while (i != _attributes.end() && i->first != name) { ++i; } @@ -198,7 +202,7 @@ cxml::Node::string_attribute (string name) const optional cxml::Node::optional_string_attribute (string name) const { - list >::const_iterator i; + KeyValueList::const_iterator i; while (i != _attributes.end() && i->first != name) { ++i; } @@ -253,7 +257,7 @@ cxml::Node::namespace_prefix () const void cxml::Node::set_attribute (string name, string value) { - list >::iterator i = _attributes.begin (); + KeyValueList::iterator i = _attributes.begin (); while (i != _attributes.end() && i->first != name) { ++i; } @@ -265,6 +269,21 @@ cxml::Node::set_attribute (string name, string value) _attributes.push_back (make_pair (name, value)); } +void +cxml::Node::set_namespace_declaration (string uri, string ns) +{ + KeyValueList::iterator i = _namespace_declarations.begin (); + while (i != _namespace_declarations.end() && i->second != ns) { + ++i; + } + + if (i != _namespace_declarations.end ()) { + _namespace_declarations.erase (i); + } + + _namespace_declarations.push_back (make_pair (uri, ns)); +} + cxml::NodePtr cxml::read_file (boost::filesystem::path file) { @@ -304,6 +323,12 @@ static void write_to_xmlpp_document (cxml::ConstNodePtr node, xmlpp::Document& doc) { xmlpp::Element* root = doc.create_root_node (node->name ()); + + cxml::KeyValueList namespace_declarations = node->namespace_declarations (); + for (cxml::KeyValueList::const_iterator i = namespace_declarations.begin(); i != namespace_declarations.end(); ++i) { + root->set_namespace_declaration (i->first, i->second); + } + cxml::NodeList children = node->children (); for (cxml::NodeList::const_iterator i = children.begin(); i != children.end(); ++i) { (*i)->write (root); diff --git a/src/cxml.h b/src/cxml.h index 1c98bbf..993a662 100644 --- a/src/cxml.h +++ b/src/cxml.h @@ -69,6 +69,7 @@ class Node; typedef boost::shared_ptr NodePtr; typedef std::list NodeList; typedef boost::shared_ptr ConstNodePtr; +typedef std::list > KeyValueList; class Node { @@ -185,6 +186,7 @@ public: NodeList children () const; NodeList children (std::string) const; + /** Add a child node with a given name */ NodePtr add_child (std::string name, std::string namespace_prefix = "") { @@ -194,17 +196,26 @@ public: _children.push_back (n); return n; } - + + void set_namespace_declaration (std::string uri, std::string prefix = ""); + + KeyValueList namespace_declarations () const { + return _namespace_declarations; + } + void set_content (std::string c) { _content = c; } /** @return The content of this node */ std::string content () const; + void set_attribute (std::string name, std::string value); + void set_namespace_prefix (std::string p) { _namespace_prefix = p; } + /** @return namespace prefix of this node */ std::string namespace_prefix () const; /** This will mark a child as to be ignored when calling done() */ @@ -237,7 +248,8 @@ private: std::string _name; std::string _content; std::string _namespace_prefix; - std::list > _attributes; + KeyValueList _attributes; + KeyValueList _namespace_declarations; mutable std::list _taken; }; diff --git a/test/ref/c.xml b/test/ref/c.xml new file mode 100644 index 0000000..2b8667e --- /dev/null +++ b/test/ref/c.xml @@ -0,0 +1,4 @@ + + + + diff --git a/test/tests.cc b/test/tests.cc index 8b32498..f0ca967 100644 --- a/test/tests.cc +++ b/test/tests.cc @@ -110,3 +110,16 @@ BOOST_AUTO_TEST_CASE (write_test) int r = system ("diff -u test/ref/b.xml build/test/b.xml"); BOOST_CHECK_EQUAL (WEXITSTATUS (r), 0); } + +BOOST_AUTO_TEST_CASE (write2_test) +{ + cxml::NodePtr document (new cxml::Node); + document->set_name ("A"); + document->add_child ("B"); + document->set_namespace_declaration ("http://my.namespace"); + document->set_namespace_declaration ("http://my.other.namespace", "foo"); + write_to_file_formatted (document, "build/test/c.xml"); + + int r = system ("diff -u test/ref/c.xml build/test/c.xml"); + BOOST_CHECK_EQUAL (WEXITSTATUS (r), 0); +} -- 2.30.2