[libxml++] Handle attributes with default values correctly.



commit e9fec24cb7d954ab6a62df47c97a15da9fb948c4
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Wed Feb 15 16:47:56 2012 +0100

    Handle attributes with default values correctly.
    
    * libxml++/attributedeclaration.[h|cc]:
    * libxml++/attributenode.[h|cc]: New files.
    * Makefile.am:
    * libxml++/Makefile.am: Add the new files.
    * libxml++/libxml++.h: Add the new .h files.
    * docs/manual/libxml++_without_code.xml: Add AttributeDeclaration and
    AttributeNode in the list of node classes.
    * libxml++/attribute.[h|cc]: Make get_value() useful also for default values
    (XML_ATTRIBUTE_DECL). Fix set_value() for attributes in a namespace.
    * libxml++/nodes/element.[h|cc]: get_attribute(): Add description. Don't use
    xmlHasProp(), it ignores namespace.
    * libxml++/nodes/node.cc: get_namespace_prefix(), get_namespace_uri(),
    set_namespace(), create_wrapper(): Add code for XML_ATTRIBUTE_DECL.
    * examples/dom_parser/example.dtd: Add attribute 'title' with default value.
    * examples/dom_parser/example.xml: Add attribute 'title' with explicit value.
    Bug #669635.

 ChangeLog                             |   21 ++++++++++++++
 Makefile.am                           |    4 +++
 docs/manual/libxml++_without_code.xml |    7 ++++-
 examples/dom_parser/example.dtd       |    1 +
 examples/dom_parser/example.xml       |    2 +-
 libxml++/Makefile.am                  |    4 +++
 libxml++/attribute.cc                 |   38 ++++++++++++++++++-------
 libxml++/attribute.h                  |   28 +++++++++++++++----
 libxml++/attributedeclaration.cc      |   42 ++++++++++++++++++++++++++++
 libxml++/attributedeclaration.h       |   48 +++++++++++++++++++++++++++++++++
 libxml++/attributenode.cc             |   23 +++++++++++++++
 libxml++/attributenode.h              |   32 ++++++++++++++++++++++
 libxml++/libxml++.h                   |    2 +
 libxml++/nodes/element.cc             |   35 ++++++++++++-----------
 libxml++/nodes/element.h              |   20 +++++++++-----
 libxml++/nodes/node.cc                |   34 ++++++++++++++++++++---
 16 files changed, 293 insertions(+), 48 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8d87906..f2ab1d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2012-02-15  Kjell Ahlstedt  <kjell ahlstedt bredband net>
 
+	Handle attributes with default values correctly.
+
+	* libxml++/attributedeclaration.[h|cc]:
+	* libxml++/attributenode.[h|cc]: New files.
+	* Makefile.am:
+	* libxml++/Makefile.am: Add the new files.
+	* libxml++/libxml++.h: Add the new .h files.
+	* docs/manual/libxml++_without_code.xml: Add AttributeDeclaration and
+	AttributeNode in the list of node classes.
+	* libxml++/attribute.[h|cc]: Make get_value() useful also for default values
+	(XML_ATTRIBUTE_DECL). Fix set_value() for attributes in a namespace.
+	* libxml++/nodes/element.[h|cc]: get_attribute(): Add description. Don't use
+	xmlHasProp(), it ignores namespace.
+	* libxml++/nodes/node.cc: get_namespace_prefix(), get_namespace_uri(),
+	set_namespace(), create_wrapper(): Add code for XML_ATTRIBUTE_DECL.
+	* examples/dom_parser/example.dtd: Add attribute 'title' with default value.
+	* examples/dom_parser/example.xml: Add attribute 'title' with explicit value.
+	Bug #669635.
+
+2012-02-15  Kjell Ahlstedt  <kjell ahlstedt bredband net>
+
 	Node: Correct mis-spelt LIBXMLCPP_EXCEPTIONS_ENABLED.
 
 	* libxml++/nodes/node.h: Add some "@throws exception".
diff --git a/Makefile.am b/Makefile.am
index 5b76b34..394f735 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,6 +36,8 @@ DEFS = @DEFS@ -DLIBXMLPP_BUILD
 
 h_root_sources_public = libxml++/libxml++.h \
 	libxml++/attribute.h \
+	libxml++/attributedeclaration.h \
+	libxml++/attributenode.h \
 	libxml++/document.h \
 	libxml++/dtd.h \
 	libxml++/keepblanks.h \
