# HG changeset patch # User paulb # Date 1065477545 0 # Node ID 0cc134cda8ec7cd9ba3a9629ec948e1386af521b # Parent 59bb4795f6c03cdf804e7f539c70ecbbb0ffe25a [project @ 2003-10-06 21:59:05 by paulb] Changed element creation to use libxml2 utility functions instead of fake node objects (which are still used for attribute nodes). Added more DOM support to enable XMLTools2 to work. Added utility functions for parsing, document creation and serialising. diff -r 59bb4795f6c0 -r 0cc134cda8ec __init__.py --- a/__init__.py Mon Oct 06 18:59:57 2003 +0000 +++ b/__init__.py Mon Oct 06 21:59:05 2003 +0000 @@ -6,6 +6,7 @@ import xml.dom import libxml2 +import sys # NOTE: Consider a generator instead. @@ -89,6 +90,7 @@ "comment" : xml.dom.Node.COMMENT_NODE, "document_xml" : xml.dom.Node.DOCUMENT_NODE, "doctype" : xml.dom.Node.DOCUMENT_TYPE_NODE, + "dtd" : xml.dom.Node.DOCUMENT_TYPE_NODE, # NOTE: Needs verifying. "element" : xml.dom.Node.ELEMENT_NODE, "entity" : xml.dom.Node.ENTITY_NODE, "entity_ref" : xml.dom.Node.ENTITY_REFERENCE_NODE, @@ -97,16 +99,13 @@ "text" : xml.dom.Node.TEXT_NODE } - def __init__(self, node, ownerElement=None): + def __init__(self, node, ownerElement=None, doctype=None): self._node = node self.ownerElement = ownerElement - - # NOTE: Fix the doctype. - - self.doctype = None + self.doctype = doctype def _ownerDocument(self): - return self._node.doc + return Node(self._node.doc) def _nodeType(self): return self._nodeTypes[self._node.type] @@ -173,11 +172,23 @@ else: return Node(self._node.parent) + def hasAttributeNS(self, ns, localName): + return self._getAttributeNS(ns, localName) is not None + + def hasAttribute(self, name): + return self._getAttribute(name) is not None + def getAttributeNS(self, ns, localName): + return self._getAttributeNS(ns, localName) or "" + + def _getAttributeNS(self, ns, localName): return self._node.nsProp(localName, ns) def getAttribute(self, name): - return self._node.prop(localName) + return self._getAttribute(name) or "" + + def _getAttribute(self, name): + return self._node.prop(name) def getAttributeNodeNS(self, ns, localName): return self.attributes[(ns, localName)] @@ -188,8 +199,13 @@ def setAttributeNS(self, ns, name, value): prefix, localName = _get_prefix_and_localName(name) - if localName: + if prefix is not None: self._node.setNsProp(self._node.newNs(ns, prefix), localName, value) + elif ns == self._node.ns().content: + self._node.setNsProp(self._node.ns(), localName, value) + else: + # NOTE: Needs verifying: what should happen to the namespace? + self._node.setNsProp(None, localName, value) def setAttribute(self, name, value): self._node.setProp(name, value) @@ -204,10 +220,14 @@ def createElementNS(self, ns, name): prefix, localName = _get_prefix_and_localName(name) - return TemporaryNode(ns, name, xml.dom.Node.ELEMENT_NODE) + _node = libxml2.newNode(localName) + _ns = _node.newNs(ns, prefix) + _node.setNs(_ns) + return Node(_node) def createElement(self, name): - return TemporaryNode(None, name, xml.dom.Node.ELEMENT_NODE) + _node = libxml2.newNode(localName) + return Node(_node) def createAttributeNS(self, ns, name): prefix, localName = _get_prefix_and_localName(name) @@ -220,30 +240,46 @@ return TemporaryText(self._node.doc.newDocText(value)) 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: + if tmp.nodeType == xml.dom.Node.ATTRIBUTE_NODE: + if tmp.ns is not None: _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: + _child = self._node.newProp(None, tmp.name, None) else: - 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 + _child = None return _child + def importNode(self, node, deep): + + if node.nodeType == xml.dom.Node.ELEMENT_NODE: + imported_element = self.ownerDocument.createElementNS(node.namespaceURI, node.tagName) + for value in node.attributes.values(): + imported_element.setAttributeNS(value.namespaceURI, value.nodeName, value.nodeValue) + + if deep: + for child in node.childNodes: + imported_child = self.importNode(child, deep) + if imported_child: + imported_element.appendChild(imported_child) + + return imported_element + + elif node.nodeType == xml.dom.Node.TEXT_NODE: + return self.ownerDocument.createTextNode(node.nodeValue) + + elif node.nodeType == xml.dom.Node.ATTRIBUTE_NODE: + return self.ownerDocument.createAttributeNS(node.namespaceURI, node.name) + + raise ValueError, node.nodeType + def insertBefore(self, tmp, oldNode): if tmp.nodeType == xml.dom.Node.TEXT_NODE: _child = tmp._text + elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE: + _child = tmp._node else: _child = self._add_node(tmp) _child.unlinkNode() @@ -252,6 +288,8 @@ def replaceChild(self, tmp, oldNode): if tmp.nodeType == xml.dom.Node.TEXT_NODE: _child = tmp._text + elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE: + _child = tmp._node else: _child = self._add_node(tmp) _child.unlinkNode() @@ -260,6 +298,8 @@ def appendChild(self, tmp): if tmp.nodeType == xml.dom.Node.TEXT_NODE: _child = self._node.addChild(tmp._text) + elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE: + _child = self._node.addChild(tmp._node) else: _child = self._add_node(tmp) return Node(_child) @@ -284,4 +324,37 @@ def __eq__(self, other): return self._node.nodePath() == other._node.nodePath() +# Utility functions. + +def createDocumentType(localName, publicId, systemId): + return None + +def createDocument(namespaceURI, localName, doctype): + # NOTE: Fixed to use version 1.0 only. + d = Node(libxml2.newDoc("1.0"), doctype=doctype) + if localName is not None: + root = d.createElementNS(namespaceURI, localName) + d.appendChild(root) + return d + +def parse(stream_or_string): + if hasattr(stream_or_string, "read"): + stream = stream_or_string + else: + stream = open(stream_or_string) + return parseString(stream.read()) + +def parseString(s): + return Node(libxml2.parseDoc(s)) + +def parseURI(uri): + return Node(libxml2.parseURI(uri)) + +def toString(node): + return node._node.serialize() + +def toStream(node, stream=None): + stream = stream or sys.stdout + stream.write(toString(node)) + # vim: tabstop=4 expandtab shiftwidth=4