libxml2dom

Changeset

276:e062bab9737f
2007-04-08 paulb raw files shortlog changelog graph [project @ 2007-04-08 22:51:59 by paulb] Added firstChild, lastChild, a NamedNodeMapIterator class. Fixed doctype retrieval for null doctypes. Moved document checking into the Node class. Introduced a Node_equals function for comparisons.
libxml2dom/__init__.py (file)
     1.1 --- a/libxml2dom/__init__.py	Sun Apr 08 22:50:34 2007 +0000
     1.2 +++ b/libxml2dom/__init__.py	Sun Apr 08 22:51:59 2007 +0000
     1.3 @@ -114,6 +114,11 @@
     1.4          self.node.removeAttributeNS(ns, localName)
     1.5          return old
     1.6  
     1.7 +    # Iterator emulation.
     1.8 +
     1.9 +    def __iter__(self):
    1.10 +        return NamedNodeMapIterator(self)
    1.11 +
    1.12      # Dictionary emulation methods.
    1.13  
    1.14      def __getitem__(self, name):
    1.15 @@ -149,6 +154,22 @@
    1.16  
    1.17      length = property(_length)
    1.18  
    1.19 +class NamedNodeMapIterator(object):
    1.20 +
    1.21 +    "An iterator over a NamedNodeMap."
    1.22 +
    1.23 +    def __init__(self, nodemap):
    1.24 +        self.nodemap = nodemap
    1.25 +        self.items = self.nodemap.items()
    1.26 +
    1.27 +    def next(self):
    1.28 +        if self.items:
    1.29 +            current = self.items[0][1]
    1.30 +            self.items = self.items[1:]
    1.31 +            return current
    1.32 +        else:
    1.33 +            raise StopIteration
    1.34 +
    1.35  class NodeList(list):
    1.36  
    1.37      "A wrapper around node lists."
    1.38 @@ -197,6 +218,12 @@
    1.39  
    1.40          return NodeList([self.impl.get_node(_node, self) for _node in Node_childNodes(self._node)])
    1.41  
    1.42 +    def _firstChild(self):
    1.43 +        return (self.childNodes or [None])[0]
    1.44 +
    1.45 +    def _lastChild(self):
    1.46 +        return (self.childNodes or [None])[-1]
    1.47 +
    1.48      def _attributes(self):
    1.49          return NamedNodeMap(self, self.impl)
    1.50  
    1.51 @@ -236,7 +263,11 @@
    1.52          return self.impl.get_node_or_none(Node_nextSibling(self._node), self)
    1.53  
    1.54      def _doctype(self):
    1.55 -        return self.impl.get_node(Node_doctype(self._node), self)
    1.56 +        _doctype = Node_doctype(self._node)
    1.57 +        if _doctype is not None:
    1.58 +            return self.impl.get_node(_doctype, self)
    1.59 +        else:
    1.60 +            return None
    1.61  
    1.62      def _publicId(self):
    1.63          # NOTE: To be fixed when the libxml2mod API has been figured out.
    1.64 @@ -341,18 +372,28 @@
    1.65          return self.importNode(self, deep)
    1.66  
    1.67      def insertBefore(self, tmp, oldNode):
    1.68 +        if tmp.ownerDocument != self.ownerDocument:
    1.69 +            raise xml.dom.DOMException(xml.dom.WRONG_DOCUMENT_ERR)
    1.70 +        if oldNode.parentNode != self:
    1.71 +            raise xml.dom.DOMException(xml.dom.NOT_FOUND_ERR)
    1.72          if hasattr(tmp, "as_native_node"):
    1.73              return self.impl.get_node(Node_insertBefore(self._node, tmp.as_native_node(), oldNode.as_native_node()), self)
    1.74          else:
    1.75              return self.impl.get_node(Node_insertBefore(self._node, tmp, oldNode.as_native_node()), self)
    1.76  
    1.77      def replaceChild(self, tmp, oldNode):
    1.78 +        if tmp.ownerDocument != self.ownerDocument:
    1.79 +            raise xml.dom.DOMException(xml.dom.WRONG_DOCUMENT_ERR)
    1.80 +        if oldNode.parentNode != self:
    1.81 +            raise xml.dom.DOMException(xml.dom.NOT_FOUND_ERR)
    1.82          if hasattr(tmp, "as_native_node"):
    1.83              return self.impl.get_node(Node_replaceChild(self._node, tmp.as_native_node(), oldNode.as_native_node()), self)
    1.84          else:
    1.85              return self.impl.get_node(Node_replaceChild(self._node, tmp, oldNode.as_native_node()), self)
    1.86  
    1.87      def appendChild(self, tmp):
    1.88 +        if tmp.ownerDocument != self.ownerDocument:
    1.89 +            raise xml.dom.DOMException(xml.dom.WRONG_DOCUMENT_ERR)
    1.90          if hasattr(tmp, "as_native_node"):
    1.91              return self.impl.get_node(Node_appendChild(self._node, tmp.as_native_node()), self)
    1.92          else:
    1.93 @@ -363,6 +404,7 @@
    1.94              Node_removeChild(self._node, tmp.as_native_node())
    1.95          else:
    1.96              Node_removeChild(self._node, tmp)
    1.97 +        return tmp
    1.98  
    1.99      def getElementById(self, identifier):
   1.100          nodes = self.xpath(".//*[@xml:id='" + identifier.replace("'", "'") + "']",
   1.101 @@ -398,6 +440,8 @@
   1.102          self.replaceChild(self.ownerDocument.createTextNode("".join(texts)), text_nodes[-1])
   1.103  
   1.104      childNodes = property(_childNodes)
   1.105 +    firstChild = property(_firstChild)
   1.106 +    lastChild = property(_lastChild)
   1.107      value = data = nodeValue = property(_nodeValue, _setNodeValue)
   1.108      textContent = property(_textContent)
   1.109      name = nodeName = property(_nodeName)
   1.110 @@ -426,7 +470,7 @@
   1.111          return hash(self.localName)
   1.112  
   1.113      def __eq__(self, other):
   1.114 -        return isinstance(other, Node) and libxml2mod.xmlXPathCmpNodes(self._node, other._node) == 0
   1.115 +        return isinstance(other, Node) and Node_equals(self._node, other._node)
   1.116  
   1.117      def __ne__(self, other):
   1.118          return not (self == other)