Sort out xmlns stuff.
authorCarl Hetherington <cth@carlh.net>
Fri, 10 Oct 2014 20:38:50 +0000 (21:38 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 10 Oct 2014 20:38:50 +0000 (21:38 +0100)
src/cxml.cc
src/cxml.h
test/ref/c.xml [new file with mode: 0644]
test/tests.cc

index 3285fe6e195aa4a69cb5e6bb79ae7c25d4beb9b5..8bfb923e60115172d76d9902ca0c6dee0dcb8d24 100644 (file)
@@ -79,7 +79,11 @@ cxml::Node::write (xmlpp::Node* parent) const
                node->add_child_text (_content);
        }
 
-       for (list<pair<string, string> >::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<pair<string, string> >::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<string>
 cxml::Node::optional_string_attribute (string name) const
 {
-       list<pair<string, string> >::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<pair<string, string> >::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);
index 1c98bbf237e18d119db87f48e2ac18397abaa790..993a662eed99bc88ce9121e3211e7b5a152e80b8 100644 (file)
@@ -69,6 +69,7 @@ class Node;
 typedef boost::shared_ptr<cxml::Node> NodePtr;
 typedef std::list<NodePtr> NodeList;   
 typedef boost::shared_ptr<const cxml::Node> ConstNodePtr;
+typedef std::list<std::pair<std::string, std::string> > 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<std::pair<std::string, std::string> > _attributes;
+       KeyValueList _attributes;
+       KeyValueList _namespace_declarations;
        mutable std::list<std::string> _taken;
 };
 
diff --git a/test/ref/c.xml b/test/ref/c.xml
new file mode 100644 (file)
index 0000000..2b8667e
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<A xmlns="http://my.namespace" xmlns:foo="http://my.other.namespace">
+  <B/>
+</A>
index 8b3249888eedc8a7d1bee215bfd70dfdbb632e4b..f0ca967bdf80e3438833209dc24713352dd6e23f 100644 (file)
@@ -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);
+}