commited early version of a python binding for private use only ATM Daniel

* python/generator.py python/libxml.c python/libxml.py
  python/libxml_wrap.h: commited early version of a python binding
  for private use only ATM
Daniel
diff --git a/python/generator.py b/python/generator.py
new file mode 100755
index 0000000..2942854
--- /dev/null
+++ b/python/generator.py
@@ -0,0 +1,284 @@
+#!/usr/bin/python -u
+#
+# generate python wrappers from the XML API description
+#
+
+functions = {}
+
+import os
+import xmllib
+try:
+    import sgmlop
+except ImportError:
+    sgmlop = None # accelerator not available
+
+debug = 0
+
+if sgmlop:
+    class FastParser:
+	"""sgmlop based XML parser.  this is typically 15x faster
+	   than SlowParser..."""
+
+	def __init__(self, target):
+
+	    # setup callbacks
+	    self.finish_starttag = target.start
+	    self.finish_endtag = target.end
+	    self.handle_data = target.data
+
+	    # activate parser
+	    self.parser = sgmlop.XMLParser()
+	    self.parser.register(self)
+	    self.feed = self.parser.feed
+	    self.entity = {
+		"amp": "&", "gt": ">", "lt": "<",
+		"apos": "'", "quot": '"'
+		}
+
+	def close(self):
+	    try:
+		self.parser.close()
+	    finally:
+		self.parser = self.feed = None # nuke circular reference
+
+	def handle_entityref(self, entity):
+	    # <string> entity
+	    try:
+		self.handle_data(self.entity[entity])
+	    except KeyError:
+		self.handle_data("&%s;" % entity)
+
+else:
+    FastParser = None
+
+
+class SlowParser(xmllib.XMLParser):
+    """slow but safe standard parser, based on the XML parser in
+       Python's standard library."""
+
+    def __init__(self, target):
+	self.unknown_starttag = target.start
+	self.handle_data = target.data
+	self.unknown_endtag = target.end
+	xmllib.XMLParser.__init__(self)
+
+def getparser(target = None):
+    # get the fastest available parser, and attach it to an
+    # unmarshalling object.  return both objects.
+    if target == None:
+	target = docParser()
+    if FastParser:
+	return FastParser(target), target
+    return SlowParser(target), target
+
+class docParser:
+    def __init__(self):
+        self._methodname = None
+	self._data = []
+	self.in_function = 0
+
+    def close(self):
+        if debug:
+	    print "close"
+
+    def getmethodname(self):
+        return self._methodname
+
+    def data(self, text):
+        if debug:
+	    print "data %s" % text
+        self._data.append(text)
+
+    def start(self, tag, attrs):
+        if debug:
+	    print "start %s, %s" % (tag, attrs)
+	if tag == 'function':
+	    self._data = []
+	    self.in_function = 1
+	    self.function = None
+	    self.function_args = []
+	    self.function_descr = None
+	    self.function_return = None
+	    self.function_file = None
+	    if attrs.has_key('name'):
+	        self.function = attrs['name']
+	    if attrs.has_key('file'):
+	        self.function_file = attrs['file']
+	elif tag == 'info':
+	    self._data = []
+	elif tag == 'arg':
+	    if self.in_function == 1:
+	        self.function_arg_name = None
+	        self.function_arg_type = None
+	        self.function_arg_info = None
+		if attrs.has_key('name'):
+		    self.function_arg_name = attrs['name']
+		if attrs.has_key('type'):
+		    self.function_arg_type = attrs['type']
+		if attrs.has_key('info'):
+		    self.function_arg_info = attrs['info']
+	elif tag == 'return':
+	    if self.in_function == 1:
+	        self.function_return_type = None
+	        self.function_return_info = None
+		if attrs.has_key('type'):
+		    self.function_return_type = attrs['type']
+		if attrs.has_key('info'):
+		    self.function_return_info = attrs['info']
+
+
+    def end(self, tag):
+        if debug:
+	    print "end %s" % tag
+	if tag == 'function':
+	    if self.function != None:
+	        function(self.function, self.function_descr,
+		         self.function_return, self.function_args,
+			 self.function_file)
+		self.in_function = 0
+	elif tag == 'arg':
+	    if self.in_function == 1:
+	        self.function_args.append([self.function_arg_name,
+		                           self.function_arg_type,
+					   self.function_arg_info])
+	elif tag == 'return':
+	    if self.in_function == 1:
+	        self.function_return = [self.function_return_type,
+		                        self.function_return_info]
+	elif tag == 'info':
+	    str = ''
+	    for c in self._data:
+		str = str + c
+	    if self.in_function == 1:
+	        self.function_descr = str
+	        
+	        
+def function(name, desc, ret, args, file):
+    global functions
+
+    functions[name] = (desc, ret, args, file)
+
+skipped_modules = {
+    'xmlmemory': None,
+}
+py_types = {
+    'void': (None, None, None),
+    'int':  ('i', None, "int"),
+    'xmlChar':  ('c', None, "int"),
+    'char *':  ('s', None, "charPtr"),
+    'const char *':  ('s', None, "charPtr"),
+    'xmlChar *':  ('s', None, "xmlCharPtr"),
+    'const xmlChar *':  ('s', None, "xmlCharPtr"),
+}
+
+unknown_types = {}
+
+def print_function_wrapper(name, output):
+    global py_types
+    global unknown_types
+    global functions
+    global skipped_modules
+
+    try:
+	(desc, ret, args, file) = functions[name]
+    except:
+        print "failed to get function %s infos"
+        return
+
+    if skipped_modules.has_key(file):
+        return 0
+
+    c_call = "";
+    format=""
+    format_args=""
+    c_args=""
+    c_return=""
+    for arg in args:
+        c_args = c_args + "    %s %s;\n" % (arg[1], arg[0])
+	if py_types.has_key(arg[1]):
+	    (f, t, n) = py_types[arg[1]]
+	    if f != None:
+		format = format + f
+	    if t != None:
+	        format_args = format_args + ", &%s" % (t)
+	    format_args = format_args + ", &%s" % (arg[0])
+	    if c_call != "":
+	        c_call = c_call + ", ";
+	    c_call = c_call + "%s" % (arg[0])
+	else:
+	    if unknown_types.has_key(arg[1]):
+	        lst = unknown_types[arg[1]]
+		lst.append(name)
+	    else:
+	        unknown_types[arg[1]] = [name]
+	    return -1
+    if format != "":
+        format = format + ":%s" % (name)
+
+    if ret[0] == 'void':
+        c_call = "\n    %s(%s);\n" % (name, c_call);
+	ret_convert = "    Py_INCREF(Py_None);\n    return(Py_None);\n"
+    elif py_types.has_key(ret[0]):
+	(f, t, n) = py_types[ret[0]]
+	c_return = "    %s c_retval;\n" % (ret[0])
+        c_call = "\n    c_retval = %s(%s);\n" % (name, c_call);
+	ret_convert = "    py_retval = libxml_%sWrap(c_retval);\n    return(py_retval);\n" % (n)
+    else:
+	if unknown_types.has_key(ret[0]):
+	    lst = unknown_types[ret[0]]
+	    lst.append(name)
+	else:
+	    unknown_types[ret[0]] = [name]
+	return -1
+
+    output.write("PyObject *\n")
+    output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name))
+    if ret[0] != 'void':
+	output.write("    PyObject *py_retval;\n")
+    if c_return != "":
+	output.write(c_return)
+    if c_args != "":
+	output.write(c_args)
+    if format != "":
+	output.write("\n    if (!PyArg_ParseTuple(args, \"%s\"%s))\n" %
+	             (format, format_args))
+	output.write("        return(NULL);\n")
+                                                              
+    output.write(c_call)
+    output.write(ret_convert)
+    output.write("}\n\n")
+    return 1
+
+try:
+    f = open("libxml2-api.xml")
+    data = f.read()
+    (parser, target)  = getparser()
+    parser.feed(data)
+    parser.close()
+except IOError, msg:
+    print file, ":", msg
+
+print "Found %d functions in libxml2-api.xml" % (len(functions.keys()))
+nb_wrap = 0
+failed = 0
+skipped = 0
+
+wrapper = open("libxml2-py.c", "w")
+wrapper.write("/* Generated */\n\n")
+wrapper.write("#include <Python.h>\n")
+wrapper.write("#include <libxml/tree.h>\n")
+wrapper.write("#include \"libxml_wrap.h\"\n")
+wrapper.write("#include \"libxml2-py.h\"\n\n")
+for function in functions.keys():
+    ret = print_function_wrapper(function, wrapper)
+    if ret < 0:
+        failed = failed + 1
+    if ret == 1:
+        nb_wrap = nb_wrap + 1
+    if ret == 0:
+        skipped = skipped + 1
+wrapper.close()
+
+print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
+							  failed, skipped);
+print "Missing type converters: %s" % (unknown_types.keys())
diff --git a/python/libxml.c b/python/libxml.c
new file mode 100644
index 0000000..13423f5
--- /dev/null
+++ b/python/libxml.c
@@ -0,0 +1,619 @@
+#include <Python.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include "libxml_wrap.h"
+
+/* #define DEBUG */
+
+/************************************************************************
+ *									*
+ *			Per type specific glue				*
+ *									*
+ ************************************************************************/
+PyObject *
+libxml_intWrap(int val) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_intWrap: val = %d\n", val);
+#endif
+    ret = PyInt_FromLong((long) val);
+    return(ret);
+}
+
+PyObject *
+libxml_charPtrWrap(const char *str) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlcharPtrWrap: str = %s\n", str);
+#endif
+    if (str == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyString_FromString(str);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlCharPtrWrap(const xmlChar *str) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlCharPtrWrap: str = %s\n", str);
+#endif
+    if (str == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyString_FromString(str);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlDocPtrWrap(xmlDocPtr doc) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlDocPtrWrap: doc = %p\n", doc);
+#endif
+    if (doc == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyCObject_FromVoidPtrAndDesc((void *) doc, "xmlDocPtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlNodePtrWrap(xmlNodePtr node) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlNodePtrWrap: node = %p\n", node);
+#endif
+    if (node == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) node, "xmlNodePtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlAttrPtrWrap(xmlAttrPtr attr) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlNodePtrWrap: attr = %p\n", attr);
+#endif
+    if (attr == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttrPtr", NULL);
+    return(ret);
+}
+
+#define PyxmlNode_Get(v) (((PyxmlNode_Object *)(v))->obj)
+
+typedef struct {
+    PyObject_HEAD
+    xmlNodePtr obj;
+} PyxmlNode_Object;
+
+static void
+PyxmlNode_dealloc(PyxmlNode_Object * self)
+{
+    printf("TODO PyxmlNode_dealloc\n");
+    PyMem_DEL(self);
+}
+
+static int
+PyxmlNode_compare(PyxmlNode_Object * self, PyxmlNode_Object * v)
+{
+    if (self->obj == v->obj)
+        return 0;
+    if (self->obj > v->obj)
+        return -1;
+    return 1;
+}
+
+static long
+PyxmlNode_hash(PyxmlNode_Object * self)
+{
+    return (long) self->obj;
+}
+
+static PyObject *
+PyxmlNode_repr(PyxmlNode_Object * self)
+{
+    char buf[100];
+
+    sprintf(buf, "<xmlNode of type %d at %lx>",
+            PyxmlNode_Get(self)->type,
+            (long) PyxmlNode_Get(self));
+    return PyString_FromString(buf);
+}
+
+static char PyxmlNode_Type__doc__[] = "This is the type of libxml Nodes";
+
+static PyTypeObject PyxmlNode_Type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+        0,                      /*ob_size */
+    "xmlNode",                  /*tp_name */
+    sizeof(PyxmlNode_Object),   /*tp_basicsize */
+    0,                          /*tp_itemsize */
+    (destructor) PyxmlNode_dealloc,/*tp_dealloc */
+    (printfunc) 0,              /*tp_print */
+    (getattrfunc) 0,            /*tp_getattr */
+    (setattrfunc) 0,            /*tp_setattr */
+    (cmpfunc) PyxmlNode_compare,/*tp_compare */
+    (reprfunc) PyxmlNode_repr,  /*tp_repr */
+    0,                          /*tp_as_number */
+    0,                          /*tp_as_sequence */
+    0,                          /*tp_as_mapping */
+    (hashfunc) PyxmlNode_hash,  /*tp_hash */
+    (ternaryfunc) 0,            /*tp_call */
+    (reprfunc) 0,               /*tp_str */
+    0L, 0L, 0L, 0L,
+    PyxmlNode_Type__doc__
+};
+
+/************************************************************************
+ *									*
+ *			Global properties access			*
+ *									*
+ ************************************************************************/
+static PyObject *
+libxml_name(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    const xmlChar *res;
+
+    if (!PyArg_ParseTuple(args, "O:name", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_name: cur = %p type %d\n", cur, cur->type);
+#endif
+
+    switch(cur->type) {
+	case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	case XML_HTML_DOCUMENT_NODE: {
+	    xmlDocPtr doc = (xmlDocPtr) cur;
+	    res = doc->URL;
+	    break;
+	}
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = attr->name;
+	    break;
+	}
+	case XML_NAMESPACE_DECL: {
+	    xmlNsPtr ns = (xmlNsPtr) cur;
+	    res = ns->prefix;
+	    break;
+	}
+	default:
+	    res = cur->name;
+	    break;
+    }
+    resultobj = libxml_xmlCharPtrWrap(res);
+
+    return resultobj;
+}
+
+static PyObject *
+libxml_doc(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    xmlDocPtr res;
+
+    if (!PyArg_ParseTuple(args, "O:doc", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_doc: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+	case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	case XML_HTML_DOCUMENT_NODE:
+	    res = NULL;
+	    break;
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = attr->doc;
+	    break;
+	}
+	case XML_NAMESPACE_DECL:
+	    res = NULL;
+	    break;
+	default:
+	    res = cur->doc;
+	    break;
+    }
+    resultobj = libxml_xmlDocPtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_properties(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur = NULL;
+    xmlAttrPtr res;
+
+    if (!PyArg_ParseTuple(args, "O:properties", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+    if (cur->type == XML_ELEMENT_NODE)
+	res = cur->properties;
+    else
+	res = NULL;
+    resultobj = libxml_xmlAttrPtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_next(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    xmlNodePtr res;
+
+    if (!PyArg_ParseTuple(args, "O:next", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_next: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+	case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	case XML_HTML_DOCUMENT_NODE:
+	    res = NULL;
+	    break;
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = (xmlNodePtr) attr->next;
+	    break;
+	}
+	case XML_NAMESPACE_DECL: {
+	    xmlNsPtr ns = (xmlNsPtr) cur;
+	    res = (xmlNodePtr) ns->next;
+	    break;
+	}
+	default:
+	    res = cur->next;
+	    break;
+
+    }
+    resultobj = libxml_xmlNodePtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_prev(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    xmlNodePtr res;
+
+    if (!PyArg_ParseTuple(args, "O:prev", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_prev: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+	case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	case XML_HTML_DOCUMENT_NODE:
+	    res = NULL;
+	    break;
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = (xmlNodePtr) attr->next;
+	}
+	case XML_NAMESPACE_DECL:
+	    res = NULL;
+	    break;
+	default:
+	    res = cur->next;
+	    break;
+    }
+    resultobj = libxml_xmlNodePtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_children(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    xmlNodePtr res;
+
+    if (!PyArg_ParseTuple(args, "O:children", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_children: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+	case XML_ELEMENT_NODE:
+	case XML_ENTITY_REF_NODE:
+	case XML_ENTITY_NODE:
+	case XML_PI_NODE:
+	case XML_COMMENT_NODE:
+	case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	case XML_HTML_DOCUMENT_NODE:
+	case XML_DTD_NODE:
+	    res = cur->children;
+	    break;
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = attr->children;
+	    break;
+	}
+	default:
+	    res = NULL;
+	    break;
+    }
+    resultobj = libxml_xmlNodePtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_last(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    xmlNodePtr res;
+
+    if (!PyArg_ParseTuple(args, "O:last", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_last: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+	case XML_ELEMENT_NODE:
+	case XML_ENTITY_REF_NODE:
+	case XML_ENTITY_NODE:
+	case XML_PI_NODE:
+	case XML_COMMENT_NODE:
+	case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	case XML_HTML_DOCUMENT_NODE:
+	case XML_DTD_NODE:
+	    res = cur->last;
+	    break;
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = attr->last;
+	}
+	default:
+	    res = NULL;
+	    break;
+    }
+    resultobj = libxml_xmlNodePtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_parent(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    xmlNodePtr res;
+
+    if (!PyArg_ParseTuple(args, "O:parent", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_parent: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+	case XML_DOCUMENT_NODE:
+	case XML_HTML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	    res = NULL;
+	    break;
+	case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    res = attr->parent;
+	}
+	case XML_ENTITY_DECL:
+	case XML_NAMESPACE_DECL:
+	case XML_XINCLUDE_START:
+	case XML_XINCLUDE_END:
+	    res = NULL;
+	    break;
+	default:
+	    res = cur->parent;
+	    break;
+    }
+    resultobj = libxml_xmlNodePtrWrap(res);
+    return resultobj;
+}
+
+static PyObject *
+libxml_type(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj, *obj;
+    xmlNodePtr cur;
+    const xmlChar *res;
+
+    if (!PyArg_ParseTuple(args, "O:last", &obj))
+        return NULL;
+    cur = PyxmlNode_Get(obj);
+
+#ifdef DEBUG
+    printf("libxml_type: cur = %p\n", cur);
+#endif
+
+    switch(cur->type) {
+        case XML_ELEMENT_NODE:
+	    res = (const xmlChar *) "element"; break;
+        case XML_ATTRIBUTE_NODE:
+	    res = (const xmlChar *) "attribute"; break;
+        case XML_TEXT_NODE:
+	    res = (const xmlChar *) "text"; break;
+        case XML_CDATA_SECTION_NODE:
+	    res = (const xmlChar *) "cdata"; break;
+        case XML_ENTITY_REF_NODE:
+	    res = (const xmlChar *) "entity_ref"; break;
+        case XML_ENTITY_NODE:
+	    res = (const xmlChar *) "entity"; break;
+        case XML_PI_NODE:
+	    res = (const xmlChar *) "pi"; break;
+        case XML_COMMENT_NODE:
+	    res = (const xmlChar *) "comment"; break;
+        case XML_DOCUMENT_NODE:
+	    res = (const xmlChar *) "document_xml"; break;
+        case XML_DOCUMENT_TYPE_NODE:
+	    res = (const xmlChar *) "doctype"; break;
+        case XML_DOCUMENT_FRAG_NODE:
+	    res = (const xmlChar *) "fragment"; break;
+        case XML_NOTATION_NODE:
+	    res = (const xmlChar *) "notation"; break;
+        case XML_HTML_DOCUMENT_NODE:
+	    res = (const xmlChar *) "document_html"; break;
+        case XML_DTD_NODE:
+	    res = (const xmlChar *) "dtd"; break;
+        case XML_ELEMENT_DECL:
+	    res = (const xmlChar *) "elem_decl"; break;
+        case XML_ATTRIBUTE_DECL:
+	    res = (const xmlChar *) "attribute_decl"; break;
+        case XML_ENTITY_DECL:
+	    res = (const xmlChar *) "entity_decl"; break;
+        case XML_NAMESPACE_DECL:
+	    res = (const xmlChar *) "namespace"; break;
+        case XML_XINCLUDE_START:
+	    res = (const xmlChar *) "xinclude_start"; break;
+        case XML_XINCLUDE_END:
+	    res = (const xmlChar *) "xinclude_end"; break;
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+	    res = (const xmlChar *) "document_docbook"; break;
+#endif
+    }
+#ifdef DEBUG
+    printf("libxml_type: cur = %p: %s\n", cur, res);
+#endif
+
+    resultobj = libxml_xmlCharPtrWrap(res);
+    return resultobj;
+}
+
+/************************************************************************
+ *									*
+ *			The interface raw code				*
+ *									*
+ ************************************************************************/
+static PyObject *
+libxml_parseFile(PyObject *self, PyObject *args)
+{
+    PyObject *resultobj;
+    char *arg0;
+    xmlDocPtr result;
+
+    if (!PyArg_ParseTuple(args, "s:parseFile", &arg0))
+        return NULL;
+#ifdef DEBUG
+    printf("libxml_parseFile: arg0 = %s\n", arg0);
+#endif
+    result = (xmlDocPtr )xmlParseFile((char const *)arg0);
+    resultobj = libxml_xmlDocPtrWrap(result);
+#ifdef DEBUG
+    printf("libxml_parseFile: resultobj = %p\n", resultobj);
+#endif
+    return resultobj;
+}
+
+static PyObject *
+libxml_freeDoc(PyObject *self, PyObject *args)
+{
+    xmlDocPtr doc;
+
+    if (!PyArg_ParseTuple(args, "O:freeDoc", &doc))
+        return NULL;
+    switch(doc->type) {
+	case XML_DOCUMENT_NODE:
+	case XML_HTML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+	case XML_DOCB_DOCUMENT_NODE:
+#endif
+	    xmlFreeDoc(doc);
+	    break;
+	default:
+	    break;
+    }
+    Py_INCREF(Py_None);
+    return(Py_None);
+}
+
+/************************************************************************
+ *									*
+ *			The registration stuff				*
+ *									*
+ ************************************************************************/
+static PyMethodDef libxmlMethods[] = {
+    { "parseFile", libxml_parseFile, METH_VARARGS },
+    { "freeDoc", libxml_freeDoc, METH_VARARGS },
+    { "name", libxml_name, METH_VARARGS },
+    { "children", libxml_children, METH_VARARGS },
+    { "properties", libxml_properties, METH_VARARGS },
+    { "last", libxml_last, METH_VARARGS },
+    { "prev", libxml_prev, METH_VARARGS },
+    { "next", libxml_next, METH_VARARGS },
+    { "parent", libxml_parent, METH_VARARGS },
+    { "type", libxml_type, METH_VARARGS },
+    { "doc", libxml_doc, METH_VARARGS }
+};
+
+void init_libxml(void) {
+    PyObject *m, *d;
+    m = Py_InitModule("_libxml", libxmlMethods);
+    d = PyModule_GetDict(m);
+    PyDict_SetItemString(d, "xmlNodeType", (PyObject *)&PyxmlNode_Type);
+}
+
diff --git a/python/libxml.py b/python/libxml.py
new file mode 100644
index 0000000..af96383
--- /dev/null
+++ b/python/libxml.py
@@ -0,0 +1,115 @@
+import _libxml
+
+class xmlNode:
+    def __init__(self, _obj=None):
+        if _obj != None: 
+	    self._o = _obj;
+	    return
+	self._o = None
+
+#    def __getattr__(self, attr):
+#	attrs = {
+#	'lower': _gtk.gtk_adjustment_get_lower,
+#	'upper': _gtk.gtk_adjustment_get_upper,
+#	'value': _gtk.gtk_adjustment_get_value,
+#	'step_increment': _gtk.gtk_adjustment_get_step_increment,
+#	'page_increment': _gtk.gtk_adjustment_get_page_increment,
+#	'page_size': _gtk.gtk_adjustment_get_page_size
+#	}
+#	if attrs.has_key(attr):
+#	    ret = attrs[attr](self._o)
+#	    if ret == None:
+#	        return None
+#	    return attrs[attr](self._o)
+    def __getattr__(self, attr):
+        if attr == "parent":
+	    ret = _libxml.parent(self._o)
+	    if ret == None:
+	        return None
+	    return xmlNode(_obj=ret)
+        elif attr == "properties":
+	    ret = _libxml.properties(self._o)
+	    if ret == None:
+	        return None
+	    return xmlNode(_obj=ret)
+	elif attr == "children":
+	    ret = _libxml.children(self._o)
+	    if ret == None:
+		return None
+	    return xmlNode(_obj=ret)
+	elif attr == "last":
+	    ret = _libxml.last(self._o)
+	    if ret == None:
+		return None
+	    return xmlNode(_obj=ret)
+	elif attr == "next":
+	    ret = _libxml.next(self._o)
+	    if ret == None:
+		return None
+	    return xmlNode(_obj=ret)
+	elif attr == "prev":
+	    ret = _libxml.prev(self._o)
+	    if ret == None:
+		return None
+	    return xmlNode(_obj=ret)
+	elif attr == "content":
+	    return self.content()
+	elif attr == "name":
+	    return _libxml.name(self._o)
+	elif attr == "type":
+	    return _libxml.type(self._o)
+	elif attr == "doc":
+	    ret = _libxml.doc(self._o)
+	    if ret == None:
+		return None
+	    return xmlDoc(_doc=ret)
+	raise AttributeError,attr
+
+	#
+	# Those are common attributes to nearly all type of nodes
+	#
+    def get_parent(self):
+	ret = _libxml.parent(self._o)
+	if ret == None:
+	    return None
+	return xmlNode(_obj=ret)
+    def get_children(self):
+	ret = _libxml.children(self._o)
+	if ret == None:
+	    return None
+	return xmlNode(_obj=ret)
+    def get_last(self):
+	ret = _libxml.last(self._o)
+	if ret == None:
+	    return None
+	return xmlNode(_obj=ret)
+    def get_next(self):
+	ret = _libxml.next(self._o)
+	if ret == None:
+	    return None
+	return xmlNode(_obj=ret)
+    def get_prev(self):
+	ret = _libxml.prev(self._o)
+	if ret == None:
+	    return None
+	return xmlNode(_obj=ret)
+    def get_content(self):
+	return self.content()
+    def get_name(self):
+	return _libxml.name(self._o)
+    def get_type(self):
+	return _libxml.type(self._o)
+    def get_doc(self):
+	ret = _libxml.doc(self._o)
+	if ret == None:
+	    return None
+	return xmlDoc(_doc=ret)
+    def free(self):
+        _libxml.freeDoc(self._o)
+	    
+
+class xmlDoc(xmlNode):
+    def __init__(self, file = None, _doc=None):
+	if _doc == None and file != None:
+	    _doc = _libxml.parseFile(file)
+	xmlNode.__init__(self, _obj=_doc)
diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h
new file mode 100644
index 0000000..a3aca48
--- /dev/null
+++ b/python/libxml_wrap.h
@@ -0,0 +1,18 @@
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/catalog.h>
+#include <libxml/threads.h>
+#include <libxml/nanoftp.h>
+#include <libxml/nanohttp.h>
+#include <libxml/uri.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/debugXML.h>
+
+PyObject * libxml_intWrap(int val);
+PyObject * libxml_xmlCharPtrWrap(const xmlChar *str);
+PyObject * libxml_charPtrWrap(const char *str);
+PyObject * libxml_xmlDocPtrWrap(xmlDocPtr doc);
+PyObject * libxml_xmlNodePtrWrap(xmlNodePtr node);
+PyObject * libxml_xmlAttrPtrWrap(xmlAttrPtr attr);