@@ -73,6 +75,8 @@ h_sources_public = $(h_root_sources_public) \
 	$(h_validators_sources_public)
 
 cc_sources = libxml++/attribute.cc \
+	libxml++/attributedeclaration.cc \
+	libxml++/attributenode.cc \
 	libxml++/document.cc \
 	libxml++/dtd.cc \
 	libxml++/keepblanks.cc \
diff --git a/docs/manual/libxml++_without_code.xml b/docs/manual/libxml++_without_code.xml
index c30a885..a8e57a0 100644
--- a/docs/manual/libxml++_without_code.xml
+++ b/docs/manual/libxml++_without_code.xml
@@ -86,7 +86,12 @@ url="http://libxmlplusplus.sourceforge.net";>libxmlplusplus.sourceforge.net</ulin
       <itemizedlist>
       <listitem><para>xmlpp::Node:
         <itemizedlist>
-          <listitem><para>xmlpp::Attribute</para></listitem>
+          <listitem><para>xmlpp::Attribute
+          <itemizedlist>
+            <listitem><para>xmlpp::AttributeDeclaration</para></listitem>
+            <listitem><para>xmlpp::AttributeNode</para></listitem>
+          </itemizedlist>
+          </para></listitem>
           <listitem><para>xmlpp::ContentNode
           <itemizedlist>
             <listitem><para>xmlpp::CdataNode</para></listitem>
diff --git a/examples/dom_parser/example.dtd b/examples/dom_parser/example.dtd
index b21ed41..0a401b1 100644
--- a/examples/dom_parser/example.dtd
+++ b/examples/dom_parser/example.dtd
@@ -8,6 +8,7 @@ DTD for libxml++ example.
 <!ELEMENT examplechild (child_of_child)+ >
 <!ATTLIST examplechild
   id    CDATA	#REQUIRED
+  title CDATA "No title"
 >
 
 <!ELEMENT child_of_child EMPTY >
diff --git a/examples/dom_parser/example.xml b/examples/dom_parser/example.xml
index 4745f79..b47410a 100644
--- a/examples/dom_parser/example.xml
+++ b/examples/dom_parser/example.xml
@@ -2,7 +2,7 @@
 <!DOCTYPE example PUBLIC "" "example.dtd">
 
 <example>
-  <examplechild id="1">
+  <examplechild id="1" title="First child element">
     <child_of_child/>
   </examplechild>
   <examplechild id="2">
diff --git a/libxml++/Makefile.am b/libxml++/Makefile.am
index 091ce26..a527138 100644
--- a/libxml++/Makefile.am
+++ b/libxml++/Makefile.am
@@ -3,6 +3,8 @@ DEFS = @DEFS@ -DLIBXMLPP_BUILD
 
 h_sources_public = libxml++.h \
 	attribute.h \
+	attributedeclaration.h \
+	attributenode.h \
 	document.h \
 	dtd.h \
 	keepblanks.h \
@@ -33,6 +35,8 @@ h_sources_public = libxml++.h \
 	validators/schemavalidator.h \
 	validators/validator.h
 cc_sources = attribute.cc \
+	attributedeclaration.cc \
+	attributenode.cc \
 	document.cc \
 	dtd.cc \
 	keepblanks.cc \
diff --git a/libxml++/attribute.cc b/libxml++/attribute.cc
index 7369783..c36428a 100644
--- a/libxml++/attribute.cc
+++ b/libxml++/attribute.cc
@@ -5,6 +5,7 @@
  */
 
 #include "libxml++/attribute.h"
+#include "libxml++/attributedeclaration.h"
 
 #include <libxml/tree.h>
 
@@ -22,24 +23,42 @@ Attribute::~Attribute()
 
 Glib::ustring Attribute::get_name() const
 {
+  // This will get the name also for an AttributeDeclaration. The name is in
+  // the same position in xmlNode, xmlAttr and xmlAttribute.
   return cobj()->name ? (char*)cobj()->name : Glib::ustring();
 }
 
