integrated the Python 2.2 optimizations from Hannu Krosing, while
* python/libxml.py: integrated the Python 2.2 optimizations
from Hannu Krosing, while maintaining compatibility with
1.5 and 2.1
Daniel
diff --git a/python/libxml.py b/python/libxml.py
index 6203e3d..a3d1bdd 100644
--- a/python/libxml.py
+++ b/python/libxml.py
@@ -208,57 +208,6 @@
self._o = _obj;
return
self._o = None
-
- def __getattr__(self, attr):
- if attr == "parent":
- ret = libxml2mod.parent(self._o)
- if ret == None:
- return None
- return xmlNode(_obj=ret)
- elif attr == "properties":
- ret = libxml2mod.properties(self._o)
- if ret == None:
- return None
- return xmlAttr(_obj=ret)
- elif attr == "children":
- ret = libxml2mod.children(self._o)
- if ret == None:
- return None
- return xmlNode(_obj=ret)
- elif attr == "last":
- ret = libxml2mod.last(self._o)
- if ret == None:
- return None
- return xmlNode(_obj=ret)
- elif attr == "next":
- ret = libxml2mod.next(self._o)
- if ret == None:
- return None
- return xmlNode(_obj=ret)
- elif attr == "prev":
- ret = libxml2mod.prev(self._o)
- if ret == None:
- return None
- return xmlNode(_obj=ret)
- elif attr == "content":
- return libxml2mod.xmlNodeGetContent(self._o)
- elif attr == "name":
- return libxml2mod.name(self._o)
- elif attr == "type":
- return libxml2mod.type(self._o)
- elif attr == "doc":
- ret = libxml2mod.doc(self._o)
- if ret == None:
- if self.type == "document_xml" or self.type == "document_html":
- return xmlDoc(_obj=self._o)
- else:
- return None
- return xmlDoc(_obj=ret)
- raise AttributeError,attr
-
- #
- # Those are common attributes to nearly all type of nodes
- #
def get_parent(self):
ret = libxml2mod.parent(self._o)
if ret == None:
@@ -284,11 +233,6 @@
if ret == None:
return None
return xmlAttr(_obj=ret)
- def get_doc(self):
- ret = libxml2mod.doc(self._o)
- if ret == None:
- return None
- return xmlDoc(_obj=ret)
def get_prev(self):
ret = libxml2mod.prev(self._o)
if ret == None:
@@ -296,20 +240,88 @@
return xmlNode(_obj=ret)
def get_content(self):
return libxml2mod.xmlNodeGetContent(self._o)
- def getContent(self):
- return libxml2mod.xmlNodeGetContent(self._o)
+ getContent = get_content # why is this duplicate naming needed ?
def get_name(self):
return libxml2mod.name(self._o)
def get_type(self):
return libxml2mod.type(self._o)
- def free(self):
- libxml2mod.freeDoc(self._o)
+ def get_doc(self):
+ ret = libxml2mod.doc(self._o)
+ if ret == None:
+ if self.type in ["document_xml", "document_html"]:
+ return xmlDoc(_obj=self._o)
+ else:
+ return None
+ return xmlDoc(_obj=ret)
+ #
+ # Those are common attributes to nearly all type of nodes
+ # defined as python2 properties
+ #
+ import sys
+ if float(sys.version[0:3]) < 2.2:
+ def __getattr__(self, attr):
+ if attr == "parent":
+ ret = libxml2mod.parent(self._o)
+ if ret == None:
+ return None
+ return xmlNode(_obj=ret)
+ elif attr == "properties":
+ ret = libxml2mod.properties(self._o)
+ if ret == None:
+ return None
+ return xmlAttr(_obj=ret)
+ elif attr == "children":
+ ret = libxml2mod.children(self._o)
+ if ret == None:
+ return None
+ return xmlNode(_obj=ret)
+ elif attr == "last":
+ ret = libxml2mod.last(self._o)
+ if ret == None:
+ return None
+ return xmlNode(_obj=ret)
+ elif attr == "next":
+ ret = libxml2mod.next(self._o)
+ if ret == None:
+ return None
+ return xmlNode(_obj=ret)
+ elif attr == "prev":
+ ret = libxml2mod.prev(self._o)
+ if ret == None:
+ return None
+ return xmlNode(_obj=ret)
+ elif attr == "content":
+ return libxml2mod.xmlNodeGetContent(self._o)
+ elif attr == "name":
+ return libxml2mod.name(self._o)
+ elif attr == "type":
+ return libxml2mod.type(self._o)
+ elif attr == "doc":
+ ret = libxml2mod.doc(self._o)
+ if ret == None:
+ if self.type == "document_xml" or self.type == "document_html":
+ return xmlDoc(_obj=self._o)
+ else:
+ return None
+ return xmlDoc(_obj=ret)
+ raise AttributeError,attr
+ else:
+ parent = property(get_parent, None, None, "Parent node")
+ children = property(get_children, None, None, "First child node")
+ last = property(get_last, None, None, "Last sibling node")
+ next = property(get_next, None, None, "Next sibling node")
+ prev = property(get_prev, None, None, "Previous sibling node")
+ properties = property(get_properties, None, None, "List of properies")
+ content = property(get_content, None, None, "Content of this node")
+ name = property(get_name, None, None, "Node name")
+ type = property(get_type, None, None, "Node type")
+ doc = property(get_doc, None, None, "The document this node belongs to")
#
# Serialization routines, the optional arguments have the following
# meaning:
# encoding: string to ask saving in a specific encoding
- # format: if 1 the serializer is asked to indent the output
+ # indent: if 1 the serializer is asked to indent the output
#
def serialize(self, encoding = None, format = 0):
return libxml2mod.serializeNode(self._o, encoding, format)
@@ -329,7 +341,82 @@
res = ctxt.xpathEval(expr)
ctxt.xpathFreeContext()
return res
-
+
+ #
+ # Selecting nodes using XPath, faster because the context
+ # is allocated just once per xmlDoc.
+ #
+ def xpathEval2(self, expr):
+ doc = self.doc
+ if doc == None:
+ return None
+ try:
+ doc._ctxt.setContextNode(self)
+ except:
+ doc._ctxt = doc.xpathNewContext()
+ doc._ctxt.setContextNode(self)
+ res = doc._ctxt.xpathEval(expr)
+ return res
+
+ # support for python2 iterators
+ def walk_depth_first(self):
+ return xmlCoreDepthFirstItertor(self)
+ def walk_breadth_first(self):
+ return xmlCoreBreadthFirstItertor(self)
+ __iter__ = walk_depth_first
+
+ def free(self):
+ try:
+ self.doc._ctxt.xpathFreeContext()
+ except:
+ pass
+ libxml2mod.freeDoc(self._o)
+
+
+#
+# implements the depth-first iterator for libxml2 DOM tree
+#
+class xmlCoreDepthFirstItertor:
+ def __init__(self, node):
+ self.node = node
+ self.parents = []
+ def __iter__(self):
+ return self
+ def next(self):
+ while 1:
+ if self.node:
+ ret = self.node
+ self.parents.append(self.node)
+ self.node = self.node.children
+ return ret
+ try:
+ parent = self.parents.pop()
+ except IndexError:
+ raise StopIteration
+ self.node = parent.next
+
+#
+# implements the breadth-first iterator for libxml2 DOM tree
+#
+class xmlCoreBreadthFirstItertor:
+ def __init__(self, node):
+ self.node = node
+ self.parents = []
+ def __iter__(self):
+ return self
+ def next(self):
+ while 1:
+ if self.node:
+ ret = self.node
+ self.parents.append(self.node)
+ self.node = self.node.next
+ return ret
+ try:
+ parent = self.parents.pop()
+ except IndexError:
+ raise StopIteration
+ self.node = parent.children
+
#
# converters to present a nicer view of the XPath returns
#
@@ -366,7 +453,6 @@
def registerXPathFunction(ctxt, name, ns_uri, f):
ret = libxml2mod.xmlRegisterXPathFunction(ctxt, name, ns_uri, f)
-
#
# For the xmlTextReader parser configuration
#