[libxml++] Add Node::add_child_with_new_ns()



commit 47b2b269cae471f2480efebbe890588cc6a65506
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Fri Oct 10 16:59:52 2014 +0200

    Add Node::add_child_with_new_ns()
    
    * libxml++/nodes/node.[h|cc]: Add add_child_with_new_ns() (*2) and
    add_child_before_with_new_ns(). Bug #737682.

 libxml++/nodes/node.cc |  102 +++++++++++++++++++++++++++++++++++++-----------
 libxml++/nodes/node.h  |   66 +++++++++++++++++++++++++++++-
 2 files changed, 142 insertions(+), 26 deletions(-)
---
diff --git a/libxml++/nodes/node.cc b/libxml++/nodes/node.cc
index c35bd16..5664f3b 100644
--- a/libxml++/nodes/node.cc
+++ b/libxml++/nodes/node.cc
@@ -111,6 +111,18 @@ Glib::ustring eval_common_to_string(const Glib::ustring& xpath,
   return Glib::ustring();
 }
 
+// Common part of all add_child*() methods.
+xmlpp::Element* add_child_common(const Glib::ustring& name, xmlNode* child, xmlNode* node)
+{
+  if (!node)
+  {
+    xmlFreeNode(child);
+    throw xmlpp::internal_error("Could not add child element node " + name);
+  }
+  xmlpp::Node::create_wrapper(node);
+  return static_cast<xmlpp::Element*>(node->_private);
+}
+
 } // anonymous namespace
 
 namespace xmlpp