+//TODO when we can break ABI: Make get_value() virtual.
 Glib::ustring Attribute::get_value() const
 {
-  const xmlChar* ns_uri = 0;
-  if(cobj()->ns)
-    ns_uri = cobj()->ns->href;
-
-  xmlChar *value = xmlGetNsProp(cobj()->parent, cobj()->name, ns_uri);
-  const Glib::ustring retn = value ? (char*)value : Glib::ustring();
-  xmlFree(value);
+  const AttributeDeclaration* const attributeDecl =
+    dynamic_cast<const AttributeDeclaration*>(this);
+  if (attributeDecl) // AttributeDeclaration
+    return attributeDecl->get_value();
+
+  // AttributeNode
+  xmlChar* value = 0;
+  if (cobj()->ns && cobj()->ns->href)
+    value = xmlGetNsProp(cobj()->parent, cobj()->name, cobj()->ns->href);
+  else
+    value = xmlGetNoNsProp(cobj()->parent, cobj()->name);
+
+  const Glib::ustring retn = value ? (const char*)value : "";
+  if (value)
+    xmlFree(value);
   return retn;
 }
 
+//TODO when we can break ABI: Move set_value() to AttributeNode.
 void Attribute::set_value(const Glib::ustring& value)
 {
-  xmlSetProp(cobj()->parent, cobj()->name, (xmlChar*)value.c_str());
+  if (dynamic_cast<const AttributeDeclaration*>(this))
+    return; // Won't change the value of an AttributeDeclaration
+
+  if (cobj()->ns)
+    xmlSetNsProp(cobj()->parent, cobj()->ns, cobj()->name, (const xmlChar*)value.c_str());
+  else
+    xmlSetProp(cobj()->parent, cobj()->name, (const xmlChar*)value.c_str());
 }
 
 xmlAttr* Attribute::cobj()
@@ -60,6 +79,3 @@ const xmlAttr* Attribute::cobj() const
 
 } //namespace xmlpp
 
