# HG changeset patch # User paulb # Date 1116113446 0 # Node ID eaae8ecfa2e9e612d402252e36acced40f8742ea # Parent 33df1847dcdee009058e48cf87f8e1fbc499b1f8 [project @ 2005-05-14 23:30:46 by paulb] Changed libxml2dom to use libxml2dom.macrolib functions throughout. diff -r 33df1847dcde -r eaae8ecfa2e9 libxml2dom/__init__.py --- a/libxml2dom/__init__.py Sat May 14 23:30:14 2005 +0000 +++ b/libxml2dom/__init__.py Sat May 14 23:30:46 2005 +0000 @@ -4,26 +4,19 @@ DOM wrapper around libxml2. """ -__version__ = "0.1.3" +__version__ = "0.2" import xml.dom import libxml2 +from libxml2dom.macrolib import * +from libxml2dom.macrolib import \ + createDocument as Node_createDocument, \ + parseString as Node_parseString, parseURI as Node_parseURI, \ + parseFile as Node_parseFile, \ + toString as Node_toString, toStream as Node_toStream, \ + toFile as Node_toFile import sys -# NOTE: libxml2 seems to use UTF-8 throughout. - -def from_unicode(s): - if type(s) == type(u""): - return s.encode("utf-8") - else: - return s - -def to_unicode(s): - if type(s) == type(""): - return unicode(s, encoding="utf-8") - else: - return s - # NOTE: Consider a generator instead. class NamedNodeMap(object): @@ -32,18 +25,10 @@ self.node = node def getNamedItem(self, name): - for attr in self.values(): - if name == attr.localName: - return attr - # NOTE: Check exception possibilities here. - return None + return self.node.getAttributeNode(name) def getNamedItemNS(self, ns, localName): - for attr in self.values(): - if localName == attr.localName and ns == attr.namespaceURI: - return attr - # NOTE: Check exception possibilities here. - return None + return self.node.getAttributeNodeNS(ns, localName) def setNamedItem(self, node): self.node.setAttributeNode(node.name, node) @@ -65,12 +50,7 @@ pass def values(self): - attributes = [] - _attribute = self.node.as_native_node().properties - while _attribute is not None: - attributes.append(Node(_attribute, ownerElement=self.node)) - _attribute = _attribute.next - return attributes + return [Node(_node) for _node in Node_attributes(self.node.as_native_node()).values()] def keys(self): return [(attr.namespaceURI, attr.localName) for attr in self.values()] @@ -84,289 +64,135 @@ 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): - _nodeTypes = { - "attribute" : xml.dom.Node.ATTRIBUTE_NODE, - "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, - "notation" : xml.dom.Node.NOTATION_NODE, - "pi" : xml.dom.Node.PROCESSING_INSTRUCTION_NODE, - "text" : xml.dom.Node.TEXT_NODE - } - def __init__(self, node, ownerElement=None, doctype=None): self._node = node - self.ownerElement = ownerElement - self.doctype = doctype def as_native_node(self): return self._node def _ownerDocument(self): - return Node(self._node.doc) + return Node(Node_ownerDocument(self._node)) def _nodeType(self): - return self._nodeTypes[self._node.type] + return Node_nodeType(self._node) def _childNodes(self): # NOTE: Consider a generator instead. - child_nodes = [] - _node = self._node.children - while _node is not None: - child_nodes.append(Node(_node)) - _node = _node.next - return child_nodes + return [Node(_node) for _node in Node_childNodes(self._node)] def _attributes(self): 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 to_unicode(ns.content) - else: - return None + return Node_namespaceURI(self._node) def _nodeValue(self): - return to_unicode(self._node.content) + return Node_nodeValue(self._node) def _prefix(self): - ns = self._getNs() - if ns is not None: - return to_unicode(ns.name) - else: - return None + return Node_prefix(self._node) def _nodeName(self): - prefix = self._prefix() - if prefix is not None: - return prefix + ":" + self._localName() - else: - return self._localName() + return Node_nodeName(self._node) def _tagName(self): - if self._node.type == "element": - return self._nodeName() - else: - return None + return Node_tagName(self._node) def _localName(self): - return to_unicode(self._node.name) + return Node_localName(self._node) def _parentNode(self): - if self.nodeType == xml.dom.Node.DOCUMENT_NODE: - return None - else: - return Node(self._node.parent) + return Node_parentNode(self._node) def _previousSibling(self): - if self._node.prev is not None: - return Node(self._node.prev) - else: - return None + return Node(Node_previousSibling(self._node)) def _nextSibling(self): - if self._node.next is not None: - return Node(self._node.next) - else: - return None + return Node(Node_nextSibling(self._node)) def hasAttributeNS(self, ns, localName): - return self.getAttributeNS(ns, localName) is not None + return Node_hasAttributeNS(self._node, ns, localName) def hasAttribute(self, name): - return self.getAttribute(name) is not None + return Node_hasAttribute(self._node, name) def getAttributeNS(self, ns, localName): - return to_unicode(self._node.nsProp(localName, ns)) + return Node_getAttributeNS(self._node, ns, localName) def getAttribute(self, name): - return to_unicode(self._node.prop(name)) + return Node_getAttribute(self._node, name) def getAttributeNodeNS(self, ns, localName): - return self.attributes.getNamedItemNS(ns, localName) + return Node(Node_getAttributeNodeNS(self._node, ns, localName)) def getAttributeNode(self, localName): - # NOTE: Needs verifying. - return self.attributes.getNamedItem(localName) + return Node(Node_getAttributeNode(self._node, localName)) def setAttributeNS(self, ns, name, value): - # NOTE: Need to convert from Unicode. - ns, name, value = map(from_unicode, [ns, name, value]) - - prefix, localName = _get_prefix_and_localName(name) - if prefix is not None: - self._node.setNsProp(self._node.newNs(ns, prefix), localName, value) - elif ns is not None and ns == self._node.ns().content: - self._node.setNsProp(self._node.ns(), localName, value) - else: - # NOTE: Needs verifying: what should happen to the namespace? - # NOTE: This also catches the case where None is the element's - # NOTE: namespace and is also used for the attribute. - self._node.setNsProp(None, localName, value) + Node_setAttributeNS(self._node, ns, name, value) def setAttribute(self, name, value): - # NOTE: Need to convert from Unicode. - name, value = map(from_unicode, [name, value]) - - self._node.setProp(name, value) + Node_setAttribute(self._node, name, value) def setAttributeNodeNS(self, ns, name, node): - # NOTE: Not actually putting the node on the element. - self.setAttributeNS(ns, name, node.nodeValue) + Node_setAttributeNodeNS(self._node, ns, name, node) def setAttributeNode(self, name, node): - # NOTE: Not actually putting the node on the element. - self.setAttribute(name, node.nodeValue) + Node_setAttributeNode(self._node, name, node) def createElementNS(self, ns, name): - # NOTE: Need to convert from Unicode. - ns, name = map(from_unicode, [ns, name]) - - prefix, localName = _get_prefix_and_localName(name) - _node = libxml2.newNode(localName) - # NOTE: Does it make sense to set the namespace if it is empty? - if ns is not None: - _ns = _node.newNs(ns, prefix) - _node.setNs(_ns) - return Node(_node) + return Node(Node_createElementNS(self._node, ns, name)) def createElement(self, name): - # NOTE: Need to convert from Unicode. - name = from_unicode(name) - - _node = libxml2.newNode(name) - return Node(_node) + return Node(Node_createElement(self._node, name)) def createAttributeNS(self, ns, name): - # NOTE: Need to convert from Unicode. - ns, name = map(from_unicode, [ns, name]) - - prefix, localName = _get_prefix_and_localName(name) - return TemporaryNode(ns, name, xml.dom.Node.ATTRIBUTE_NODE) + # Returns a special temporary node. + return Node_createAttributeNS(self._node, ns, name) def createAttribute(self, name): - # NOTE: Need to convert from Unicode. - name = from_unicode(name) - - return TemporaryNode(ns, name, xml.dom.Node.ATTRIBUTE_NODE) + # Returns a special temporary node. + return Node_createAttribute(self._node, name) def createTextNode(self, value): - # NOTE: Need to convert from Unicode. - value = from_unicode(value) - - return Node(libxml2.newText(value)) + return Node(Node_createTextNode(self._node, value)) def createComment(self, value): - # NOTE: Need to convert from Unicode. - value = from_unicode(value) - - return Node(libxml2.newComment(value)) - - def _add_node(self, tmp): - if tmp.nodeType == xml.dom.Node.ATTRIBUTE_NODE: - if tmp.ns is not None: - _child = self._node.newNsProp(None, tmp.localName, None) - _ns = _child.newNs(tmp.ns, tmp.prefix) - _child.setNs(_ns) - else: - _child = self._node.newProp(None, tmp.name, None) - else: - _child = None - - return _child + return Node(Node_createComment(self._node, value)) 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) - - elif node.nodeType == xml.dom.Node.COMMENT_NODE: - return self.ownerDocument.createComment(node.data) - - raise ValueError, node.nodeType + if hasattr(node, "as_native_node"): + return Node(Node_importNode(self._node, node.as_native_node(), deep)) + else: + return Node(Node_importNode_DOM(self._node, node, deep)) def insertBefore(self, tmp, oldNode): - if tmp.nodeType == xml.dom.Node.TEXT_NODE: - _child = tmp._node - elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE: - _child = tmp._node + if hasattr(tmp, "as_native_node"): + return Node(Node_insertBefore(self._node, tmp.as_native_node(), oldNode.as_native_node())) else: - _child = self._add_node(tmp) - _child.unlinkNode() - return Node(oldNode._node.addPrevSibling(_child)) + return Node(Node_insertBefore(self._node, tmp, oldNode.as_native_node())) def replaceChild(self, tmp, oldNode): - if tmp.nodeType == xml.dom.Node.TEXT_NODE: - _child = tmp._node - elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE: - _child = tmp._node + if hasattr(tmp, "as_native_node"): + return Node(Node_replaceChild(self._node, tmp.as_native_node(), oldNode.as_native_node())) else: - _child = self._add_node(tmp) - _child.unlinkNode() - return Node(oldNode._node.replaceNode(_child)) + return Node(Node_replaceChild(self._node, tmp, oldNode.as_native_node())) def appendChild(self, tmp): - if tmp.nodeType == xml.dom.Node.TEXT_NODE: - _child = self._node.addChild(tmp._node) - elif tmp.nodeType == xml.dom.Node.ELEMENT_NODE: - _child = self._node.addChild(tmp._node) + if hasattr(tmp, "as_native_node"): + return Node(Node_appendChild(self._node, tmp.as_native_node())) else: - _child = self._add_node(tmp) - return Node(_child) + return Node(Node_appendChild(self._node, tmp)) def removeChild(self, tmp): - tmp._node.unlinkNode() + if hasattr(tmp, "as_native_node"): + Node_removeChild(self._node, tmp.as_native_node()) + else: + Node_removeChild(self._node, tmp) #doctype defined in __init__ #ownerElement defined in __init__ @@ -384,23 +210,17 @@ previousSibling = property(_previousSibling) nextSibling = property(_nextSibling) - def isSameNode(self, other): - return self._node.nodePath() == other._node.nodePath() + #def isSameNode(self, other): + # return self._node.nodePath() == other._node.nodePath() - def __eq__(self, other): - return self._node.nodePath() == other._node.nodePath() + #def __eq__(self, other): + # return self._node.nodePath() == other._node.nodePath() # 4DOM extensions to the usual PyXML API. # NOTE: To be finished. def xpath(self, expr, variables=None, namespaces=None): - context = self.ownerDocument.as_native_node().xpathNewContext() - context.setContextNode(self.as_native_node()) - # NOTE: Discover namespaces from the node. - for prefix, ns in (namespaces or {}).items(): - context.xpathRegisterNs(prefix, ns) - # NOTE: May need to tidy up the context. - return [Node(_node) for _node in context.xpathEval(expr)] + return [Node(_node) for _node in Node_xpath(self._node, expr, variables, namespaces)] # Utility functions. @@ -408,12 +228,7 @@ 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 + return Node(Node_createDocument(namespaceURI, localName, doctype)) def parse(stream_or_string): if hasattr(stream_or_string, "read"): @@ -423,34 +238,21 @@ return parseFile(stream_or_string) def parseFile(s): - # NOTE: Switching off validation and remote DTD resolution. - context = libxml2.createFileParserCtxt(s) - context.validate(0) - context.ctxtUseOptions(0) - # Wish context.pedantic(0) would suppress warnings about "DAV:" - context.parseDocument() - return Node(context.doc()) + return Node(Node_parseFile(s)) def parseString(s): - # NOTE: Switching off validation and remote DTD resolution. - context = libxml2.createMemoryParserCtxt(s, len(s)) - context.validate(0) - context.ctxtUseOptions(0) - # Wish context.pedantic(0) would suppress warnings about "DAV:" - context.parseDocument() - return Node(context.doc()) + return Node(Node_parseString(s)) def parseURI(uri): - return Node(libxml2.parseURI(uri)) + return Node(Node_parseURI(uri)) def toString(node, encoding=None): - if encoding is None: - return node.as_native_node().serialize() - else: - return node.as_native_node().serialize(encoding) + return Node_toString(node.as_native_node(), encoding) -def toStream(node, stream=None, encoding=None): - stream = stream or sys.stdout - stream.write(toString(node, encoding)) +def toStream(node, stream, encoding=None): + Node_toStream(node.as_native_node(), stream, encoding) + +def toFile(node, f, encoding=None): + Node_toFile(node.as_native_node(), f, encoding) # vim: tabstop=4 expandtab shiftwidth=4