1.1 --- a/libxml2dom/__init__.py Mon Jan 08 23:22:48 2007 +0000
1.2 +++ b/libxml2dom/__init__.py Mon Jan 08 23:23:23 2007 +0000
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 DOM wrapper around libxml2, specifically the libxml2mod Python extension module.
1.6
1.7 -Copyright (C) 2003, 2004, 2005, 2006 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2003, 2004, 2005, 2006, 2007 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This library is free software; you can redistribute it and/or
1.11 modify it under the terms of the GNU Lesser General Public
1.12 @@ -20,7 +20,7 @@
1.13 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
1.14 """
1.15
1.16 -__version__ = "0.3.6"
1.17 +__version__ = "0.4"
1.18
1.19 from libxml2dom.macrolib import *
1.20 from libxml2dom.macrolib import \
1.21 @@ -30,6 +30,26 @@
1.22 toString as Node_toString, toStream as Node_toStream, \
1.23 toFile as Node_toFile
1.24
1.25 +class Implementation(object):
1.26 +
1.27 + "Contains an abstraction over the DOM implementation."
1.28 +
1.29 + def createDocumentType(self, localName, publicId, systemId):
1.30 + return DocumentType(localName, publicId, systemId)
1.31 +
1.32 + def createDocument(self, namespaceURI, localName, doctype):
1.33 + return Document(Node_createDocument(namespaceURI, localName, doctype), self)
1.34 +
1.35 + # Factory functions.
1.36 +
1.37 + def get_node(self, _node, context_node):
1.38 + if Node_nodeType(_node) == context_node.DOCUMENT_NODE:
1.39 + return context_node.ownerDocument
1.40 + elif Node_nodeType(_node) == context_node.ATTRIBUTE_NODE:
1.41 + return Attribute(_node, self, context_node.ownerDocument, context_node)
1.42 + else:
1.43 + return Node(_node, self, context_node.ownerDocument)
1.44 +
1.45 # Attribute and node list wrappers.
1.46
1.47 class NamedNodeMap(object):
1.48 @@ -96,7 +116,7 @@
1.49 pass
1.50
1.51 def values(self):
1.52 - return [Attribute(_node, self.node.ownerDocument) for _node in Node_attributes(self.node.as_native_node()).values()]
1.53 + return [Attribute(_node, self.impl, self.node.ownerDocument) for _node in Node_attributes(self.node.as_native_node()).values()]
1.54
1.55 def keys(self):
1.56 return [(attr.namespaceURI, attr.localName) for attr in self.values()]
1.57 @@ -146,8 +166,9 @@
1.58 PROCESSING_INSTRUCTION_NODE = xml.dom.Node.PROCESSING_INSTRUCTION_NODE
1.59 TEXT_NODE = xml.dom.Node.TEXT_NODE
1.60
1.61 - def __init__(self, node, ownerDocument=None):
1.62 + def __init__(self, node, impl, ownerDocument=None):
1.63 self._node = node
1.64 + self.impl = impl
1.65 self.ownerDocument = ownerDocument
1.66
1.67 def as_native_node(self):
1.68 @@ -160,7 +181,7 @@
1.69
1.70 # NOTE: Consider a generator instead.
1.71
1.72 - return NodeList([Node(_node, self.ownerDocument) for _node in Node_childNodes(self._node)])
1.73 + return NodeList([self.impl.get_node(_node, self) for _node in Node_childNodes(self._node)])
1.74
1.75 def _attributes(self):
1.76 return NamedNodeMap(self)
1.77 @@ -187,16 +208,16 @@
1.78 return Node_localName(self._node)
1.79
1.80 def _parentNode(self):
1.81 - return get_node(Node_parentNode(self._node), self)
1.82 + return self.impl.get_node(Node_parentNode(self._node), self)
1.83
1.84 def _previousSibling(self):
1.85 - return Node(Node_previousSibling(self._node), self.ownerDocument)
1.86 + return self.impl.get_node(Node_previousSibling(self._node), self)
1.87
1.88 def _nextSibling(self):
1.89 - return Node(Node_nextSibling(self._node), self.ownerDocument)
1.90 + return self.impl.get_node(Node_nextSibling(self._node), self)
1.91
1.92 def _doctype(self):
1.93 - return Node(Node_doctype(self._node), self.ownerDocument)
1.94 + return self.impl.get_node(Node_doctype(self._node), self)
1.95
1.96 def _publicId(self):
1.97 # NOTE: To be fixed when the libxml2mod API has been figured out.
1.98 @@ -244,10 +265,10 @@
1.99 return Node_getAttribute(self._node, name)
1.100
1.101 def getAttributeNodeNS(self, ns, localName):
1.102 - return Attribute(Node_getAttributeNodeNS(self._node, ns, localName), self.ownerDocument, self)
1.103 + return Attribute(Node_getAttributeNodeNS(self._node, ns, localName), self.impl, self.ownerDocument, self)
1.104
1.105 def getAttributeNode(self, localName):
1.106 - return Attribute(Node_getAttributeNode(self._node, localName), self.ownerDocument, self)
1.107 + return Attribute(Node_getAttributeNode(self._node, localName), self.impl, self.ownerDocument, self)
1.108
1.109 def setAttributeNS(self, ns, name, value):
1.110 Node_setAttributeNS(self._node, ns, name, value)
1.111 @@ -268,30 +289,30 @@
1.112 Node_removeAttribute(self._node, name)
1.113
1.114 def createElementNS(self, ns, name):
1.115 - return Node(Node_createElementNS(self._node, ns, name), self.ownerDocument)
1.116 + return self.impl.get_node(Node_createElementNS(self._node, ns, name), self)
1.117
1.118 def createElement(self, name):
1.119 - return Node(Node_createElement(self._node, name), self.ownerDocument)
1.120 + return self.impl.get_node(Node_createElement(self._node, name), self)
1.121
1.122 def createAttributeNS(self, ns, name):
1.123 tmp = self.createElement("tmp")
1.124 - return Attribute(Node_createAttributeNS(tmp._node, ns, name))
1.125 + return Attribute(Node_createAttributeNS(tmp._node, self.impl, ns, name))
1.126
1.127 def createAttribute(self, name):
1.128 tmp = self.createElement("tmp")
1.129 - return Attribute(Node_createAttribute(tmp._node, name))
1.130 + return Attribute(Node_createAttribute(tmp._node, name), self.impl)
1.131
1.132 def createTextNode(self, value):
1.133 - return Node(Node_createTextNode(self._node, value), self.ownerDocument)
1.134 + return self.impl.get_node(Node_createTextNode(self._node, value), self)
1.135
1.136 def createComment(self, value):
1.137 - return Node(Node_createComment(self._node, value), self.ownerDocument)
1.138 + return self.impl.get_node(Node_createComment(self._node, value), self)
1.139
1.140 def importNode(self, node, deep):
1.141 if hasattr(node, "as_native_node"):
1.142 - return Node(Node_importNode(self._node, node.as_native_node(), deep), self.ownerDocument)
1.143 + return self.impl.get_node(Node_importNode(self._node, node.as_native_node(), deep), self)
1.144 else:
1.145 - return Node(Node_importNode_DOM(self._node, node, deep), self.ownerDocument)
1.146 + return self.impl.get_node(Node_importNode_DOM(self._node, node, deep), self)
1.147
1.148 def cloneNode(self, deep):
1.149 # This takes advantage of the ubiquity of importNode (in spite of the DOM specification).
1.150 @@ -299,21 +320,21 @@
1.151
1.152 def insertBefore(self, tmp, oldNode):
1.153 if hasattr(tmp, "as_native_node"):
1.154 - return Node(Node_insertBefore(self._node, tmp.as_native_node(), oldNode.as_native_node()), self.ownerDocument)
1.155 + return self.impl.get_node(Node_insertBefore(self._node, tmp.as_native_node(), oldNode.as_native_node()), self)
1.156 else:
1.157 - return Node(Node_insertBefore(self._node, tmp, oldNode.as_native_node()), self.ownerDocument)
1.158 + return self.impl.get_node(Node_insertBefore(self._node, tmp, oldNode.as_native_node()), self)
1.159
1.160 def replaceChild(self, tmp, oldNode):
1.161 if hasattr(tmp, "as_native_node"):
1.162 - return Node(Node_replaceChild(self._node, tmp.as_native_node(), oldNode.as_native_node()), self.ownerDocument)
1.163 + return self.impl.get_node(Node_replaceChild(self._node, tmp.as_native_node(), oldNode.as_native_node()), self)
1.164 else:
1.165 - return Node(Node_replaceChild(self._node, tmp, oldNode.as_native_node()), self.ownerDocument)
1.166 + return self.impl.get_node(Node_replaceChild(self._node, tmp, oldNode.as_native_node()), self)
1.167
1.168 def appendChild(self, tmp):
1.169 if hasattr(tmp, "as_native_node"):
1.170 - return Node(Node_appendChild(self._node, tmp.as_native_node()), self.ownerDocument)
1.171 + return self.impl.get_node(Node_appendChild(self._node, tmp.as_native_node()), self)
1.172 else:
1.173 - return Node(Node_appendChild(self._node, tmp), self.ownerDocument)
1.174 + return self.impl.get_node(Node_appendChild(self._node, tmp), self)
1.175
1.176 def removeChild(self, tmp):
1.177 if hasattr(tmp, "as_native_node"):
1.178 @@ -381,7 +402,7 @@
1.179 if isinstance(result, str):
1.180 return to_unicode(result)
1.181 elif hasattr(result, "__len__"):
1.182 - return NodeList([get_node(_node, self) for _node in result])
1.183 + return NodeList([self.impl.get_node(_node, self) for _node in result])
1.184 else:
1.185 return result
1.186
1.187 @@ -402,8 +423,8 @@
1.188
1.189 "A class providing attribute access."
1.190
1.191 - def __init__(self, node, ownerDocument=None, ownerElement=None):
1.192 - Node.__init__(self, node, ownerDocument)
1.193 + def __init__(self, node, impl, ownerDocument=None, ownerElement=None):
1.194 + Node.__init__(self, node, impl, ownerDocument)
1.195 self.ownerElement = ownerElement
1.196
1.197 def _parentNode(self):
1.198 @@ -417,8 +438,9 @@
1.199
1.200 "A class providing document-level housekeeping."
1.201
1.202 - def __init__(self, node):
1.203 + def __init__(self, node, impl):
1.204 self._node = node
1.205 + self.impl = impl
1.206
1.207 def _ownerDocument(self):
1.208 return self
1.209 @@ -448,25 +470,15 @@
1.210 self.entities = {}
1.211 self.notations = {}
1.212
1.213 -# Factory functions.
1.214 -
1.215 -def get_node(_node, context_node):
1.216 - if Node_nodeType(_node) == context_node.DOCUMENT_NODE:
1.217 - return context_node.ownerDocument
1.218 - elif Node_nodeType(_node) == context_node.ATTRIBUTE_NODE:
1.219 - return Attribute(_node, context_node.ownerDocument, context_node)
1.220 - else:
1.221 - return Node(_node, context_node.ownerDocument)
1.222 -
1.223 # Utility functions.
1.224
1.225 def createDocumentType(localName, publicId, systemId):
1.226 - return DocumentType(localName, publicId, systemId)
1.227 + return impl.createDocumentType(localName, publicId, systemId)
1.228
1.229 def createDocument(namespaceURI, localName, doctype):
1.230 - return Document(Node_createDocument(namespaceURI, localName, doctype))
1.231 + return impl.createDocument(namespaceURI, localName, doctype)
1.232
1.233 -def parse(stream_or_string, html=0):
1.234 +def parse(stream_or_string, html=0, impl=None):
1.235
1.236 """
1.237 Parse the given 'stream_or_string', where the supplied object can either be
1.238 @@ -478,13 +490,15 @@
1.239 A document object is returned by this function.
1.240 """
1.241
1.242 + impl = impl or default_impl
1.243 +
1.244 if hasattr(stream_or_string, "read"):
1.245 stream = stream_or_string
1.246 - return parseString(stream.read(), html)
1.247 + return parseString(stream.read(), html, impl)
1.248 else:
1.249 - return parseFile(stream_or_string, html)
1.250 + return parseFile(stream_or_string, html, impl)
1.251
1.252 -def parseFile(filename, html=0):
1.253 +def parseFile(filename, html=0, impl=None):
1.254
1.255 """
1.256 Parse the file having the given 'filename'. If the optional 'html' parameter
1.257 @@ -494,9 +508,10 @@
1.258 A document object is returned by this function.
1.259 """
1.260
1.261 - return Document(Node_parseFile(filename, html))
1.262 + impl = impl or default_impl
1.263 + return Document(Node_parseFile(filename, html), impl)
1.264
1.265 -def parseString(s, html=0):
1.266 +def parseString(s, html=0, impl=None):
1.267
1.268 """
1.269 Parse the content of the given string 's'. If the optional 'html' parameter
1.270 @@ -506,9 +521,10 @@
1.271 A document object is returned by this function.
1.272 """
1.273
1.274 - return Document(Node_parseString(s, html))
1.275 + impl = impl or default_impl
1.276 + return Document(Node_parseString(s, html), impl)
1.277
1.278 -def parseURI(uri, html=0):
1.279 +def parseURI(uri, html=0, impl=None):
1.280
1.281 """
1.282 Parse the content found at the given 'uri'. If the optional 'html' parameter
1.283 @@ -523,7 +539,8 @@
1.284 A document object is returned by this function.
1.285 """
1.286
1.287 - return Document(Node_parseURI(uri, html))
1.288 + impl = impl or default_impl
1.289 + return Document(Node_parseURI(uri, html), impl)
1.290
1.291 def toString(node, encoding=None, prettyprint=0):
1.292
1.293 @@ -561,7 +578,7 @@
1.294
1.295 Node_toFile(node.as_native_node(), filename, encoding, prettyprint)
1.296
1.297 -def adoptNodes(nodes):
1.298 +def adoptNodes(nodes, impl=None):
1.299
1.300 """
1.301 A special utility method which adopts the given low-level 'nodes' and which
1.302 @@ -569,12 +586,18 @@
1.303 should not be casually used.
1.304 """
1.305
1.306 + impl = impl or default_impl
1.307 +
1.308 if len(nodes) == 0:
1.309 return []
1.310 - doc = Document(libxml2mod.doc(nodes[0]))
1.311 + doc = Document(libxml2mod.doc(nodes[0]), impl)
1.312 results = []
1.313 for node in nodes:
1.314 - results.append(Node(node, doc))
1.315 + results.append(Node(node, impl, doc))
1.316 return results
1.317
1.318 +# Single instance of the implementation.
1.319 +
1.320 +default_impl = Implementation()
1.321 +
1.322 # vim: tabstop=4 expandtab shiftwidth=4