[libxml++] [patch] Namespace class and custom_dom example



Moderators, please discard the previous message sent using the wrong
>From address.
----
Hi guys,

I implemented XML Namespaces support against the current CVS. I also
made an example custom_dom that demonstrates deriving classes from
Element and using a SAX parser to build a tree of these derived objects
to make it easy to serialize and deserialize a custom DOM. This example
also tests the Namespace.

There are overloaded methods that can take a Namespace object as a
parameter, but I have not tested these. The example, just uses the
methods with prefix or prefix/uri parameters. I imagine the methods that
take a Namespace object might be useful with DOM manipulations. For now,
I wanted to get some implementation feedback for a merge to ease ongoing
development.

I am using this as the basis for a rewrite of the Kino video editor that
uses the W3C SMIL2 for its project file format. We need namespaces
support because we will have Kino specific features in it and only
implement selective SMIL modules while doing other modules a different
way. I will also look at Bakery soon to get ideas about how it
approaches the Document_XML.

+-DRD-+


diff -uprN /home/dan/libxml++/configure.in libxml++/configure.in
--- /home/dan/libxml++/configure.in	2003-07-16 16:32:52.000000000 -0400
+++ libxml++/configure.in	2003-08-08 00:16:06.000000000 -0400
@@ -55,6 +55,7 @@ AC_OUTPUT(
     docs/reference/Makefile
 
   examples/Makefile
+    examples/custom_dom/Makefile
     examples/dom_build/Makefile
     examples/dom_parser/Makefile
     examples/dom_read_write/Makefile
diff -uprN /home/dan/libxml++/examples/Makefile.am libxml++/examples/Makefile.am
--- /home/dan/libxml++/examples/Makefile.am	2003-07-12 08:41:59.000000000 -0400
+++ libxml++/examples/Makefile.am	2003-08-08 00:14:55.000000000 -0400
@@ -1,3 +1,4 @@
-SUBDIRS = dom_build dom_parser dom_read_write dom_xpath sax_parser sax_exception import_node
+SUBDIRS = dom_build dom_parser dom_read_write dom_xpath sax_parser sax_exception \
+          import_node custom_dom
 
 EXTRA_DIST = README Makefile.am_fragment
diff -uprN /home/dan/libxml++/examples/custom_dom/Makefile.am libxml++/examples/custom_dom/Makefile.am
--- /home/dan/libxml++/examples/custom_dom/Makefile.am	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/examples/custom_dom/Makefile.am	2002-11-15 08:33:08.000000000 -0500
@@ -0,0 +1,9 @@
+include $(top_srcdir)/examples/Makefile.am_fragment
+
+#Build the executable, but don't install it.
+noinst_PROGRAMS = example
+
+#List of source files needed to build the executable:
+example_SOURCES = main.cc myparser.h myparser.cc
+
+EXTRA_DIST = example.xml
diff -uprN /home/dan/libxml++/examples/custom_dom/README libxml++/examples/custom_dom/README
--- /home/dan/libxml++/examples/custom_dom/README	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/examples/custom_dom/README	2003-08-07 23:44:16.000000000 -0400
@@ -0,0 +1,2 @@
+This example tests XML Namespaces support. It also demonstrates how to use
+a SAX parser to build a custom DOM inherited from libxml++ nodes.
diff -uprN /home/dan/libxml++/examples/custom_dom/example.xml libxml++/examples/custom_dom/example.xml
--- /home/dan/libxml++/examples/custom_dom/example.xml	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/examples/custom_dom/example.xml	2003-08-08 00:18:30.000000000 -0400
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<gjob:Helping xmlns:gjob="http://www.gnome.org/some-location";>
+  <gjob:Jobs>
+
+    <gjob:Job>
+      <gjob:Project ID="3"/>
+      <gjob:Application>GBackup</gjob:Application>
+      <gjob:Category>Development</gjob:Category>
+
+      <gjob:Update xmlns:foo="http://foo";>
+	<gjob:Status>Open</gjob:Status>
+	<gjob:Modified>Mon, 07 Jun 1999 20:27:45 -0400 MET DST</gjob:Modified>
+        <gjob:Salary foo:bar="no">USD 0.00</gjob:Salary>
+      </gjob:Update>
+
+      <gjob:Developers>
+        <gjob:Developer>
+        </gjob:Developer>
+      </gjob:Developers>
+
+      <gjob:Contact>
+        <gjob:Person>Nathan Clemons</gjob:Person>
+	<gjob:Email>nathan windsofstorm net</gjob:Email>
+        <gjob:Company>
+	</gjob:Company>
+        <gjob:Organisation>
+	</gjob:Organisation>
+        <gjob:Webpage>
+	</gjob:Webpage>
+	<gjob:Snailmail>
+	</gjob:Snailmail>
+	<gjob:Phone>
+	</gjob:Phone>
+      </gjob:Contact>
+
+      <gjob:Requirements>
+      The program should be released as free software, under the GPL.
+      </gjob:Requirements>
+
+      <gjob:Skills>
+      </gjob:Skills>
+
+      <gjob:Details>
+      A GNOME based system that will allow a superuser to configure
+      compressed and uncompressed files and/or file systems to be backed
+      up with a supported media in the system.  This should be able to
+      perform via find commands generating a list of files that are passed
+      to tar, dd, cpio, cp, gzip, etc., to be directed to the tape machine
+      or via operations performed on the filesystem itself. Email
+      notification and GUI status display very important.
+      </gjob:Details>
+
+    </gjob:Job>
+
+  </gjob:Jobs>
+</gjob:Helping>
+
diff -uprN /home/dan/libxml++/examples/custom_dom/main.cc libxml++/examples/custom_dom/main.cc
--- /home/dan/libxml++/examples/custom_dom/main.cc	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/examples/custom_dom/main.cc	2003-07-16 02:43:09.000000000 -0400
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+/* main.cc
+ *
+ * By Dan Dennedy <dan dennedy org> 
+ *
+ * Copyright (C) 2003 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fstream>
+#include <iostream>
+
+#include "myparser.h"
+
+int
+main(int argc, char* argv[])
+{
+  std::string filepath;
+  if(argc > 1 )
+    filepath = argv[1]; //Allow the user to specify a different XML file to parse.
+  else
+    filepath = "example.xml";
+    
+  // Parse the entire document in one go:
+  try
+  {
+    MyDocument doc;
+    MyParser parser(doc);
+    parser.parse_file(filepath);
+    std::cout << doc.write_to_string_formatted() << std::endl;
+    MyObject* obj = parser.getRoot();
+    std::cout << "MyObject's name is \"" << obj->get_name() << "\" (level " << obj->getLevel() << ")" << std::endl;
+  }
+  catch(const xmlpp::exception& ex)
+  {
+    std::cout << "libxml++ exception: " << ex.what() << std::endl;
+  }
+  
+  return 0;
+}
+
diff -uprN /home/dan/libxml++/examples/custom_dom/myparser.cc libxml++/examples/custom_dom/myparser.cc
--- /home/dan/libxml++/examples/custom_dom/myparser.cc	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/examples/custom_dom/myparser.cc	2003-07-29 07:28:35.000000000 -0400
@@ -0,0 +1,126 @@
+// -*- C++ -*-
+
+/* myparser.cc
+ *
+ * By Dan Dennedy <dan dennedy org> 
+ *
+ * Copyright (C) 2003 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "myparser.h"
+
+#include <iostream>
+using std::cout;
+using std::endl;
+#include <string>
+using std::string;
+
+MyParser::MyParser(xmlpp::Document& document)
+  : _doc(document), _root(NULL)
+{
+}
+
+MyParser::~MyParser()
+{
+}
+
+void MyParser::on_start_document()
+{
+  //std::cout << "on_start_document()" << std::endl;
+}
+
+void MyParser::on_end_document()
+{
+  //std::cout << "on_end_document()" << std::endl;
+}
+
+void MyParser::on_start_element(const std::string& name,
+                                   const AttributeMap& attributes)
+{
+  //cout << "Element " << name << endl;
+
+  if (_root == NULL)
+  {
+    MyObject *obj = reinterpret_cast<MyObject*>(_doc.create_root_node(name));
+    obj->setLevel(42);
+    _root = obj;
+    _context.push(_root);
+  }
+  else
+  {
+    _context.push( reinterpret_cast<MyObject*>(_context.top()->add_child(name)));
+  }
+  
+  xmlpp::Element* element = _context.top();
+  xmlpp::SaxParser::AttributeMap::const_iterator iter;
+  
+  for (iter = attributes.begin(); iter != attributes.end(); ++iter)
+  {
+    string name = (*iter).first;
+    string value = (*iter).second;
+    //cout << "  Attribute " << name << " = " << value << endl;
+    string::size_type idx = name.find(':');
+    if (idx == string::npos)
+    {
+      if (name == "xmlns")
+        element->add_namespace("", value);
+      else
+        element->add_attribute(name, value);
+    }
+    else
+    {
+      string prefix = name.substr(0, idx);
+      name = name.substr(idx+1);
+      if (prefix == "xmlns")
+        element->add_namespace(name, value);
+      else
+        element->add_attribute(name, value, prefix);
+    }
+  }
+}
+
+void MyParser::on_end_element(const std::string& name)
+{
+  //std::cout << "on_end_element()" << std::endl;
+  _context.pop();
+}
+
+void MyParser::on_characters(const std::string& text)
+{
+  //std::cout << "on_characters(): " << text << std::endl;
+  _context.top()->add_content(text);
+}
+
+void MyParser::on_comment(const std::string& text)
+{
+  std::cout << "on_comment(): " << text << std::endl;
+}
+
+void MyParser::on_warning(const std::string& text)
+{
+  std::cout << "on_warning(): " << text << std::endl;
+}
+
+void MyParser::on_error(const std::string& text)
+{
+  std::cout << "on_error(): " << text << std::endl;
+}
+
+void MyParser::on_fatal_error(const std::string& text)
+{
+  std::cout << "on_fatal_error(): " << text << std::endl;
+}
diff -uprN /home/dan/libxml++/examples/custom_dom/myparser.h libxml++/examples/custom_dom/myparser.h
--- /home/dan/libxml++/examples/custom_dom/myparser.h	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/examples/custom_dom/myparser.h	2003-07-16 02:44:29.000000000 -0400
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+
+/* myparser.h
+ *
+ * By Dan Dennedy <dan dennedy org> 
+ *
+ * Copyright (C) 2003 The libxml++ development team
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LIBXMLPP_EXAMPLES_MYPARSER_H
+#define __LIBXMLPP_EXAMPLES_MYPARSER_H
+
+#include <stack>
+#include <string>
+#include <libxml++/libxml++.h>
+
+class MyDocument : public xmlpp::Document
+{
+  // TODO: add high-level document editing methods
+};
+
+
+class MyObject : public xmlpp::Element
+{
+  // TODO: add custom properties and methods
+private:
+  int m_level;
+
+public:
+
+  MyObject(xmlpp::Node* node)
+    : xmlpp::Element(node->cobj())
+    {}
+  virtual ~MyObject()
+    {}
+  void setLevel(int level)
+    {
+      m_level = level;
+    }
+  const int getLevel() const
+    {
+      return m_level;
+    }
+};
+
+
+class MyParser : public xmlpp::SaxParser
+{
+public:
+  MyParser(xmlpp::Document& document);
+  virtual ~MyParser();
+  MyObject* getRoot() const
+    {
+      return reinterpret_cast<MyObject*>(_root);
+    }
+
+protected:
+  //overrides:
+  virtual void on_start_document();
+  virtual void on_end_document();
+  virtual void on_start_element(const std::string& name,
+                                const AttributeMap& properties);
+  virtual void on_end_element(const std::string& name);
+  virtual void on_characters(const std::string& characters);
+  virtual void on_comment(const std::string& text);
+  virtual void on_warning(const std::string& text);
+  virtual void on_error(const std::string& text);
+  virtual void on_fatal_error(const std::string& text);
+
+private:
+	std::stack<xmlpp::Element*> _context;
+  xmlpp::Document& _doc;
+  xmlpp::Element* _root;
+};
+
+#endif //__LIBXMLPP_EXAMPLES_MYPARSER_H
diff -uprN /home/dan/libxml++/libxml++/Makefile.am libxml++/libxml++/Makefile.am
--- /home/dan/libxml++/libxml++/Makefile.am	2003-05-20 06:46:17.000000000 -0400
+++ libxml++/libxml++/Makefile.am	2003-08-07 23:59:03.000000000 -0400
@@ -2,9 +2,10 @@ SUBDIRS = parsers exceptions nodes
 
 INCLUDES = -I$(top_srcdir) @LIBXML_CFLAGS@
 
-h_sources_public = libxml++.h attribute.h dtd.h document.h noncopyable.h keepblanks.h
+h_sources_public = libxml++.h attribute.h dtd.h document.h noncopyable.h keepblanks.h \
+                   namespace.h
 h_sources_private = 
-cc_sources = attribute.cc dtd.cc document.cc noncopyable.cc keepblanks.cc
+cc_sources = attribute.cc dtd.cc document.cc noncopyable.cc keepblanks.cc namespace.cc
 cc_sources_private =
 
 lib_LTLIBRARIES = libxml++-0.1.la
diff -uprN /home/dan/libxml++/libxml++/document.cc libxml++/libxml++/document.cc
--- /home/dan/libxml++/libxml++/document.cc	2003-07-15 12:53:22.000000000 -0400
+++ libxml++/libxml++/document.cc	2003-08-07 23:56:34.000000000 -0400
@@ -203,6 +203,16 @@ Element* Document::create_root_node(cons
   return get_root_node();
 }
 
+Element* Document::create_root_node(const std::string& name,
+                                    const Namespace& ns)
+{
+  xmlNode* node = xmlNewDocNode(_impl, 0, (xmlChar*)name.c_str(), 0);
+  xmlSetNs(node, const_cast<xmlNs*>(ns.cobj()));
+  xmlDocSetRootElement(_impl, node);
+
+  return get_root_node();
+}
+
 void Document::write_to_file(const std::string& filename, const std::string& encoding)
 {
   KeepBlanks k(KeepBlanks::Default);
diff -uprN /home/dan/libxml++/libxml++/document.h libxml++/libxml++/document.h
--- /home/dan/libxml++/libxml++/document.h	2003-07-15 12:53:22.000000000 -0400
+++ libxml++/libxml++/document.h	2003-08-07 23:56:32.000000000 -0400
@@ -14,6 +14,7 @@
 #include <libxml++/exceptions/internal_error.h>
 #include <libxml++/nodes/element.h>
 #include <libxml++/dtd.h>
+#include <libxml++/namespace.h>
 
 extern "C" {
   struct _xmlDoc;
@@ -48,6 +49,8 @@ public:
   Element* create_root_node(const std::string& name,
                             const std::string& ns = std::string(),
                             const std::string& ns_prefix = std::string());
+  Element* create_root_node(const std::string& name,
+                            const Namespace& ns);
 
   virtual void write_to_file(const std::string& filename, const std::string& encoding = std::string());
   virtual void write_to_file_formatted(const std::string& filename, const std::string& encoding = std::string());
diff -uprN /home/dan/libxml++/libxml++/libxml++.h libxml++/libxml++/libxml++.h
--- /home/dan/libxml++/libxml++/libxml++.h	2003-02-03 13:47:27.000000000 -0500
+++ libxml++/libxml++/libxml++.h	2003-08-07 23:58:03.000000000 -0400
@@ -17,5 +17,6 @@
 #include <libxml++/nodes/textnode.h>
 #include <libxml++/attribute.h>
 #include <libxml++/document.h>
+#include <libxml++/namespace.h>
 
 #endif //__LIBXMLCPP_H
diff -uprN /home/dan/libxml++/libxml++/namespace.cc libxml++/libxml++/namespace.cc
--- /home/dan/libxml++/libxml++/namespace.cc	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/libxml++/namespace.cc	2003-07-13 23:29:03.000000000 -0400
@@ -0,0 +1,56 @@
+/* namespace.cc
+ * libxml++ and this file are
+ * copyright (C) 2003 by The libxml++ Development Team, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include <libxml++/namespace.h>
+#include <libxml++/exceptions/internal_error.h>
+
+#include <libxml/tree.h>
+
+namespace xmlpp
+{
+
+Namespace::Namespace(xmlNs* ns)
+  : _impl(ns)
+{
+   _impl->_private = this;
+}
+
+Namespace::~Namespace()
+{}
+
+std::string Namespace::get_prefix() const
+{
+  return _impl->prefix ? (char*)_impl->prefix : "";
+}
+
+void Namespace::set_prefix(const std::string & prefix)
+{
+  _impl->prefix = (const xmlChar *)prefix.c_str();
+}
+
+std::string Namespace::get_href() const
+{
+  return _impl->href ? (char*)_impl->href : "";
+}
+
+void Namespace::set_href(const std::string & href)
+{
+  _impl->href = (const xmlChar *)href.c_str();
+}
+
+xmlNs* Namespace::cobj()
+{
+  return _impl;
+}
+
+const xmlNs* Namespace::cobj() const
+{
+  return _impl;
+}
+
+}
+  
diff -uprN /home/dan/libxml++/libxml++/namespace.h libxml++/libxml++/namespace.h
--- /home/dan/libxml++/libxml++/namespace.h	1969-12-31 19:00:00.000000000 -0500
+++ libxml++/libxml++/namespace.h	2003-07-16 00:06:39.000000000 -0400
@@ -0,0 +1,50 @@
+
+/* namespace.h
+ * libxml++ and this file are
+ * copyright (C) 2003 by The libxml++ Development Team, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ *
+ * Namespace support contributed by Dan Dennedy <dan dennedy org>
+ */
+
+#ifndef __LIBXMLPP_NAMESPACE_H
+#define __LIBXMLPP_NAMESPACE_H
+
+#include <libxml++/noncopyable.h>
+#include <string>
+
+extern "C" {
+  struct _xmlNs;
+};
+
+namespace xmlpp {
+
+class Namespace;
+  
+class Namespace : NonCopyable
+{
+public:
+
+  explicit Namespace(_xmlNs* ns);
+  virtual ~Namespace();
+
+  std::string get_prefix() const;
+  void set_prefix(const std::string & prefix);
+
+  std::string get_href() const;
+  void set_href(const std::string & href);
+
+  ///Access the underlying libxml implementation.
+  _xmlNs* cobj();
+
+  ///Access the underlying libxml implementation.
+  const _xmlNs* cobj() const;
+
+private:
+  _xmlNs* _impl;
+};
+
+} // namespace xmlpp
+
+#endif /* __LIBXMLPP_NAMESPACE_H */
diff -uprN /home/dan/libxml++/libxml++/nodes/element.cc libxml++/libxml++/nodes/element.cc
--- /home/dan/libxml++/libxml++/nodes/element.cc	2003-05-23 08:46:35.000000000 -0400
+++ libxml++/libxml++/nodes/element.cc	2003-08-08 00:06:44.000000000 -0400
@@ -25,6 +25,18 @@ Attribute* Element::add_attribute(const 
   return set_attribute(name, value);
 }
 
+Attribute* Element::add_attribute(const std::string& name, const std::string& value,
+                                  const Namespace& ns)
+{
+  return set_attribute(name, value, ns);
+}
+
+Attribute* Element::add_attribute(const std::string& name, const std::string& value,
+                         const std::string& ns_prefix)
+{
+  return set_attribute(name, value, ns_prefix);
+}
+
 Element::AttributeList Element::get_attributes() const
 {
   AttributeList attributes;
@@ -47,6 +59,24 @@ Attribute* Element::get_attribute(const 
   return 0;
 }
 
+Attribute* Element::get_attribute(const std::string& name, const Namespace& ns) const
+{
+  for(xmlAttr* attr = cobj()->properties; attr; attr = attr->next)
+  {
+    if(xmlStrEqual(attr->name, (xmlChar*)name.c_str()) && attr->ns == ns.cobj())
+      return reinterpret_cast<Attribute*>(attr->_private);
+  }
+
+  return 0;
+}
+
+Attribute* Element::get_attribute(const std::string& name, const std::string& ns_prefix) const
+{
+  xmlAttr* attr = xmlHasNsProp(const_cast<xmlNode*>(cobj()), (xmlChar*)name.c_str(),
+                               (xmlChar*)ns_prefix.c_str());
+  return reinterpret_cast<Attribute*>(attr->_private);
+}
+
 Attribute* Element::set_attribute(const std::string& name, const std::string& value)
 {
   xmlAttr* attr = xmlSetProp(cobj(),
@@ -55,11 +85,47 @@ Attribute* Element::set_attribute(const 
   return reinterpret_cast<Attribute*>(attr->_private);
 }
 
+Attribute* Element::set_attribute(const std::string& name, const std::string& value,
+                                  const Namespace& ns)
+{
+  xmlAttr* attr = xmlSetNsProp(cobj(), const_cast<xmlNs*>(ns.cobj()),
+                               (xmlChar*)name.c_str(),
+                               (xmlChar*)value.c_str());
+  return reinterpret_cast<Attribute*>(attr->_private);
+}
+
+Attribute* Element::set_attribute(const std::string& name, const std::string& value,
+                                  const std::string& ns_prefix)
+{
+  xmlNs* ns = xmlSearchNs(cobj()->doc, cobj(), (xmlChar*)ns_prefix.c_str());
+  if (ns)
+  {
+    xmlAttr* attr = xmlSetNsProp(cobj(), ns,
+                                 (xmlChar*)name.c_str(),
+                                 (xmlChar*)value.c_str());
+    return reinterpret_cast<Attribute*>(attr->_private);
+  }
+  else
+    return 0;
+}
+
 void Element::remove_attribute(const std::string& name)
 {
   xmlUnsetProp(cobj(), (xmlChar*)name.c_str());
 }
 
+void Element::remove_attribute(const std::string& name, const Namespace& ns)
+{
+  xmlUnsetNsProp(cobj(), const_cast<xmlNs*>(ns.cobj()), (xmlChar*)name.c_str());
+}
+
+void Element::remove_attribute(const std::string& name, std::string& ns_prefix)
+{
+  xmlNs* ns = xmlSearchNs(cobj()->doc, cobj(), (xmlChar*)ns_prefix.c_str());
+  if (ns)
+    xmlUnsetNsProp(cobj(), ns, (xmlChar*)name.c_str());
+}
+
 const TextNode* Element::get_child_content() const
 {
   // FIXME: return only the first content node
@@ -105,6 +171,27 @@ bool Element::has_content() const
   return get_child_content() != 0;
 }
 
+void Element::set_namespace(const Namespace& ns)
+{
+  xmlSetNs(cobj(), const_cast<xmlNs*>(ns.cobj()));
+}
+
+Namespace* Element::set_namespace(const std::string& ns_prefix)
+{
+  xmlNs* ns = xmlSearchNs(cobj()->doc, cobj(), (xmlChar*)ns_prefix.c_str());
+  if (ns)
+    return reinterpret_cast<Namespace*>(ns);
+  else
+    return 0;
+}
+
+Namespace* Element::add_namespace(const std::string& ns_prefix,
+                                  const std::string& ns)
+{
+  xmlNs* newNs = xmlNewNs(cobj(), (xmlChar*)ns.c_str(),
+                 (xmlChar*)(ns_prefix.empty() ? 0 : ns_prefix.c_str()));
+  return reinterpret_cast<Namespace*>(cobj()->ns);
+}
 
 
 } //namespace xmlpp
diff -uprN /home/dan/libxml++/libxml++/nodes/element.h libxml++/libxml++/nodes/element.h
--- /home/dan/libxml++/libxml++/nodes/element.h	2003-05-30 14:12:49.000000000 -0400
+++ libxml++/libxml++/nodes/element.h	2003-08-08 00:12:09.000000000 -0400
@@ -9,6 +9,7 @@
 
 #include <libxml++/nodes/node.h>
 #include <libxml++/attribute.h>
+#include <libxml++/namespace.h>
 
 namespace xmlpp
 {
@@ -24,10 +25,24 @@ public:
   // FIXME: the following only returns explicitely provided
   // attributes, not default ones declared in the dtd.
   Attribute* get_attribute(const std::string& name) const;
+  Attribute* get_attribute(const std::string& name, const Namespace& ns) const;
+  Attribute* get_attribute(const std::string& name, const std::string& ns_prefix) const;
+
   Attribute* set_attribute(const std::string& name, const std::string& value);
+  Attribute* set_attribute(const std::string& name, const std::string& value,
+                           const Namespace& ns);
+  Attribute* set_attribute(const std::string& name, const std::string& value,
+                           const std::string& ns_prefix);
+
   void remove_attribute(const std::string& name);
+  void remove_attribute(const std::string& name, const Namespace& ns);
+  void remove_attribute(const std::string& name, std::string& ns_prefix);
   
   Attribute* add_attribute(const std::string& name, const std::string& value);
+  Attribute* add_attribute(const std::string& name, const std::string& value,
+                           const Namespace& ns);
+  Attribute* add_attribute(const std::string& name, const std::string& value,
+                           const std::string& ns_prefix);
 
   
   // TODO: this should be reimplemented in two ways:
@@ -44,6 +59,11 @@ public:
   void set_child_content(const std::string& content);
 
   bool has_content() const;
+
+  void set_namespace(const Namespace& ns);
+  Namespace* set_namespace(const std::string& ns_prefix);
+  Namespace* add_namespace(const std::string& ns_prefix,
+                           const std::string& ns = std::string());
 };
 
 } // namespace xmlpp
diff -uprN /home/dan/libxml++/libxml++/nodes/node.cc libxml++/libxml++/nodes/node.cc
--- /home/dan/libxml++/libxml++/nodes/node.cc	2003-07-15 12:53:22.000000000 -0400
+++ libxml++/libxml++/nodes/node.cc	2003-08-08 00:11:36.000000000 -0400
@@ -53,6 +53,46 @@ Element* Node::add_child(const std::stri
    return static_cast<Element*>(node->_private);
 }
 
+Element* Node::add_child(const std::string& name, const Namespace& ns)
+{
+   if(_impl->type != XML_ELEMENT_NODE)
+      throw internal_error("you can only add child nodes to element nodes");
+      
+   xmlNode* node = xmlAddChild(_impl, xmlNewNode(const_cast<xmlNs*>(ns.cobj()),
+                               (xmlChar*)name.c_str()));
+   return static_cast<Element*>(node->_private);
+}
+
+Element* Node::add_child(const std::string& name,
+                   const std::string& ns_prefix)
+{
+   if(_impl->type != XML_ELEMENT_NODE)
+      throw internal_error("you can only add child nodes to element nodes");
+   
+   xmlNs* ns = xmlSearchNs(_impl->doc, _impl, ns_prefix.empty() ? 0 : (xmlChar*)ns_prefix.c_str());
+   if (ns)
+   {
+     xmlNode* node = xmlAddChild(_impl, xmlNewNode(ns, (xmlChar*)name.c_str()));
+     return static_cast<Element*>(node->_private);
+   }
+   else
+     throw internal_error("specified namespace prefix does not exist");
+}
+
+Element* Node::add_child(const std::string& name,
+                   const std::string& ns,
+                   const std::string& ns_prefix)
+{
+   if(_impl->type != XML_ELEMENT_NODE)
+      throw internal_error("you can only add child nodes to element nodes");
+      
+   xmlNode* node = xmlAddChild(_impl, xmlNewNode(0, (xmlChar*)name.c_str()));
+   xmlNewNs(node,
+            (xmlChar*) ns.c_str(),
+            (xmlChar*) ns_prefix.c_str());
+   return static_cast<Element*>(node->_private);
+}
+
 void Node::remove_child(Node* node)
 {
   //TODO: Allow a node to be removed without deleting it, to allow it to be moved?
@@ -136,6 +176,11 @@ NodeSet Node::find(const std::string& xp
   return nodes;
 }
 
+Namespace* Node::get_namespace()
+{
+  return reinterpret_cast<Namespace*>(_impl->ns);
+}
+
 } //namespace xmlpp
 
 
diff -uprN /home/dan/libxml++/libxml++/nodes/node.h libxml++/libxml++/nodes/node.h
--- /home/dan/libxml++/libxml++/nodes/node.h	2003-07-15 12:53:22.000000000 -0400
+++ libxml++/libxml++/nodes/node.h	2003-08-08 00:13:06.000000000 -0400
@@ -9,6 +9,7 @@
 
 #include <libxml++/noncopyable.h>
 #include <libxml++/exceptions/exception.h>
+#include <libxml++/namespace.h>
 #include <string>
 #include <list>
 #include <map>
@@ -51,6 +52,12 @@ public:
   // TODO: how should this work in general (depending on the exact types
   // of parent and child node)
   //   Node* add_child(Node* node);
+  Element* add_child(const std::string& name, const Namespace& ns);
+  Element* add_child(const std::string& name,
+                     const std::string& ns_prefix);
+  Element* add_child(const std::string& name,
+                     const std::string& ns,
+                     const std::string& ns_prefix);
 
 
   /** Remove the child node.
@@ -73,6 +80,8 @@ public:
   ///Access the underlying libxml implementation.
   const _xmlNode* cobj() const;
 
+  Namespace* get_namespace();
+
 private:
   _xmlNode* _impl;
 };


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