# HG changeset patch # User paulb # Date 1065390782 0 # Node ID c696f11fd40b04a54d456856abf4580830d37b7d # Parent 3f47c37560792a5e295df7b01ea59ebd8d6b2318 [project @ 2003-10-05 21:53:02 by paulb] Added much improved support for elements and attributes to permit simple document modification. diff -r 3f47c3756079 -r c696f11fd40b __init__.py --- a/__init__.py Fri Jun 20 21:40:13 2008 +0200 +++ b/__init__.py Sun Oct 05 21:53:02 2003 +0000 @@ -5,11 +5,72 @@ """ import xml.dom +import libxml2 -class Attribute(object): +# NOTE: Consider a generator instead. + +class NamedNodeMap(object): def __init__(self, node): - self._node = node + self.node = node + + def getNamedItem(self, name): + pass + + def getNamedItemNS(self, ns, localName): + pass + + def setNamedItem(self, node): + pass + + def setNamedItemNS(self, node): + pass + + def __getitem__(self, name): + pass + + def __setitem__(self, name, node): + pass + + def __delitem__(self, name): + pass + + def values(self): + attributes = [] + _attribute = self.node._node.properties + while _attribute is not None: + attributes.append(Node(_attribute, ownerElement=self.node)) + _attribute = _attribute.next + return attributes + + def keys(self): + return [(attr.namespaceURI, attr.localName) for attr in self.values()] + + def items(self): + return [((attr.namespaceURI, attr.localName), attr) for attr in self.values()] + + def __repr__(self): + return str(self) + + def __str__(self): + return "{%s}" % ",\n".join(["%s : %s" % (repr(key), repr(value)) for key, value in self.items()]) + +def _get_prefix_and_localName(name): + t = name.split(":") + if len(t) == 1: + return None, name + elif len(t) == 2: + return t + else: + # NOTE: Should raise an exception. + return None, None + +class TemporaryNode(object): + def __init__(self, ns, name, nodeType): + self.ns = ns + self.name = name + self.nodeType = nodeType + self.prefix, self.localName = _get_prefix_and_localName(self.name) class Node(object): @@ -26,8 +87,9 @@ "text" : xml.dom.Node.TEXT_NODE } - def __init__(self, node): + def __init__(self, node, ownerElement=None): self._node = node + self.ownerElement = ownerElement def _ownerDocument(self): return self._node.doc @@ -36,6 +98,9 @@ return self._nodeTypes[self._node.type] def _childNodes(self): + + # NOTE: Consider a generator instead. + child_nodes = [] child_node = self._node.children while child_node is not None: @@ -45,31 +110,149 @@ return child_nodes def _attributes(self): - attributes = [] - attribute = self._node.properties - while attribute is not None: - attributes.append( - Attribute(attribute)) - attribute = attribute.next - return attributes + return NamedNodeMap(self) + + def _getNs(self): + + "Internal namespace information retrieval." + + try: + return self._node.ns() + except libxml2.treeError: + return None + + def _namespaceURI(self): + ns = self._getNs() + if ns is not None: + return ns.content + else: + return None + + def _nodeValue(self): + return self._node.content + + def _prefix(self): + ns = self._getNs() + if ns is not None: + return ns.name + else: + return None + + def _nodeName(self): + prefix = self._prefix() + if prefix is not None: + return prefix + ":" + self._localName() + else: + return self._localName() def _tagName(self): if self._node.type == "element": - return self._node.name + return self._nodeName() else: return None - def _namespaceURI(self): - if self._node.type == "element": - return self._node.ns().content + def _localName(self): + return self._node.name + + def _parentNode(self): + return self._node.parent + + def getAttributeNS(self, ns, localName): + return self._node.nsProp(localName, ns) + + def getAttribute(self, name): + return self._node.prop(localName) + + def getAttributeNodeNS(self, ns, localName): + return self.attributes[(ns, localName)] + + def getAttributeNode(self, localName): + # NOTE: Needs verifying. + return self.attributes[(None, localName)] + + def setAttributeNS(self, ns, name, value): + prefix, localName = _get_prefix_and_localName(name) + if localName: + self._node.setNsProp(self._node.newNs(ns, prefix), localName, value) + + def setAttribute(self, name, value): + self._node.setProp(name, value) + + def setAttributeNodeNS(self, ns, name, node): + # NOTE: Not actually putting the node on the element. + self.setAttributeNS(ns, name, node.nodeValue) + + def setAttributeNode(self, name, node): + # NOTE: Not actually putting the node on the element. + self.setAttribute(name, node.nodeValue) + + def createElementNS(self, ns, name): + prefix, localName = _get_prefix_and_localName(name) + return TemporaryNode(ns, name, xml.dom.Node.ELEMENT_NODE) + + def createElement(self, name): + return TemporaryNode(None, name, xml.dom.Node.ELEMENT_NODE) + + def createAttributeNS(self, ns, name): + prefix, localName = _get_prefix_and_localName(name) + return TemporaryNode(ns, name, xml.dom.Node.ATTRIBUTE_NODE) + + def createAttribute(self, name): + return TemporaryNode(ns, name, xml.dom.Node.ATTRIBUTE_NODE) + + def _add_node(self, tmp): + if tmp.ns is not None: + if tmp.nodeType == xml.dom.Node.ELEMENT_NODE: + _child = self._node.newChild(None, tmp.localName, None) + elif tmp.nodeType == xml.dom.Node.ATTRIBUTE_NODE: + _child = self._node.newNsProp(None, tmp.localName, None) + else: + _child = None + + if _child is not None: + _ns = _child.newNs(tmp.ns, tmp.prefix) + _child.setNs(_ns) else: - return None + if tmp.nodeType == xml.dom.Node.ELEMENT_NODE: + _child = self._node.newChild(None, tmp.name, None) + elif tmp.nodeType == xml.dom.Node.ATTRIBUTE_NODE: + _child = self._node.newProp(None, tmp.name, None) + else: + _child = None + + return _child - nodeType = property(_nodeType) + def insertBefore(self, tmp, oldNode): + _child = self._add_node(tmp) + _child.unlinkNode() + return Node(oldNode._node.addPrevSibling(_child)) + + def replaceChild(self, tmp, oldNode): + _child = self._add_node(tmp) + _child.unlinkNode() + return Node(oldNode._node.replaceNode(_child)) + + def appendChild(self, tmp): + return Node(self._add_node(tmp)) + + #doctype = property(_doctype) + #ownerElement = property(_ownerElement) ownerDocument = property(_ownerDocument) childNodes = property(_childNodes) - attributes = property(_attributes) + value = data = nodeValue = property(_nodeValue) + name = nodeName = property(_nodeName) tagName = property(_tagName) namespaceURI = property(_namespaceURI) + prefix = property(_prefix) + localName = property(_localName) + parentNode = property(_parentNode) + nodeType = property(_nodeType) + attributes = property(_attributes) + + def isSameNode(self, other): + return self._node.nodePath() == other._node.nodePath() + + def __eq__(self, other): + return self._node.nodePath() == other._node.nodePath() # vim: tabstop=4 expandtab shiftwidth=4