[Libxmlplusplus-general] Multiple Node types



I've mostly implemented the separate TextNode class (see the attached
patch), but I can't figure out why examples/dom_build has this output:

<?xml version="1.0"?>
<!DOCTYPE example_xml_doc PUBLIC "" "example_xml_doc.dtd">
<exampleroot><examplechild id="1"><>Some
content</><child_of_child/></examplechild><examplechild
id="2"/></exampleroot>

Notice the <> and </> around "Some Content".

examples/dom_parser seems to work OK.


-- 
Murray Cumming
murray usa net
www.murrayc.com
? Makefile
? Makefile.in
? aclocal.m4
? autom4te.cache
? config.log
? config.status
? configure
? libtool
? libxml++-1.0.pc
? libxml++.kdevprj
? libxml++.kdevses
? libxmlplusplus_textnode.patch
? temp.diff
? xml++-config
? docs/Makefile
? docs/Makefile.in
? docs/reference/Makefile
? docs/reference/Makefile.in
? examples/Makefile
? examples/Makefile.in
? examples/dom_build/.deps
? examples/dom_build/.libs
? examples/dom_build/Makefile
? examples/dom_build/Makefile.in
? examples/dom_build/example
? examples/dom_parser/.deps
? examples/dom_parser/.libs
? examples/dom_parser/Makefile
? examples/dom_parser/Makefile.in
? examples/dom_parser/example
? examples/sax_exception/.deps
? examples/sax_exception/.libs
? examples/sax_exception/Makefile
? examples/sax_exception/Makefile.in
? examples/sax_exception/example
? examples/sax_parser/.deps
? examples/sax_parser/.libs
? examples/sax_parser/Makefile
? examples/sax_parser/Makefile.in
? examples/sax_parser/example
? libxml++/.deps
? libxml++/.libs
? libxml++/Makefile
? libxml++/Makefile.in
? libxml++/attribute.lo
? libxml++/dtd.lo
? libxml++/libxml++-0.1.la
? libxml++/exceptions/.deps
? libxml++/exceptions/.libs
? libxml++/exceptions/Makefile
? libxml++/exceptions/Makefile.in
? libxml++/exceptions/exception.lo
? libxml++/exceptions/internal_error.lo
? libxml++/exceptions/libexceptions.la
? libxml++/exceptions/parse_error.lo
? libxml++/nodes/.deps
? libxml++/nodes/.libs
? libxml++/nodes/Makefile
? libxml++/nodes/Makefile.am
? libxml++/nodes/Makefile.in
? libxml++/nodes/libnodes.la
? libxml++/nodes/node.lo
? libxml++/nodes/textnode.cc
? libxml++/nodes/textnode.h
? libxml++/nodes/textnode.lo
? libxml++/parsers/.deps
? libxml++/parsers/.libs
? libxml++/parsers/Makefile
? libxml++/parsers/Makefile.in
? libxml++/parsers/domparser.lo
? libxml++/parsers/libparsers.la
? libxml++/parsers/parser.lo
? libxml++/parsers/saxparser.lo
Index: examples/dom_build/main.cc
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/examples/dom_build/main.cc,v
retrieving revision 1.4
diff -u -p -r1.4 main.cc
--- examples/dom_build/main.cc	9 Dec 2002 18:56:22 -0000	1.4
+++ examples/dom_build/main.cc	17 Dec 2002 16:55:05 -0000
@@ -45,7 +45,7 @@ main(int argc, char* argv[])
 
     xmlpp::Node* nodeChild = nodeRoot->add_child("examplechild");
     nodeChild->add_attribute("id", "1");
-    nodeChild->set_content("Some content");
+    nodeChild->set_child_content("Some content");
 
     nodeChild->add_child("child_of_child");
 