-
-
-
diff --git a/libxml++/attribute.h b/libxml++/attribute.h
index 0c49d7c..6bb72df 100644
--- a/libxml++/attribute.h
+++ b/libxml++/attribute.h
@@ -21,8 +21,8 @@ extern "C" {
 namespace xmlpp
 {
 
-/** Represents XML Node attributes.
- *
+/** Represents an XML Node attribute.
+ * This will be instantiated by the parser.
  */
 class Attribute : public Node
 {
@@ -31,26 +31,42 @@ public:
   virtual ~Attribute();
   
   //TODO: Can we remove this and just use Node::get_name()?
+  // Yes, when we can break ABI. /Kjell Ahlstedt 2012-02-09
 
   /** Get the name of this attribute.
    * See also Node::get_namespace_prefix() and Node::get_namespace_uri()
-   * @returns The attributes's name.
+   * @returns The attribute's name.
    */
   Glib::ustring get_name() const;
 
   /** Get the value of this attribute.
-   * @returns The attributes's value.
+   * Can be used for both an AttributeDeclaration and an AttributeNode.
+   * @returns The attribute's value.
    */
   Glib::ustring get_value() const;
 
   /** Set the value of this attribute.
+   *
+   * If this is an AttributeDeclaration, the value will not be changed.
+   * This method is here for backward compatibility. It may be moved to
+   * AttributeNode in the future.
    */
   void set_value(const Glib::ustring& value);
 
-  ///Access the underlying libxml implementation.
+  /** Access the underlying libxml implementation.
+   *
+   * If this is an AttributeDeclaration, use AttributeDeclaration::cobj() instead.
+   * This method is here for backward compatibility. It may be moved to
+   * AttributeNode in the future.
+   */
   _xmlAttr* cobj();
 
-  ///Access the underlying libxml implementation.
+  /** Access the underlying libxml implementation.
+   *
+   * If this is an AttributeDeclaration, use AttributeDeclaration::cobj() instead.
+   * This method is here for backward compatibility. It may be moved to
+   * AttributeNode in the future.
+   */
   const _xmlAttr* cobj() const;
 };
 
diff --git a/libxml++/attributedeclaration.cc b/libxml++/attributedeclaration.cc
new file mode 100644
index 0000000..16ff57b
--- /dev/null
+++ b/libxml++/attributedeclaration.cc
@@ -0,0 +1,42 @@
+/* attributedeclaration.cc
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include "libxml++/attributedeclaration.h"
+
+#include <libxml/tree.h>
+
+namespace xmlpp
+{
+
+AttributeDeclaration::AttributeDeclaration(xmlNode* node)
+  : Attribute(node)
+{
+}
+
+AttributeDeclaration::~AttributeDeclaration()
+{
+}
+
+Glib::ustring AttributeDeclaration::get_value() const
+{
+  return (const char*)cobj()->defaultValue;
+}
+
+xmlAttribute* AttributeDeclaration::cobj()
+{
+  // An XML_ATTRIBUTE_DECL is represented by an xmlAttribute struct. Reinterpret
+  // the xmlNode pointer stored in the base class as an xmlAttribute pointer.
+  return reinterpret_cast<xmlAttribute*>(Node::cobj());
+}
+
+const xmlAttribute* AttributeDeclaration::cobj() const
+{
+  // An XML_ATTRIBUTE_DECL is represented by an xmlAttribute struct. Reinterpret
+  // the xmlNode pointer stored in the base class as an xmlAttribute pointer.
+  return reinterpret_cast<const xmlAttribute*>(Node::cobj());
+}
+
+} //namespace xmlpp
diff --git a/libxml++/attributedeclaration.h b/libxml++/attributedeclaration.h
new file mode 100644
index 0000000..8764b0b
--- /dev/null
+++ b/libxml++/attributedeclaration.h
@@ -0,0 +1,48 @@
+/* attributedeclaration.h
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#ifndef __LIBXMLPP_ATTRIBUTEDECLARATION_H
+#define __LIBXMLPP_ATTRIBUTEDECLARATION_H
+
+#include <glibmm/ustring.h>
+
+#include <libxml++/attribute.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" {
+  struct _xmlAttribute;
+}
+#endif //#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace xmlpp
+{
+
+/** Represents the default value of an attribute of an XML Element node.
+ * This will be instantiated by the parser.
+ *
+ * @newin{2,36}
+ */
+class AttributeDeclaration : public Attribute
+{
+public:
+  explicit AttributeDeclaration(_xmlNode* node);
+  virtual ~AttributeDeclaration();
+
+  /** Get the default value of this attribute.
+   * @returns The attribute's default value.
+   */
+  Glib::ustring get_value() const;
+
+  ///Access the underlying libxml implementation.
+  _xmlAttribute* cobj();
+
+  ///Access the underlying libxml implementation.
+  const _xmlAttribute* cobj() const;
+};
+
+} // namespace xmlpp
+
+#endif //__LIBXMLPP_ATTRIBUTEDECLARATION_H
diff --git a/libxml++/attributenode.cc b/libxml++/attributenode.cc
new file mode 100644
index 0000000..a874415
--- /dev/null
+++ b/libxml++/attributenode.cc
@@ -0,0 +1,23 @@
+/* attributenode.cc
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include "libxml++/attributenode.h"
+
+#include <libxml/tree.h>
+
+namespace xmlpp
+{
+
+AttributeNode::AttributeNode(xmlNode* node)
+  : Attribute(node)
+{
+}
+
+AttributeNode::~AttributeNode()
+{
+}
+
+} //namespace xmlpp
diff --git a/libxml++/attributenode.h b/libxml++/attributenode.h
new file mode 100644
index 0000000..cd559f3
--- /dev/null
+++ b/libxml++/attributenode.h
@@ -0,0 +1,32 @@
+/* attributenode.h
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#ifndef __LIBXMLPP_ATTRIBUTENODE_H
+#define __LIBXMLPP_ATTRIBUTENODE_H
+
+
+#include <glibmm/ustring.h>
+
+#include <libxml++/attribute.h>
+
+namespace xmlpp
+{
+
+/** Represents an explicit attribute of an XML Element node.
+ * This will be instantiated by the parser.
+ *
+ * @newin{2,36}
+ */
+class AttributeNode : public Attribute
+{
+public:
+  explicit AttributeNode(_xmlNode* node);
+  virtual ~AttributeNode();
+};
+
+} // namespace xmlpp
+
+#endif //__LIBXMLPP_ATTRIBUTENODE_H
diff --git a/libxml++/libxml++.h b/libxml++/libxml++.h
index 6f630a7..05a5806 100644
--- a/libxml++/libxml++.h
+++ b/libxml++/libxml++.h
@@ -59,6 +59,8 @@
 #include <libxml++/nodes/entityreference.h>
 #include <libxml++/nodes/textnode.h>
 #include <libxml++/attribute.h>
