4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/libxml2dom/macrolib/macrolib.py Sun Jan 16 01:16:41 2005 +0000
4.3 @@ -0,0 +1,325 @@
4.4 +#!/usr/bin/env python
4.5 +
4.6 +"""
4.7 +DOM macros for libxml2.
4.8 +"""
4.9 +
4.10 +__version__ = "0.1.2"
4.11 +
4.12 +import xml.dom
4.13 +import libxml2
4.14 +import sys
4.15 +
4.16 +class TemporaryNode:
4.17 + def __init__(self, ns, name):
4.18 + self._ns = ns
4.19 + self.name = name
4.20 + self.type = "attribute"
4.21 +
4.22 + def ns(self):
4.23 + return self._ns
4.24 +
4.25 +# NOTE: libxml2 seems to use UTF-8 throughout.
4.26 +
4.27 +def from_unicode(s):
4.28 + if type(s) == type(u""):
4.29 + return s.encode("utf-8")
4.30 + else:
4.31 + return s
4.32 +
4.33 +def to_unicode(s):
4.34 + if type(s) == type(""):
4.35 + return unicode(s, encoding="utf-8")
4.36 + else:
4.37 + return s
4.38 +
4.39 +def _get_prefix_and_localName(name):
4.40 + t = name.split(":")
4.41 + if len(t) == 1:
4.42 + return None, name
4.43 + elif len(t) == 2:
4.44 + return t
4.45 + else:
4.46 + # NOTE: Should raise an exception.
4.47 + return None, None
4.48 +
4.49 +_nodeTypes = {
4.50 + "attribute" : xml.dom.Node.ATTRIBUTE_NODE,
4.51 + "comment" : xml.dom.Node.COMMENT_NODE,
4.52 + "document_xml" : xml.dom.Node.DOCUMENT_NODE,
4.53 + "doctype" : xml.dom.Node.DOCUMENT_TYPE_NODE,
4.54 + "dtd" : xml.dom.Node.DOCUMENT_TYPE_NODE, # NOTE: Needs verifying.
4.55 + "element" : xml.dom.Node.ELEMENT_NODE,
4.56 + "entity" : xml.dom.Node.ENTITY_NODE,
4.57 + "entity_ref" : xml.dom.Node.ENTITY_REFERENCE_NODE,
4.58 + "notation" : xml.dom.Node.NOTATION_NODE,
4.59 + "pi" : xml.dom.Node.PROCESSING_INSTRUCTION_NODE,
4.60 + "text" : xml.dom.Node.TEXT_NODE
4.61 + }
4.62 +
4.63 +def Node_ownerDocument(node):
4.64 + return node.doc
4.65 +
4.66 +def Node_nodeType(node):
4.67 + global _nodesTypes
4.68 + return _nodeTypes[node.type]
4.69 +
4.70 +def Node_childNodes(node):
4.71 +
4.72 + # NOTE: Consider a generator instead.
4.73 +
4.74 + child_nodes = []
4.75 + node = node.children
4.76 + while node is not None:
4.77 + child_nodes.append(node)
4.78 + node = node.next
4.79 + return child_nodes
4.80 +
4.81 +def Node_attributes(node):
4.82 + attributes = {}
4.83 + node = node.properties
4.84 + while node is not None:
4.85 + ns = _getNs(node)
4.86 + if ns is not None:
4.87 + attributes[(ns.content, node.name)] = node
4.88 + else:
4.89 + attributes[(None, node.name)] = node
4.90 + node = node.next
4.91 + return attributes
4.92 +
4.93 +def _getNs(node):
4.94 +
4.95 + "Internal namespace information retrieval."
4.96 +
4.97 + try:
4.98 + return node.ns()
4.99 + except libxml2.treeError:
4.100 + return None
4.101 +
4.102 +def Node_namespaceURI(node):
4.103 + ns = _getNs(node)
4.104 + if ns is not None:
4.105 + return to_unicode(ns.content)
4.106 + else:
4.107 + return None
4.108 +
4.109 +def Node_nodeValue(node):
4.110 + return to_unicode(node.content)
4.111 +
4.112 +def Node_prefix(node):
4.113 + ns = _getNs(node)
4.114 + if ns is not None:
4.115 + return to_unicode(ns.name)
4.116 + else:
4.117 + return None
4.118 +
4.119 +def Node_nodeName(node):
4.120 + prefix = Node_prefix(node)
4.121 + if prefix is not None:
4.122 + return prefix + ":" + Node_localName(node)
4.123 + else:
4.124 + return Node_localName(node)
4.125 +
4.126 +def Node_tagName(node):
4.127 + if node.type == "element":
4.128 + return Node_nodeName(node)
4.129 + else:
4.130 + return None
4.131 +
4.132 +def Node_localName(node):
4.133 + return to_unicode(node.name)
4.134 +
4.135 +def Node_parentNode(node):
4.136 + if node.type == "document_xml":
4.137 + return None
4.138 + else:
4.139 + return node.parent
4.140 +
4.141 +def Node_previousSibling(node):
4.142 + if node.prev is not None:
4.143 + return node.prev
4.144 + else:
4.145 + return None
4.146 +
4.147 +def Node_nextSibling(node):
4.148 + if node.next is not None:
4.149 + return node.next
4.150 + else:
4.151 + return None
4.152 +
4.153 +def Node_hasAttributeNS(node, ns, localName):
4.154 + return Node_getAttributeNS(ns, localName) is not None
4.155 +
4.156 +def Node_hasAttribute(node, name):
4.157 + return Node_getAttribute(name) is not None
4.158 +
4.159 +def Node_getAttributeNS(node, ns, localName):
4.160 + return to_unicode(node.nsProp(localName, ns))
4.161 +
4.162 +def Node_getAttribute(node, name):
4.163 + return to_unicode(node.prop(name))
4.164 +
4.165 +def Node_getAttributeNodeNS(node, ns, localName):
4.166 + return node.nsProp(localName, ns)
4.167 +
4.168 +def Node_getAttributeNode(node, name):
4.169 + # NOTE: Needs verifying.
4.170 + return node.prop(name)
4.171 +
4.172 +def Node_setAttributeNS(node, ns, name, value):
4.173 + # NOTE: Need to convert from Unicode.
4.174 + ns, name, value = map(from_unicode, [ns, name, value])
4.175 +
4.176 + prefix, localName = _get_prefix_and_localName(name)
4.177 + if prefix is not None:
4.178 + node.setNsProp(node.newNs(ns, prefix), localName, value)
4.179 + elif ns is not None and ns == node.ns().content:
4.180 + node.setNsProp(node.ns(), localName, value)
4.181 + else:
4.182 + # NOTE: Needs verifying: what should happen to the namespace?
4.183 + # NOTE: This also catches the case where None is the element's
4.184 + # NOTE: namespace and is also used for the attribute.
4.185 + node.setNsProp(None, localName, value)
4.186 +
4.187 +def Node_setAttribute(node, name, value):
4.188 + # NOTE: Need to convert from Unicode.
4.189 + name, value = map(from_unicode, [name, value])
4.190 +
4.191 + node.setProp(name, value)
4.192 +
4.193 +def Node_setAttributeNodeNS(node, ns, name, attr):
4.194 + # NOTE: Not actually putting the node on the element.
4.195 + Node_setAttributeNS(node, ns, name, Node_nodeValue(attr))
4.196 +
4.197 +def Node_setAttributeNode(node, name, attr):
4.198 + # NOTE: Not actually putting the node on the element.
4.199 + Node_setAttribute(node, name, Node_nodeValue(attr))
4.200 +
4.201 +def Node_createElementNS(node, ns, name):
4.202 + # NOTE: Need to convert from Unicode.
4.203 + ns, name = map(from_unicode, [ns, name])
4.204 +
4.205 + prefix, localName = _get_prefix_and_localName(name)
4.206 + new_node = libxml2.newNode(localName)
4.207 + # NOTE: Does it make sense to set the namespace if it is empty?
4.208 + if ns is not None:
4.209 + new_ns = new_node.newNs(ns, prefix)
4.210 + new_node.setNs(new_ns)
4.211 + return new_node
4.212 +
4.213 +def Node_createElement(node, name):
4.214 + # NOTE: Need to convert from Unicode.
4.215 + name = from_unicode(name)
4.216 +
4.217 + new_node = libxml2.newNode(name)
4.218 + return new_node
4.219 +
4.220 +def Node_createAttributeNS(node, ns, name):
4.221 + # NOTE: Need to convert from Unicode.
4.222 + ns, name = map(from_unicode, [ns, name])
4.223 +
4.224 + prefix, localName = _get_prefix_and_localName(name)
4.225 + # NOTE: Does it make sense to set the namespace if it is empty?
4.226 + if ns is not None:
4.227 + new_ns = new_node.newNs(ns, prefix)
4.228 + else:
4.229 + new_ns = None
4.230 + return TemporaryNode(new_ns, localName)
4.231 +
4.232 +def Node_createAttribute(node, name):
4.233 + # NOTE: Need to convert from Unicode.
4.234 + name = from_unicode(name)
4.235 +
4.236 + return TemporaryNode(None, name)
4.237 +
4.238 +def Node_createTextNode(node, value):
4.239 + # NOTE: Need to convert from Unicode.
4.240 + value = from_unicode(value)
4.241 +
4.242 + return libxml2.newText(value)
4.243 +
4.244 +def Node_createComment(node, value):
4.245 + # NOTE: Need to convert from Unicode.
4.246 + value = from_unicode(value)
4.247 +
4.248 + return libxml2.newComment(value)
4.249 +
4.250 +def _add_node(node, tmp):
4.251 + if tmp.ns is not None:
4.252 + child = node.newNsProp(None, Node_localName(tmp), None)
4.253 + ns = child.newNs(Node_namespaceURI(tmp), Node_prefix(tmp))
4.254 + child.setNs(ns)
4.255 + else:
4.256 + child = node.newProp(None, tmp.name, None)
4.257 +
4.258 + return child
4.259 +
4.260 +def Node_insertBefore(node, tmp, oldNode):
4.261 + if isinstance(tmp, TemporaryNode):
4.262 + child = _add_node(tmp)
4.263 + else:
4.264 + child = tmp
4.265 + return oldNode.addPrevSibling(child)
4.266 +
4.267 +def Node_replaceChild(node, tmp, oldNode):
4.268 + if isinstance(tmp, TemporaryNode):
4.269 + child = _add_node(tmp)
4.270 + else:
4.271 + child = tmp
4.272 + return oldNode.replaceNode(child)
4.273 +
4.274 +def Node_appendChild(node, tmp):
4.275 + return node.addChild(tmp)
4.276 +
4.277 +def Node_removeChild(node, child):
4.278 + child.unlinkNode()
4.279 +
4.280 +def Node_xpath(node, expr, variables=None, namespaces=None):
4.281 + context = Node_ownerDocument(node).xpathNewContext()
4.282 + context.setContextNode(node)
4.283 + # NOTE: Discover namespaces from the node.
4.284 + for prefix, ns in (namespaces or {}).items():
4.285 + context.xpathRegisterNs(prefix, ns)
4.286 + # NOTE: May need to tidy up the context.
4.287 + return context.xpathEval(expr)
4.288 +
4.289 +# Utility functions.
4.290 +
4.291 +def createDocumentType(localName, publicId, systemId):
4.292 + return None
4.293 +
4.294 +def createDocument(namespaceURI, localName, doctype):
4.295 + # NOTE: Fixed to use version 1.0 only.
4.296 + d = libxml2.newDoc("1.0")
4.297 + if localName is not None:
4.298 + root = Node_createElementNS(d, namespaceURI, localName)
4.299 + Node_appendChild(d, root)
4.300 + return d
4.301 +
4.302 +def parse(stream_or_string):
4.303 + if hasattr(stream_or_string, "read"):
4.304 + stream = stream_or_string
4.305 + return parseString(stream.read())
4.306 + else:
4.307 + return parseFile(stream_or_string)
4.308 +
4.309 +def parseFile(s):
4.310 + # NOTE: Switching off validation and remote DTD resolution.
4.311 + context = libxml2.createFileParserCtxt(s)
4.312 + context.validate(0)
4.313 + context.ctxtUseOptions(0)
4.314 + context.parseDocument()
4.315 + return context.doc()
4.316 +
4.317 +def parseString(s):
4.318 + # NOTE: Switching off validation and remote DTD resolution.
4.319 + context = libxml2.createMemoryParserCtxt(s, len(s))
4.320 + context.validate(0)
4.321 + context.ctxtUseOptions(0)
4.322 + context.parseDocument()
4.323 + return context.doc()
4.324 +
4.325 +def parseURI(uri):
4.326 + return libxml2.parseURI(uri)
4.327 +
4.328 +# vim: tabstop=4 expandtab shiftwidth=4