Index: examples/dom_parser/main.cc
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/examples/dom_parser/main.cc,v
retrieving revision 1.12
diff -u -p -r1.12 main.cc
--- examples/dom_parser/main.cc	9 Dec 2002 21:24:20 -0000	1.12
+++ examples/dom_parser/main.cc	17 Dec 2002 16:55:05 -0000
@@ -35,31 +35,40 @@ void print_indentation(unsigned int inde
 
 void print_node(const xmlpp::Node& node, unsigned int indentation = 0)
 {
-  print_indentation(indentation);
-  std::cout << "Node name = " << node.name() << std::endl;
-  print_indentation(indentation);
-  std::cout << "     line = " << node.line() << std::endl;
-
-  if(node.has_content())
+  //If this is a text node:
+  const xmlpp::TextNode* nodeContent = dynamic_cast<const xmlpp::TextNode*>(&node);
+  if(nodeContent)
   {
     print_indentation(indentation);
-    std::cout << "content = " << node.content() << std::endl;
+    std::cout << "content = " << nodeContent->get_content() << std::endl;
   }
-
-  //Print attributes:
-  xmlpp::Node::AttributeList attributes = node.attributes();
-  for(xmlpp::Node::AttributeList::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
+  else
   {
-    const xmlpp::Attribute* attribute = *iter;
+    //A normal node:
     print_indentation(indentation);
-    std::cout << "  Attribute " << attribute->name() << " = " << attribute->value() << std::endl;
+    std::cout << "Node name = " << node.name() << std::endl;
   }
 
-  //Recurse through child nodes:
-  xmlpp::Node::NodeList list = node.children();
-  for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
+  print_indentation(indentation);
+  std::cout << "     line = " << node.line() << std::endl;
+
+  if(!nodeContent)
   {
-    print_node(*(*iter), indentation + 2); //recursive
+    //Print attributes:
+    xmlpp::Node::AttributeList attributes = node.attributes();
+    for(xmlpp::Node::AttributeList::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
+    {
+      const xmlpp::Attribute* attribute = *iter;
+      print_indentation(indentation);
+      std::cout << "  Attribute " << attribute->name() << " = " << attribute->value() << std::endl;
+    }
+
+    //Recurse through child nodes:
+    xmlpp::Node::NodeList list = node.children();
+    for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
+    {
+      print_node(*(*iter), indentation + 2); //recursive
+    }
   }
 }
 
Index: libxml++/libxml++.h
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/libxml++.h,v
retrieving revision 1.8
diff -u -p -r1.8 libxml++.h
--- libxml++/libxml++.h	17 Dec 2002 15:22:43 -0000	1.8
+++ libxml++/libxml++.h	17 Dec 2002 16:55:05 -0000
@@ -12,6 +12,7 @@
 #include <libxml++/parsers/domparser.h>
 #include <libxml++/parsers/saxparser.h>
 #include <libxml++/nodes/node.h>
+#include <libxml++/nodes/textnode.h>
 #include <libxml++/attribute.h>
 
 #endif //__LIBXMLCPP_H
Index: libxml++/nodes/node.cc
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/node.cc,v
retrieving revision 1.1
diff -u -p -r1.1 node.cc
--- libxml++/nodes/node.cc	17 Dec 2002 15:22:45 -0000	1.1
+++ libxml++/nodes/node.cc	17 Dec 2002 16:55:05 -0000
@@ -5,7 +5,9 @@
  */
 
 #include <libxml++/nodes/node.h>
+#include <libxml++/nodes/textnode.h>
 #include <libxml++/exceptions/internal_error.h>
+#include <iostream>
 
 namespace xmlpp {
 
@@ -25,16 +27,9 @@ Node::Node(const std::string& name, int 
     _initialized = true;
 }
 
-Node::Node(const std::string& name, const std::string& content)
- : _name(std::string()), _content(content), _line(0) {
-  _initialized = true;
-}
-
 Node::Node(const Node* from)
 : _initialized(false), _name(from->name()), _line(from->line())
 {
-  set_content(from->_content);
-
   for(AttributeList::const_iterator curattr = from->attributes().begin();
 	  curattr != from->attributes().end();
 	  ++curattr)
@@ -46,6 +41,7 @@ Node::Node(const Node* from)
 	  curnode != from->children().end();
 	  ++curnode)
   {
+    //TODO: Create the appropriate type:
     add_child(new Node(*curnode));
   }
 
@@ -59,9 +55,6 @@ Node::Node(xmlNodePtr node)
 
   _line = XML_GET_LINE(node);
 
-  if(XML_GET_CONTENT(node))
-	  set_content((char*) XML_GET_CONTENT(node));
-
   for(xmlAttrPtr attr = node->properties;
 		  attr;
 		  attr = attr->next)
@@ -73,7 +66,14 @@ Node::Node(xmlNodePtr node)
 		  child;
 		  child = child->next)
   {
-	  add_child(new Node(child));
+    Node* pChild = 0;
+    
+    if(child->type == XML_TEXT_NODE)
+      pChild = new TextNode(child);
+    else
+      pChild = new Node(child);
+    
+	  add_child(pChild);
   }
 }
 
@@ -95,11 +95,6 @@ Node::~Node() {
   }
 }
 
-void Node::set_content(const std::string& content)
-{
-  _content = content;
-}
-
 Node::NodeList Node::children(const std::string& name)
 {
   if(name.empty())
@@ -136,12 +131,11 @@ Node* Node::add_child(Node* node) {
   return node;
 }
 
-Node* Node::add_content(const std::string& content) {
-  Node* tmp;
-
-  tmp = new Node(std::string(), content);
+TextNode* Node::add_content(const std::string& content)
+{
+  TextNode* tmp = new TextNode(std::string(), content);
 
-  return add_child(tmp);
+  return static_cast<TextNode*>(add_child(tmp));
 }
 
 void Node::remove_child(Node* node)
@@ -229,26 +223,32 @@ int Node::line() const
 
 bool Node::has_content() const
 {
-  return !(content().empty());
+  return get_child_content() != 0;
 }
 
-const std::string& Node::content() const
+const TextNode* Node::get_child_content() const
 {
-  if(!_content.empty())
-    return _content;
+  const NodeList& listNodes = children("text");
+  if(listNodes.empty())
+    return 0;
   else
   {
-    const NodeList& listNodes = children("text");
-    if(listNodes.empty())
-      return _content; //Which will be empty. We could return "" but this would break because we return a const std::string&. I wish we didn't. murrayc.
-    else
-    {
-      Node* nodeContent = *(listNodes.begin());
-      return nodeContent->content();
-    }
+    const Node* nodeContent = *(listNodes.begin());
+    return static_cast<const TextNode*>(nodeContent);
   }
 }
 
+TextNode* Node::get_child_content()
+{
+  NodeList listNodes = children("text");
+  if(listNodes.empty())
+    return 0;
+  else
+  {
+    Node* nodeContent = *(listNodes.begin());
+    return static_cast<TextNode*>(nodeContent);
+  }
+}
 
 const Node::AttributeList& Node::attributes() const
 {
@@ -261,13 +261,15 @@ const Attribute* Node::attribute(const s
 }
 
 void Node::write(xmlDocPtr doc, xmlNodePtr parent) const
-{
+{ 
   xmlNodePtr node = 0;
 
   if(!parent)
     node = doc->children = xmlNewDocNode(doc, NULL /* ns */, (xmlChar*) name().c_str(), 0);
   else
   {
+    //std::cout << "Node::write: xmlNewChild(): " << _name << std::endl;
+
     node = xmlNewChild(parent, NULL /* ns */, (xmlChar*) name().c_str(), 0);
     if(!node)
       throw internal_error("xmlNewChild() returned NULL");
@@ -275,11 +277,6 @@ void Node::write(xmlDocPtr doc, xmlNodeP
 
   if(node)
   {
-    if( !_content.empty() )
-    {
-      xmlNodeSetContent(node, (const xmlChar*)_content.c_str());
-    }
-
     //Add the attributes:
     for(AttributeList::const_iterator iter = _attributes_list.begin();
       iter != _attributes_list.end();
@@ -295,10 +292,21 @@ void Node::write(xmlDocPtr doc, xmlNodeP
        ++iter)
     {
       //Add the nodes to this parent node:
+
+      //write() is a virtual function, implemented differently for each node type.
       (*iter)->write(doc, node);
     }
   }
 
+}
+
+void Node::set_child_content(const std::string& content)
+{
+  TextNode* node = get_child_content();
+  if(!node)
+    node = add_content(content);
+  else
+    node->set_content(content);
 }
 
 } // namespace xmlpp
Index: libxml++/nodes/node.h
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/node.h,v
retrieving revision 1.1
diff -u -p -r1.1 node.h
--- libxml++/nodes/node.h	17 Dec 2002 15:22:45 -0000	1.1
+++ libxml++/nodes/node.h	17 Dec 2002 16:55:05 -0000
@@ -15,6 +15,8 @@
 
 namespace xmlpp {
 
+class TextNode;
+
 /** Represents XML Nodes.
  * You should never new or delete Nodes. The Parser will create and manage them for you.
  */
@@ -27,7 +29,6 @@ public:
 
   explicit Node(const std::string& name);
   Node(const std::string& name, int line);
-  Node(const std::string& name, const std::string& content);
   explicit Node(const Node* from);
   explicit Node(xmlNodePtr node);
   ~Node();
@@ -37,15 +38,18 @@ public:
   int line() const;
 
   bool has_content() const;
-  const std::string& content() const;
-  void set_content(const std::string& content);
-
+  
+  TextNode* get_child_content();
+  const TextNode* get_child_content() const;
+  TextNode* add_content(const std::string& name = std::string());
+  void set_child_content(const std::string& content);
+  
   NodeList children(const std::string& name = std::string());
   const NodeList children(const std::string& name = std::string()) const;
 
   Node* add_child(const std::string& name);
   Node* add_child(Node* node);
-  Node* add_content(const std::string& name = std::string());
+
 
   /** Remove the child node.
    * @param node The child node to remove. This Node will be deleted and therefore unusable after calling this method.
@@ -62,7 +66,7 @@ public:
    */
   void remove_attribute(const std::string& name);
 
-  void write(xmlDocPtr doc, xmlNodePtr parent = 0) const;
+  virtual void write(xmlDocPtr doc, xmlNodePtr parent = 0) const;
 
 private:
   Attribute* add_attribute(xmlAttrPtr attr);


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