[libxml++] node iterators
- From: Christophe de VIENNE <cdevienne alphacent com>
- To: libxmlplusplus-general lists sourceforge net
- Subject: [libxml++] node iterators
- Date: Thu, 22 May 2003 16:13:36 +0200
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
I'd like to discuss the subject of iterators inside libxml++.
We did already several month ago but this did not went to any
conclusion/decision.
To illustrate how I would see things, I made a small patch which implements a
class NodeIterator, which permit to iterate through the children of a node.
I think it implements correctly the following concept from STL:
- - Bidirectionnal Iterator.
- - Input Iterator.
It's quite trivial to use. Exemple to iterate a complete tree:
void do_something(xmlpp::Node & node) {
for( xmlpp::NodeIterator i = node.children_node(),
i_end = xmlpp::NodeIterator();
i != i_end;
++i)
{
std::cout << i->get_name() << std::endl;
do_something(*i);
}
};
One interesting thing is that is nodes are added/removed at the same tree
level, the iterator will stay valid (unless we suppress the pointed node of
course).
A const iterator is needed, but I did not do it yet.
I'd like to have comments/suggestions at least on:
- Does this iterator have the behavior any C++ developer would expect ?
- The class name. Should it be Node::iterator ? I'm not sure about that since
it would suggest Node is a container, which is not right I think.
- Does Node::children_begin() sounds right ? It seems to me that yes.
- Should we drop Node::get_children ? simply keep it ?
- Should we wait for the next major version to add this feature ?
The patch (which concerns only the 'nodes' directory) also includes a little
change : it uses pimpl idiom so that no libxml header is included by the
libxml++ user.
I think it would be a good thing to do this for the whole library, and it's
not much work. What do you think about it ?
Comments welcome
Cheers
Christophe
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
iD8DBQE+zNsQB+sU3TyOQjARAmhAAJ0f0HMTVUiJv9SrCoikIeprPYaJ+QCgxVgI
1dUmvUzJqx3rW09uoFJYfgE=
=GMZg
-----END PGP SIGNATURE-----
/* node.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.
*/
#include "nodeiterator.h"
#include "node.h"
#include "libxml++/exceptions/internal_error.h"
#include <libxml/tree.h>
namespace xmlpp
{
NodeIterator::NodeIterator()
: _impl(NULL)
{
}
NodeIterator::NodeIterator(
struct _xmlNode * p)
: _impl(p)
{
}
NodeIterator NodeIterator::operator++(int)
{
NodeIterator previous(*this);
next();
return previous;
}
NodeIterator & NodeIterator::operator++()
{
next();
return *this;
}
NodeIterator NodeIterator::operator--(int)
{
NodeIterator previous(*this);
prev();
return previous;
}
NodeIterator & NodeIterator::operator--()
{
prev();
return *this;
}
Node & NodeIterator::operator*() const
{
return *get();
}
Node * NodeIterator::operator->() const
{
return get();
}
bool NodeIterator::operator==(const NodeIterator & it) const
{
return _impl == it._impl;
}
bool NodeIterator::operator!=(const NodeIterator & it) const
{
return _impl != it._impl;
}
NodeIterator::operator bool () const
{
return _impl != NULL;
}
void NodeIterator::next()
{
if(_impl != NULL)
{
_impl = _impl->next;
}
}
void NodeIterator::prev()
{
if(_impl->prev != NULL)
{
_impl = _impl->prev;
}
}
Node * NodeIterator::get() const
{
if(_impl == NULL)
{
throw xmlpp::internal_error("");
}
return static_cast<Node*>( _impl->_private );
}
};
/* nodeiterator.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_NODES_NODEITERATOR_H
#define __LIBXMLPP_NODES_NODEITERATOR_H
extern "C" {
struct _xmlNode;
};
namespace xmlpp
{
class Node;
class NodeIterator
{
private:
struct _xmlNode * _impl;
public:
// compiler generate copy-constructor and destructor
NodeIterator();
NodeIterator(struct _xmlNode * p);
NodeIterator operator++(int); // postincrement
NodeIterator & operator++(); // preincrement
NodeIterator operator--(int);
NodeIterator & operator--();
Node & operator*() const;
Node * operator->() const;
bool operator==(const NodeIterator & it) const;
bool operator!=(const NodeIterator & it) const;
operator bool () const;
private:
void next();
void prev();
Node * get() const;
};
};
#endif // __LIBXMLPP_NODES_NODEITERATOR_H
? .deps
? .libs
? Makefile
? Makefile.in
? commentnode.lo
? element.lo
? libnodes.la
? node.lo
? nodeiterator.cc
? nodeiterator.h
? nodeiterator.lo
? nodeiterator.patch
? textnode.lo
Index: Makefile.am
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/Makefile.am,v
retrieving revision 1.1
diff -u -u -r1.1 Makefile.am
--- Makefile.am 18 Dec 2002 16:01:26 -0000 1.1
+++ Makefile.am 22 May 2003 14:00:46 -0000
@@ -1,7 +1,7 @@
INCLUDES = -I$(top_srcdir) @LIBXML_CFLAGS@
-h_sources_public = node.h element.h commentnode.h textnode.h
-cc_sources = node.cc element.cc commentnode.cc textnode.cc
+h_sources_public = node.h element.h commentnode.h textnode.h nodeiterator.h
+cc_sources = node.cc element.cc commentnode.cc textnode.cc nodeiterator.cc
noinst_LTLIBRARIES = libnodes.la
Index: commentnode.cc
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/commentnode.cc,v
retrieving revision 1.4
diff -u -u -r1.4 commentnode.cc
--- commentnode.cc 7 Feb 2003 10:41:25 -0000 1.4
+++ commentnode.cc 22 May 2003 14:00:46 -0000
@@ -7,6 +7,8 @@
#include <libxml++/nodes/commentnode.h>
#include <libxml++/exceptions/internal_error.h>
+#include <libxml/tree.h>
+
namespace xmlpp
{
Index: commentnode.h
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/commentnode.h,v
retrieving revision 1.4
diff -u -u -r1.4 commentnode.h
--- commentnode.h 7 Feb 2003 10:41:25 -0000 1.4
+++ commentnode.h 22 May 2003 14:00:46 -0000
@@ -17,7 +17,7 @@
class CommentNode : public Node
{
public:
- explicit CommentNode(xmlNode* node);
+ explicit CommentNode(struct _xmlNode * node);
virtual ~CommentNode();
std::string get_content() const;
Index: node.cc
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/node.cc,v
retrieving revision 1.21
diff -u -u -r1.21 node.cc
--- node.cc 22 May 2003 09:57:41 -0000 1.21
+++ node.cc 22 May 2003 14:00:46 -0000
@@ -5,6 +5,7 @@
*/
#include <libxml/xpath.h>
+#include <libxml/tree.h>
#include <libxml++/nodes/node.h>
#include <libxml++/nodes/element.h>
@@ -25,6 +26,11 @@
Node::~Node()
{}
+
+NodeIterator Node::children_begin()
+{
+ return NodeIterator(_impl->children);
+}
Node::NodeList Node::get_children(const std::string& name)
{
Index: node.h
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/node.h,v
retrieving revision 1.18
diff -u -u -r1.18 node.h
--- node.h 22 May 2003 09:57:41 -0000 1.18
+++ node.h 22 May 2003 14:00:46 -0000
@@ -7,13 +7,18 @@
#ifndef __LIBXMLPP_NODES_NODE_H
#define __LIBXMLPP_NODES_NODE_H
+#include <libxml++/nodes/nodeiterator.h>
#include <libxml++/noncopyable.h>
+
#include <string>
#include <list>
#include <map>
#include <vector>
-#include <libxml/tree.h>
+
+extern "C" {
+ struct _xmlNode;
+};
namespace xmlpp {
@@ -33,7 +38,7 @@
typedef std::list<Node*> NodeList;
typedef std::list<Attribute*> AttributeList;
- explicit Node(xmlNode* node);
+ explicit Node(struct _xmlNode * node);
virtual ~Node();
std::string get_name() const;
@@ -41,6 +46,7 @@
int get_line() const;;
+ NodeIterator children_begin();
NodeList get_children(const std::string& name = std::string());
const NodeList get_children(const std::string& name = std::string()) const;
@@ -59,13 +65,13 @@
NodeSet find(const std::string& xpath) const;
///Access the underlying libxml implementation.
- xmlNode* cobj();
+ struct _xmlNode* cobj();
///Access the underlying libxml implementation.
- const xmlNode* cobj() const;
+ struct _xmlNode const * cobj() const;
private:
- xmlNode* _impl;
+ struct _xmlNode* _impl;
};
} // namespace xmlpp
Index: textnode.cc
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/textnode.cc,v
retrieving revision 1.5
diff -u -u -r1.5 textnode.cc
--- textnode.cc 7 Feb 2003 10:41:25 -0000 1.5
+++ textnode.cc 22 May 2003 14:00:46 -0000
@@ -6,7 +6,8 @@
#include <libxml++/nodes/textnode.h>
#include <libxml++/exceptions/internal_error.h>
-#include <iostream>
+
+#include <libxml/tree.h>
namespace xmlpp
{
Index: textnode.h
===================================================================
RCS file: /cvsroot/libxmlplusplus/libxml++/libxml++/nodes/textnode.h,v
retrieving revision 1.5
diff -u -u -r1.5 textnode.h
--- textnode.h 7 Feb 2003 10:41:25 -0000 1.5
+++ textnode.h 22 May 2003 14:00:46 -0000
@@ -15,7 +15,7 @@
class TextNode : public Node
{
public:
- explicit TextNode(xmlNode* node);
+ explicit TextNode(struct _xmlNode* node);
virtual ~TextNode();
std::string get_content() const;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]