@@ -229,49 +241,63 @@ Element* Node::add_child(const Glib::ustring& name,
 {
   _xmlNode* child = create_new_child_node(name, ns_prefix);
   _xmlNode* node = xmlAddChild(impl_, child);
-  if (!node)
-  {
-    xmlFreeNode(child);
-    throw internal_error("Could not add child element node " + name);
-  }
-  Node::create_wrapper(node);
-  return static_cast<Element*>(node->_private);
+  return add_child_common(name, child, node);
 }
 
 Element* Node::add_child(xmlpp::Node* previous_sibling, 
                          const Glib::ustring& name,
                          const Glib::ustring& ns_prefix)
 {
-  if(!previous_sibling)
+  if (!previous_sibling)
     return 0;
 
   _xmlNode* child = create_new_child_node(name, ns_prefix);
   _xmlNode* node = xmlAddNextSibling(previous_sibling->cobj(), child);
-  if (!node)
-  {
-    xmlFreeNode(child);
-    throw internal_error("Could not add child element node " + name);
-  }
-  Node::create_wrapper(node);
-  return static_cast<Element*>(node->_private);
+  return add_child_common(name, child, node);
 }
 
 Element* Node::add_child_before(xmlpp::Node* next_sibling, 
                          const Glib::ustring& name,
                          const Glib::ustring& ns_prefix)
 {
-  if(!next_sibling)
+  if (!next_sibling)
     return 0;
 
   _xmlNode* child = create_new_child_node(name, ns_prefix);
   _xmlNode* node = xmlAddPrevSibling(next_sibling->cobj(), child);
-  if (!node)
-  {
-    xmlFreeNode(child);
-    throw internal_error("Could not add child element node " + name);
-  }
-  Node::create_wrapper(node);
-  return static_cast<Element*>(node->_private);
+  return add_child_common(name, child, node);
+}
+
+Element* Node::add_child_with_new_ns(const Glib::ustring& name,
+  const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix)
+{
+  _xmlNode* child = create_new_child_node_with_new_ns(name, ns_uri, ns_prefix);
+  _xmlNode* node = xmlAddChild(impl_, child);
+  return add_child_common(name, child, node);
+}
+
+Element* Node::add_child_with_new_ns(xmlpp::Node* previous_sibling,
+  const Glib::ustring& name,
+  const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix)
+{
+  if (!previous_sibling)
+    return 0;
+
+  _xmlNode* child = create_new_child_node_with_new_ns(name, ns_uri, ns_prefix);
+  _xmlNode* node = xmlAddNextSibling(previous_sibling->cobj(), child);
+  return add_child_common(name, child, node);
+}
+
+Element* Node::add_child_before_with_new_ns(xmlpp::Node* next_sibling,
+  const Glib::ustring& name,
+  const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix)
+{
+  if (!next_sibling)
+    return 0;
+
+  _xmlNode* child = create_new_child_node_with_new_ns(name, ns_uri, ns_prefix);
+  _xmlNode* node = xmlAddPrevSibling(next_sibling->cobj(), child);
+  return add_child_common(name, child, node);
 }
 
 _xmlNode* Node::create_new_child_node(const Glib::ustring& name, const Glib::ustring& ns_prefix)
@@ -301,6 +327,36 @@ _xmlNode* Node::create_new_child_node(const Glib::ustring& name, const Glib::ust
    return xmlNewNode(ns, (const xmlChar*)name.c_str());
 }
 
+_xmlNode* Node::create_new_child_node_with_new_ns(const Glib::ustring& name,
+  const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix)
+{
+  if (impl_->type != XML_ELEMENT_NODE)
+    throw internal_error("You can only add child nodes to element nodes.");
+
+  xmlNode* child = xmlNewNode(0, (const xmlChar*)name.c_str());
+  if (!child)
+    throw internal_error("Could not create new element node.");
+
+  xmlNs* ns = xmlNewNs(child, (const xmlChar*)(ns_uri.empty() ? 0 : ns_uri.c_str()),
+                       (const xmlChar*)(ns_prefix.empty() ? 0 : ns_prefix.c_str()) );
+  // xmlNewNs() does not create a namespace node for the predefined xml prefix.
+  // It's usually defined in the document and not in any specific node.
+  if (!ns && ns_prefix == "xml")
+  {
+    ns = xmlSearchNs(impl_->doc, impl_, (const xmlChar*)ns_prefix.c_str());
+    if (ns && (ns_uri != (ns->href ? (const char*)ns->href : "")))
+      ns = 0;
+  }
+  if (!ns)
+  {
+    xmlFreeNode(child);
+    throw internal_error("Could not create new namespace node.");
+  }
+
+  xmlSetNs(child, ns);
+
+  return child;
+}
 
 void Node::remove_child(Node* node)
 {
diff --git a/libxml++/nodes/node.h b/libxml++/nodes/node.h
index 6a02ecf..92a5fbe 100644
--- a/libxml++/nodes/node.h
+++ b/libxml++/nodes/node.h
@@ -158,7 +158,8 @@ public:
    * @param ns_prefix The namespace prefix. If the prefix has not been declared then this method will throw 
an exception.
    * @returns The newly-created element
    * @throws xmlpp::exception If a namespace prefix is specified, but has not been declared.
-   * @throws xmlpp::internal_error If this node is not an element node.
+   * @throws xmlpp::internal_error If this node is not an element node,
+   *         or the child node cannot be created.
    */
   Element* add_child(const Glib::ustring& name,
                      const Glib::ustring& ns_prefix = Glib::ustring());
@@ -173,7 +174,8 @@ public:
    * @param ns_prefix The namespace prefix. If the prefix has not been declared then this method will throw 
an exception.
    * @returns The newly-created element
    * @throws xmlpp::exception If a namespace prefix is specified, but has not been declared.
-   * @throws xmlpp::internal_error If this node is not an element node.
+   * @throws xmlpp::internal_error If this node is not an element node,
+   *         or the child node cannot be created.
    */
   Element* add_child(xmlpp::Node* previous_sibling, const Glib::ustring& name,
                      const Glib::ustring& ns_prefix = Glib::ustring());
@@ -188,11 +190,65 @@ public:
    * @param ns_prefix The namespace prefix. If the prefix has not been declared then this method will throw 
an exception.
    * @returns The newly-created element
    * @throws xmlpp::exception If a namespace prefix is specified, but has not been declared.
-   * @throws xmlpp::internal_error If this node is not an element node.
+   * @throws xmlpp::internal_error If this node is not an element node,
+   *         or the child node cannot be created.
    */
   Element* add_child_before(xmlpp::Node* next_sibling, const Glib::ustring& name,
                      const Glib::ustring& ns_prefix = Glib::ustring());
 
+  /** Add a child element to this node.
+   * This node must be an element node.
+   *
+   * @newin{2,38}
+   *
+   * @param name The new node name.
+   * @param ns_uri The namespace to associate with the prefix,
+   *               or to use as the default namespace if no prefix is specified.
+   * @param ns_prefix The prefix of the node's namespace. If no prefix is specified
+   *                  then the namespace URI will be the default namespace.
+   * @returns The newly-created element.
+   * @throws xmlpp::internal_error If this node is not an element node,
+   *         or the child node or the namespace node cannot be created.
+   */
+  Element* add_child_with_new_ns(const Glib::ustring& name,
+    const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix = Glib::ustring());
+
+  /** Add a child element to this node after the specified existing child node.
+   * This node must be an element node.
+   *
+   * @newin{2,38}
+   *
+   * @param previous_sibling An existing child node.
+   * @param name The new node name.
+   * @param ns_uri The namespace to associate with the prefix,
+   *               or to use as the default namespace if no prefix is specified.
+   * @param ns_prefix The prefix of the node's namespace. If no prefix is specified
+   *                  then the namespace URI will be the default namespace.
+   * @returns The newly-created element.
+   * @throws xmlpp::internal_error If this node is not an element node,
+   *         or the child node or the namespace node cannot be created.
+   */
+  Element* add_child_with_new_ns(xmlpp::Node* previous_sibling, const Glib::ustring& name,
+    const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix = Glib::ustring());
+
+  /** Add a child element to this node before the specified existing child node.
+   * This node must be an element node.
+   *
+   * @newin{2,38}
+   *
+   * @param next_sibling An existing child node.
+   * @param name The new node name.
+   * @param ns_uri The namespace to associate with the prefix,
+   *               or to use as the default namespace if no prefix is specified.
+   * @param ns_prefix The prefix of the node's namespace. If no prefix is specified
+   *                  then the namespace URI will be the default namespace.
+   * @returns The newly-created element.
+   * @throws xmlpp::internal_error If this node is not an element node,
+   *         or the child node or the namespace node cannot be created.
+   */
+  Element* add_child_before_with_new_ns(xmlpp::Node* next_sibling, const Glib::ustring& name,
+    const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix = Glib::ustring());
+
   /** Remove the child node.
    * @param node The child node to remove. This Node will be deleted and therefore unusable after calling 
this method.
    */
@@ -352,6 +408,10 @@ protected:
   ///Create the C instance ready to be added to the parent node.
   _xmlNode* create_new_child_node(const Glib::ustring& name, const Glib::ustring& ns_prefix);
 
+  ///Create the C instance ready to be added to the parent node.
+  _xmlNode* create_new_child_node_with_new_ns(const Glib::ustring& name,
+    const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix);
+
 private:
   _xmlNode* impl_;
 };


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]