1.1 --- a/__init__.py Sat Nov 15 00:15:25 2003 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,396 +0,0 @@
1.4 -#!/usr/bin/env python
1.5 -
1.6 -"""
1.7 -DOM wrapper around libxml2.
1.8 -"""
1.9 -
1.10 -import xml.dom
1.11 -import libxml2
1.12 -import sys
1.13 -
1.14 -# NOTE: libxml2 seems to use UTF-8 throughout.
1.15 -
1.16 -def from_unicode(s):
1.17 - if type(s) == type(u""):
1.18 - return s.encode("utf-8")
1.19 - else:
1.20 - return s
1.21 -
1.22 -def to_unicode(s):
1.23 - if type(s) == type(""):
1.24 - return unicode(s, encoding="utf-8")
1.25 - else:
1.26 - return s
1.27 -
1.28 -# NOTE: Consider a generator instead.
1.29 -
1.30 -class NamedNodeMap(object):
1.31 -
1.32 - def __init__(self, node):
1.33 - self.node = node
1.34 -
1.35 - def getNamedItem(self, name):
1.36 - return self.node.getAttributeNode(name)
1.37 -
1.38 - def getNamedItemNS(self, ns, localName):
1.39 - return self.node.getAttributeNodeNS(ns, localName)
1.40 -
1.41 - def setNamedItem(self, node):
1.42 - self.node.setAttributeNode(node.name, node)
1.43 -
1.44 - def setNamedItemNS(self, node):
1.45 - self.node.setAttributeNodeNS(node.namespaceURI, node.localName, node)
1.46 -
1.47 - def __getitem__(self, name):
1.48 - return self.getNamedItem(name)
1.49 -
1.50 - def __setitem__(self, name, node):
1.51 - if name == node.nodeName:
1.52 - self.setNamedItem(node)
1.53 - else:
1.54 - raise KeyError, name
1.55 -
1.56 - def __delitem__(self, name):
1.57 - # NOTE: To be implemented.
1.58 - pass
1.59 -
1.60 - def values(self):
1.61 - attributes = []
1.62 - _attribute = self.node.as_native_node().properties
1.63 - while _attribute is not None:
1.64 - attributes.append(Node(_attribute, ownerElement=self.node))
1.65 - _attribute = _attribute.next
1.66 - return attributes
1.67 -
1.68 - def keys(self):
1.69 - return [(attr.namespaceURI, attr.localName) for attr in self.values()]
1.70 -
1.71 - def items(self):
1.72 - return [((attr.namespaceURI, attr.localName), attr) for attr in self.values()]
1.73 -
1.74 - def __repr__(self):
1.75 - return str(self)
1.76 -
1.77 - def __str__(self):
1.78 - return "{%s}" % ",\n".join(["%s : %s" % (repr(key), repr(value)) for key, value in self.items()])
1.79 -
1.80 -def _get_prefix_and_localName(name):
1.81 - t = name.split(":")
1.82 - if len(t) == 1:
1.83 - return None, name
1.84 - elif len(t) == 2:
1.85 - return t
1.86 - else:
1.87 - # NOTE: Should raise an exception.
1.88 - return None, None
1.89 -
1.90 -class TemporaryNode(object):
1.91 - def __init__(self, ns, name, nodeType):
1.92 - self.ns = ns
1.93 - self.name = name
1.94 - self.nodeType = nodeType
1.95 - self.prefix, self.localName = _get_prefix_and_localName(self.name)
1.96 -
1.97 -class Node(object):
1.98 -
1.99 - _nodeTypes = {
1.100 - "attribute" : xml.dom.Node.ATTRIBUTE_NODE,
1.101 - "comment" : xml.dom.Node.COMMENT_NODE,
1.102 - "document_xml" : xml.dom.Node.DOCUMENT_NODE,
1.103 - "doctype" : xml.dom.Node.DOCUMENT_TYPE_NODE,
1.104 - "dtd" : xml.dom.Node.DOCUMENT_TYPE_NODE, # NOTE: Needs verifying.
1.105 - "element" : xml.dom.Node.ELEMENT_NODE,
1.106 - "entity" : xml.dom.Node.ENTITY_NODE,
1.107 - "entity_ref" : xml.dom.Node.ENTITY_REFERENCE_NODE,
1.108 - "notation" : xml.dom.Node.NOTATION_NODE,
1.109 - "pi" : xml.dom.Node.PROCESSING_INSTRUCTION_NODE,
1.110 - "text" : xml.dom.Node.TEXT_NODE
1.111 - }
1.112 -
1.113 - def __init__(self, node, ownerElement=None, doctype=None):
1.114 - self._node = node
1.115 - self.ownerElement = ownerElement
1.116 - self.doctype = doctype
1.117 -
1.118 - def as_native_node(self):
1.119 - return self._node
1.120 -
1.121 - def _ownerDocument(self):
1.122 - return Node(self._node.doc)
1.123 -
1.124 - def _nodeType(self):
1.125 - return self._nodeTypes[self._node.type]
1.126 -
1.127 - def _childNodes(self):
1.128 -
1.129 - # NOTE: Consider a generator instead.
1.130 -
1.131 - child_nodes = []
1.132 - _node = self._node.children
1.133 - while _node is not None:
1.134 - child_nodes.append(Node(_node))
1.135 - _node = _node.next
1.136 - return child_nodes
1.137 -
1.138 - def _attributes(self):
1.139 - return NamedNodeMap(self)
1.140 -
1.141 - def _getNs(self):
1.142 -
1.143 - "Internal namespace information retrieval."
1.144 -
1.145 - try:
1.146 - return self._node.ns()
1.147 - except libxml2.treeError:
1.148 - return None
1.149 -
1.150 - def _namespaceURI(self):
1.151 - ns = self._getNs()
1.152 - if ns is not None:
1.153 - return to_unicode(ns.content)
1.154 - else:
1.155 - return None
1.156 -
1.157 - def _nodeValue(self):
1.158 - return to_unicode(self._node.content)
1.159 -
1.160 - def _prefix(self):
1.161 - ns = self._getNs()
1.162 - if ns is not None:
1.163 - return to_unicode(ns.name)
1.164 - else:
1.165 - return None
1.166 -
1.167 - def _nodeName(self):
1.168 - prefix = self._prefix()
1.169 - if prefix is not None:
1.170 - return prefix + ":" + self._localName()
1.171 - else:
1.172 - return self._localName()
1.173 -
1.174 - def _tagName(self):
1.175 - if self._node.type == "element":
1.176 - return self._nodeName()
1.177 - else:
1.178 - return None
1.179 -
1.180 - def _localName(self):
1.181 - return to_unicode(self._node.name)
1.182 -
1.183 - def _parentNode(self):
1.184 - if self.nodeType == xml.dom.Node.DOCUMENT_NODE:
1.185 - return None
1.186 - else:
1.187 - return Node(self._node.parent)
1.188 -
1.189 - def _nextSibling(self):
1.190 - if self._node.next is not None:
1.191 - return Node(self._node.next)
1.192 - else:
1.193 - return None
1.194 -
1.195 - def hasAttributeNS(self, ns, localName):
1.196 - return self.getAttributeNS(ns, localName) is not None
1.197 -
1.198 - def hasAttribute(self, name):
1.199 - return self.getAttribute(name) is not None
1.200 -
1.201 - def getAttributeNS(self, ns, localName):
1.202 - return to_unicode(self._node.nsProp(localName, ns))
1.203 -
1.204 - def getAttribute(self, name):
1.205 - return to_unicode(self._node.prop(name))
1.206 -
1.207 - def getAttributeNodeNS(self, ns, localName):
1.208 - return self.attributes[(ns, localName)]
1.209 -
1.210 - def getAttributeNode(self, localName):
1.211 - # NOTE: Needs verifying.
1.212 - return self.attributes[(None, localName)]
1.213 -
1.214 - def setAttributeNS(self, ns, name, value):
1.215 - # NOTE: Need to convert from Unicode.
1.216 - ns, name, value = map(from_unicode, [ns, name, value])
1.217 -
1.218 - prefix, localName = _get_prefix_and_localName(name)
1.219 - if prefix is not None:
1.220 - self._node.setNsProp(self._node.newNs(ns, prefix), localName, value)
1.221 - elif ns == self._node.ns().content:
1.222 - self._node.setNsProp(self._node.ns().content, localName, value)
1.223 - else:
1.224 - # NOTE: Needs verifying: what should happen to the namespace?
1.225 - self._node.setNsProp(None, localName, value)
1.226 -
1.227 - def setAttribute(self, name, value):
1.228 - # NOTE: Need to convert from Unicode.
1.229 - name, value = map(from_unicode, [name, value])
1.230 -
1.231 - self._node.setProp(name, value)
1.232 -
1.233 - def setAttributeNodeNS(self, ns, name, node):
1.234 - # NOTE: Not actually putting the node on the element.
1.235 - self.setAttributeNS(ns, name, node.nodeValue)
1.236 -
1.237 - def setAttributeNode(self, name, node):
1.238 - # NOTE: Not actually putting the node on the element.
1.239 - self.setAttribute(name, node.nodeValue)
1.240 -
1.241 - def createElementNS(self, ns, name):
1.242 - # NOTE: Need to convert from Unicode.
1.243 - ns, name = map(from_unicode, [ns, name])
1.244 -
1.245 - prefix, localName = _get_prefix_and_localName(name)
1.246 - _node = libxml2.newNode(localName)
1.247 - _ns = _node.newNs(ns, prefix)
1.248 - _node.setNs(_ns)
1.249 - return Node(_node)
1.250 -
1.251 - def createElement(self, name):
1.252 - # NOTE: Need to convert from Unicode.
1.253 - name = from_unicode(name)
1.254 -
1.255 - _node = libxml2.newNode(localName)
1.256 - return Node(_node)
1.257 -
1.258 - def createAttributeNS(self, ns, name):
1.259 - # NOTE: Need to convert from Unicode.
1.260 - ns, name = map(from_unicode, [ns, name])
1.261 -
1.262 - prefix, localName = _get_prefix_and_localName(name)
1.263 - return TemporaryNode(ns, name, xml.dom.Node.ATTRIBUTE_NODE)
1.264 -
1.265 - def createAttribute(self, name):
1.266 - # NOTE: Need to convert from Unicode.
1.267 - name = from_unicode(name)
1.268 -
1.269 - return TemporaryNode(ns, name, xml.dom.Node.ATTRIBUTE_NODE)
1.270 -
1.271 - def createTextNode(self, value):
1.272 - # NOTE: Need to convert from Unicode.
1.273 - name = from_unicode(name)
1.274 -
1.275 - return Node(libxml2.newText(value))
1.276 -
1.277 - def _add_node(self, tmp):
1.278 - if tmp.nodeType == xml.dom.Node.ATTRIBUTE_NODE:
1.279 - if tmp.ns is not None:
1.280 - _child = self._node.newNsProp(None, tmp.localName, None)
1.281 - _ns = _child.newNs(tmp.ns, tmp.prefix)
1.282 - _child.setNs(_ns)
1.283 - else:
1.284 - _child = self._node.newProp(None, tmp.name, None)
1.285 - else:
1.286 - _child = None
1.287 -
1.288 - return _child
1.289 -
1.290 - def importNode(self, node, deep):
1.291 -
1.292 - if node.nodeType == xml.dom.Node.ELEMENT_NODE:
1.293 - imported_element = self.ownerDocument.createElementNS(node.namespaceURI, node.tagName)
1.294 - for value in node.attributes.values():
1.295 - imported_element.setAttributeNS(value.namespaceURI, value.nodeName, value.nodeValue)
1.296 -
1.297 - if deep:
1.298 - for child in node.childNodes:
1.299 - imported_child = self.importNode(child, deep)
1.300 - if imported_child:
1.301 - imported_element.appendChild(imported_child)
1.302 -
1.303 - return imported_element
1.304 -
1.305 - elif node.nodeType == xml.dom.Node.TEXT_NODE:
1.306 - return self.ownerDocument.createTextNode(node.nodeValue)
1.307 -
1.308 - elif node.nodeType == xml.dom.Node.ATTRIBUTE_NODE:
1.309 - return self.ownerDocument.createAttributeNS(node.namespaceURI, node.name)
1.310 -
1.311 - raise ValueError, node.nodeType
1.312 -
1.313 - def insertBefore(self, tmp, oldNode):
1.314 - if tmp.nodeType == xml.dom.Node.TEXT_NODE:
1.315 - _child = tmp._node
1.316 - elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE:
1.317 - _child = tmp._node
1.318 - else:
1.319 - _child = self._add_node(tmp)
1.320 - _child.unlinkNode()
1.321 - return Node(oldNode._node.addPrevSibling(_child))
1.322 -
1.323 - def replaceChild(self, tmp, oldNode):
1.324 - if tmp.nodeType == xml.dom.Node.TEXT_NODE:
1.325 - _child = tmp._node
1.326 - elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE:
1.327 - _child = tmp._node
1.328 - else:
1.329 - _child = self._add_node(tmp)
1.330 - _child.unlinkNode()
1.331 - return Node(oldNode._node.replaceNode(_child))
1.332 -
1.333 - def appendChild(self, tmp):
1.334 - if tmp.nodeType == xml.dom.Node.TEXT_NODE:
1.335 - _child = self._node.addChild(tmp._node)
1.336 - elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE:
1.337 - _child = self._node.addChild(tmp._node)
1.338 - else:
1.339 - _child = self._add_node(tmp)
1.340 - return Node(_child)
1.341 -
1.342 - def removeChild(self, tmp):
1.343 - tmp._node.unlinkNode()
1.344 -
1.345 - #doctype defined in __init__
1.346 - #ownerElement defined in __init__
1.347 - ownerDocument = property(_ownerDocument)
1.348 - childNodes = property(_childNodes)
1.349 - value = data = nodeValue = property(_nodeValue)
1.350 - name = nodeName = property(_nodeName)
1.351 - tagName = property(_tagName)
1.352 - namespaceURI = property(_namespaceURI)
1.353 - prefix = property(_prefix)
1.354 - localName = property(_localName)
1.355 - parentNode = property(_parentNode)
1.356 - nodeType = property(_nodeType)
1.357 - attributes = property(_attributes)
1.358 - nextSibling = property(_nextSibling)
1.359 -
1.360 - def isSameNode(self, other):
1.361 - return self._node.nodePath() == other._node.nodePath()
1.362 -
1.363 - def __eq__(self, other):
1.364 - return self._node.nodePath() == other._node.nodePath()
1.365 -
1.366 -# Utility functions.
1.367 -
1.368 -def createDocumentType(localName, publicId, systemId):
1.369 - return None
1.370 -
1.371 -def createDocument(namespaceURI, localName, doctype):
1.372 - # NOTE: Fixed to use version 1.0 only.
1.373 - d = Node(libxml2.newDoc("1.0"), doctype=doctype)
1.374 - if localName is not None:
1.375 - root = d.createElementNS(namespaceURI, localName)
1.376 - d.appendChild(root)
1.377 - return d
1.378 -
1.379 -def parse(stream_or_string):
1.380 - if hasattr(stream_or_string, "read"):
1.381 - stream = stream_or_string
1.382 - else:
1.383 - stream = open(stream_or_string)
1.384 - return parseString(stream.read())
1.385 -
1.386 -def parseString(s):
1.387 - return Node(libxml2.parseDoc(s))
1.388 -
1.389 -def parseURI(uri):
1.390 - return Node(libxml2.parseURI(uri))
1.391 -
1.392 -def toString(node):
1.393 - return node.as_native_node().serialize()
1.394 -
1.395 -def toStream(node, stream=None):
1.396 - stream = stream or sys.stdout
1.397 - stream.write(toString(node))
1.398 -
1.399 -# vim: tabstop=4 expandtab shiftwidth=4