+#include <libxml++/attributedeclaration.h>
+#include <libxml++/attributenode.h>
 #include <libxml++/document.h>
 #include <libxml++/validators/validator.h>
 #include <libxml++/validators/dtdvalidator.h>
diff --git a/libxml++/nodes/element.cc b/libxml++/nodes/element.cc
index 809eaa3..365d5ac 100644
--- a/libxml++/nodes/element.cc
+++ b/libxml++/nodes/element.cc
@@ -40,25 +40,26 @@ const Element::AttributeList Element::get_attributes() const
 Attribute* Element::get_attribute(const Glib::ustring& name,
                                   const Glib::ustring& ns_prefix) const
 {
-  if(ns_prefix.empty())
+  // An empty ns_prefix means "use no namespace".
+  // The default namespace never applies to an attribute.
+  Glib::ustring ns_uri;
+  if (!ns_prefix.empty())
   {
-    xmlAttr* attr = xmlHasProp(const_cast<xmlNode*>(cobj()), (const xmlChar*)name.c_str());
-    if( attr )
-    {
-      Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
-      return reinterpret_cast<Attribute*>(attr->_private);
-    }
+    ns_uri = get_namespace_uri_for_prefix(ns_prefix);
+    if (ns_uri.empty())
+      return 0; // No such prefix.
   }
-  else
+
+  // The return value of xmlHasNsProp() may be either an xmlAttr*, pointing to an
+  // explicitly set attribute (XML_ATTRIBUTE_NODE), or an xmlAttribute*,
+  // cast to an xmlAttr*, pointing to the declaration of an attribute with a
+  // default value (XML_ATTRIBUTE_DECL).
+  xmlAttr* attr = xmlHasNsProp(const_cast<xmlNode*>(cobj()), (const xmlChar*)name.c_str(),
+                               ns_uri.empty() ? 0 : (const xmlChar*)ns_uri.c_str());
+  if (attr)
   {
-    Glib::ustring ns_uri = get_namespace_uri_for_prefix(ns_prefix);  
-    xmlAttr* attr = xmlHasNsProp(const_cast<xmlNode*>(cobj()), (const xmlChar*)name.c_str(),
-                                 (const xmlChar*)ns_uri.c_str());
-    if( attr )
-    {
-      Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
-      return reinterpret_cast<Attribute*>(attr->_private);
-    }
+    Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
+    return reinterpret_cast<Attribute*>(attr->_private);
   }
 
   return 0;
@@ -215,7 +216,7 @@ void Element::set_namespace_declaration(const Glib::ustring& ns_uri, const Glib:
   //Create a new namespace declaration for this element:
   xmlNewNs(cobj(), (const xmlChar*)(ns_uri.empty() ? 0 : ns_uri.c_str()),
                    (const xmlChar*)(ns_prefix.empty() ? 0 : ns_prefix.c_str()) );
-  //We ignore the returned xmlNS*. Hopefully this is owned by the node. murrayc.
+  //We ignore the returned xmlNs*. Hopefully this is owned by the node. murrayc.
 }
 
 Glib::ustring Element::get_namespace_uri_for_prefix(const Glib::ustring& ns_prefix) const
diff --git a/libxml++/nodes/element.h b/libxml++/nodes/element.h
index da46d4c..c9e3082 100644
--- a/libxml++/nodes/element.h
+++ b/libxml++/nodes/element.h
@@ -34,21 +34,26 @@ public:
    */
   void set_namespace_declaration(const Glib::ustring& ns_uri, const Glib::ustring& ns_prefix = Glib::ustring());
 
-  /** Obtain the list of attributes for this element.
-   * @returns The list of attributes.
+  /** Obtain the list of explicitly set attributes for this element.
+   * @returns The list of explicitly set attributes.
    */
   AttributeList get_attributes();
 
-  /** Obtain the list of attributes for this element.
-   * @returns The list of attributes.
+  /** Obtain the list of explicitly set attributes for this element.
+   * @returns The list of explicitly set attributes.
    */
   const AttributeList get_attributes() const;
 
   //TODO: There should be a const and non-const version.
   //See the patch at https://bugzilla.gnome.org/show_bug.cgi?id=632524
-  // FIXME: the following only returns explicitely provided
-  // attributes, not default ones declared in the dtd.
-  // TODO: Is this still true? murrayc
+  /** Get the attribute with this name, and optionally with this namespace.
+   * @param name The name of the attribute that will be retrieved.
+   * @param ns_prefix Namespace prefix.
+   * @return The attribute, or 0 if no suitable Attribute was found.
+   *         Is either an AttributeNode*, pointing to an explicitly set
+   *         attribute, or an AttributeDeclaration*, pointing to the declaration
+   *         of an attribute with a default value.
+   */
   Attribute* get_attribute(const Glib::ustring& name,
                            const Glib::ustring& ns_prefix = Glib::ustring()) const;
 
@@ -70,6 +75,7 @@ public:
    * @param value The new value for the attribute
    * @param ns_prefix Namespace prefix. If the prefix has not been declared then this method will throw an exception.
    * @return The attribute that was changed, or 0 is no suitable Attribute was found.
+   * @throws exception
    */
   Attribute* set_attribute(const Glib::ustring& name, const Glib::ustring& value,
                            const Glib::ustring& ns_prefix = Glib::ustring());
diff --git a/libxml++/nodes/node.cc b/libxml++/nodes/node.cc
index ef70bfc..6ce2b64 100644
--- a/libxml++/nodes/node.cc
+++ b/libxml++/nodes/node.cc
@@ -13,6 +13,8 @@
 #include <libxml++/nodes/cdatanode.h>
 #include <libxml++/nodes/processinginstructionnode.h>
 #include <libxml++/exceptions/internal_error.h>
+#include <libxml++/attributedeclaration.h>
+#include <libxml++/attributenode.h>
 #include <libxml++/document.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
@@ -362,6 +364,12 @@ Glib::ustring Node::get_namespace_prefix() const
 
     return Glib::ustring();
   }
+  else if (impl_->type == XML_ATTRIBUTE_DECL)
+  {
+    //impl_ is actually of type xmlAttribute, instead of just xmlNode.
+    const xmlAttribute* const attr = reinterpret_cast<const xmlAttribute*>(impl_);
+    return attr->prefix ? (const char*)attr->prefix : "";
+  }
 
   if(impl_ && impl_->ns && impl_->ns->prefix)
     return (char*)impl_->ns->prefix;
@@ -371,11 +379,13 @@ Glib::ustring Node::get_namespace_prefix() const
 
 Glib::ustring Node::get_namespace_uri() const
 {
-  if(impl_->type == XML_DOCUMENT_NODE || impl_->type == XML_ENTITY_DECL)
+  if(impl_->type == XML_DOCUMENT_NODE ||
+     impl_->type == XML_ENTITY_DECL ||
+     impl_->type == XML_ATTRIBUTE_DECL)
   {
-    //impl_ is actually of type xmlDoc or xmlEntity, instead of just xmlNode.
-    //libxml does not always use GObject-style inheritance, so xmlDoc and
-    //xmlEntity do not have all the same struct fields as xmlNode.
+    //impl_ is actually of type xmlDoc, xmlEntity or xmlAttribute, instead of just xmlNode.
+    //libxml does not always use GObject-style inheritance, so those structs
+    //do not have all the same struct fields as xmlNode.
     //Therefore, a call to impl_->ns would be invalid.
     //This can be an issue when calling this method on a Node returned by Node::find().
     //See the TODO comment on Document, suggesting that Document should derived from Node.
@@ -391,6 +401,15 @@ Glib::ustring Node::get_namespace_uri() const
 
 void Node::set_namespace(const Glib::ustring& ns_prefix)
 {
+  if (impl_->type == XML_ATTRIBUTE_DECL)
+  {
+    #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
+    throw exception("Can't set the namespace of an attribute declaration");
+    #else
+    return;
+    #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
+  }
+
   //Look for the existing namespace to use:
   xmlNs* ns = xmlSearchNs( cobj()->doc, cobj(), (xmlChar*)(ns_prefix.empty() ? 0 : ns_prefix.c_str()) );
   if(ns)
@@ -423,7 +442,12 @@ void Node::create_wrapper(xmlNode* node)
     }
     case XML_ATTRIBUTE_NODE:
     {
-      node->_private = new xmlpp::Attribute(node);
+      node->_private = new xmlpp::AttributeNode(node);
+      break;
+    }
+    case XML_ATTRIBUTE_DECL:
+    {
+      node->_private = new xmlpp::AttributeDeclaration(node);
       break;
     }
     case XML_TEXT_NODE:



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