1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libxml2dom/macrolib/macrolib.py Sun Jan 16 01:16:41 2005 +0000
1.3 @@ -0,0 +1,325 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +DOM macros for libxml2.
1.8 +"""
1.9 +
1.10 +__version__ = "0.1.2"
1.11 +
1.12 +import xml.dom
1.13 +import libxml2
1.14 +import sys
1.15 +
1.16 +class TemporaryNode:
1.17 + def __init__(self, ns, name):
1.18 + self._ns = ns
1.19 + self.name = name
1.20 + self.type = "attribute"
1.21 +
1.22 + def ns(self):
1.23 + return self._ns
1.24 +
1.25 +# NOTE: libxml2 seems to use UTF-8 throughout.
1.26 +
1.27 +def from_unicode(s):
1.28 + if type(s) == type(u""):
1.29 + return s.encode("utf-8")
1.30 + else:
1.31 + return s
1.32 +
1.33 +def to_unicode(s):
1.34 + if type(s) == type(""):
1.35 + return unicode(s, encoding="utf-8")
1.36 + else:
1.37 + return s
1.38 +
1.39 +def _get_prefix_and_localName(name):
1.40 + t = name.split(":")
1.41 + if len(t) == 1:
1.42 + return None, name
1.43 + elif len(t) == 2:
1.44 + return t
1.45 + else:
1.46 + # NOTE: Should raise an exception.
1.47 + return None, None
1.48 +
1.49 +_nodeTypes = {
1.50 + "attribute" : xml.dom.Node.ATTRIBUTE_NODE,
1.51 + "comment" : xml.dom.Node.COMMENT_NODE,
1.52 + "document_xml" : xml.dom.Node.DOCUMENT_NODE,
1.53 + "doctype" : xml.dom.Node.DOCUMENT_TYPE_NODE,
1.54 + "dtd" : xml.dom.Node.DOCUMENT_TYPE_NODE, # NOTE: Needs verifying.
1.55 + "element" : xml.dom.Node.ELEMENT_NODE,
1.56 + "entity" : xml.dom.Node.ENTITY_NODE,
1.57 + "entity_ref" : xml.dom.Node.ENTITY_REFERENCE_NODE,
1.58 + "notation" : xml.dom.Node.NOTATION_NODE,
1.59 + "pi" : xml.dom.Node.PROCESSING_INSTRUCTION_NODE,
1.60 + "text" : xml.dom.Node.TEXT_NODE
1.61 + }
1.62 +
1.63 +def Node_ownerDocument(node):
1.64 + return node.doc
1.65 +
1.66 +def Node_nodeType(node):
1.67 + global _nodesTypes
1.68 + return _nodeTypes[node.type]
1.69 +
1.70 +def Node_childNodes(node):
1.71 +
1.72 + # NOTE: Consider a generator instead.
1.73 +
1.74 + child_nodes = []
1.75 + node = node.children
1.76 + while node is not None:
1.77 + child_nodes.append(node)
1.78 + node = node.next
1.79 + return child_nodes
1.80 +
1.81 +def Node_attributes(node):
1.82 + attributes = {}
1.83 + node = node.properties
1.84 + while node is not None:
1.85 + ns = _getNs(node)
1.86 + if ns is not None:
1.87 + attributes[(ns.content, node.name)] = node
1.88 + else:
1.89 + attributes[(None, node.name)] = node
1.90 + node = node.next
1.91 + return attributes
1.92 +
1.93 +def _getNs(node):
1.94 +
1.95 + "Internal namespace information retrieval."
1.96 +
1.97 + try:
1.98 + return node.ns()
1.99 + except libxml2.treeError:
1.100 + return None
1.101 +
1.102 +def Node_namespaceURI(node):
1.103 + ns = _getNs(node)
1.104 + if ns is not None:
1.105 + return to_unicode(ns.content)
1.106 + else:
1.107 + return None
1.108 +
1.109 +def Node_nodeValue(node):
1.110 + return to_unicode(node.content)
1.111 +
1.112 +def Node_prefix(node):
1.113 + ns = _getNs(node)
1.114 + if ns is not None:
1.115 + return to_unicode(ns.name)
1.116 + else:
1.117 + return None
1.118 +
1.119 +def Node_nodeName(node):
1.120 + prefix = Node_prefix(node)
1.121 + if prefix is not None:
1.122 + return prefix + ":" + Node_localName(node)
1.123 + else:
1.124 + return Node_localName(node)
1.125 +
1.126 +def Node_tagName(node):
1.127 + if node.type == "element":
1.128 + return Node_nodeName(node)
1.129 + else:
1.130 + return None
1.131 +
1.132 +def Node_localName(node):
1.133 + return to_unicode(node.name)
1.134 +
1.135 +def Node_parentNode(node):
1.136 + if node.type == "document_xml":
1.137 + return None
1.138 + else:
1.139 + return node.parent
1.140 +
1.141 +def Node_previousSibling(node):
1.142 + if node.prev is not None:
1.143 + return node.prev
1.144 + else:
1.145 + return None
1.146 +
1.147 +def Node_nextSibling(node):
1.148 + if node.next is not None:
1.149 + return node.next
1.150 + else:
1.151 + return None
1.152 +
1.153 +def Node_hasAttributeNS(node, ns, localName):
1.154 + return Node_getAttributeNS(ns, localName) is not None
1.155 +
1.156 +def Node_hasAttribute(node, name):
1.157 + return Node_getAttribute(name) is not None
1.158 +
1.159 +def Node_getAttributeNS(node, ns, localName):
1.160 + return to_unicode(node.nsProp(localName, ns))
1.161 +
1.162 +def Node_getAttribute(node, name):
1.163 + return to_unicode(node.prop(name))
1.164 +
1.165 +def Node_getAttributeNodeNS(node, ns, localName):
1.166 + return node.nsProp(localName, ns)
1.167 +
1.168 +def Node_getAttributeNode(node, name):
1.169 + # NOTE: Needs verifying.
1.170 + return node.prop(name)
1.171 +
1.172 +def Node_setAttributeNS(node, ns, name, value):
1.173 + # NOTE: Need to convert from Unicode.
1.174 + ns, name, value = map(from_unicode, [ns, name, value])
1.175 +
1.176 + prefix, localName = _get_prefix_and_localName(name)
1.177 + if prefix is not None:
1.178 + node.setNsProp(node.newNs(ns, prefix), localName, value)
1.179 + elif ns is not None and ns == node.ns().content:
1.180 + node.setNsProp(node.ns(), localName, value)
1.181 + else:
1.182 + # NOTE: Needs verifying: what should happen to the namespace?
1.183 + # NOTE: This also catches the case where None is the element's
1.184 + # NOTE: namespace and is also used for the attribute.
1.185 + node.setNsProp(None, localName, value)
1.186 +
1.187 +def Node_setAttribute(node, name, value):
1.188 + # NOTE: Need to convert from Unicode.
1.189 + name, value = map(from_unicode, [name, value])
1.190 +
1.191 + node.setProp(name, value)
1.192 +
1.193 +def Node_setAttributeNodeNS(node, ns, name, attr):
1.194 + # NOTE: Not actually putting the node on the element.
1.195 + Node_setAttributeNS(node, ns, name, Node_nodeValue(attr))
1.196 +
1.197 +def Node_setAttributeNode(node, name, attr):
1.198 + # NOTE: Not actually putting the node on the element.
1.199 + Node_setAttribute(node, name, Node_nodeValue(attr))
1.200 +
1.201 +def Node_createElementNS(node, ns, name):
1.202 + # NOTE: Need to convert from Unicode.
1.203 + ns, name = map(from_unicode, [ns, name])
1.204 +
1.205 + prefix, localName = _get_prefix_and_localName(name)
1.206 + new_node = libxml2.newNode(localName)
1.207 + # NOTE: Does it make sense to set the namespace if it is empty?
1.208 + if ns is not None:
1.209 + new_ns = new_node.newNs(ns, prefix)
1.210 + new_node.setNs(new_ns)
1.211 + return new_node
1.212 +
1.213 +def Node_createElement(node, name):
1.214 + # NOTE: Need to convert from Unicode.
1.215 + name = from_unicode(name)
1.216 +
1.217 + new_node = libxml2.newNode(name)
1.218 + return new_node
1.219 +
1.220 +def Node_createAttributeNS(node, ns, name):
1.221 + # NOTE: Need to convert from Unicode.
1.222 + ns, name = map(from_unicode, [ns, name])
1.223 +
1.224 + prefix, localName = _get_prefix_and_localName(name)
1.225 + # NOTE: Does it make sense to set the namespace if it is empty?
1.226 + if ns is not None:
1.227 + new_ns = new_node.newNs(ns, prefix)
1.228 + else:
1.229 + new_ns = None
1.230 + return TemporaryNode(new_ns, localName)
1.231 +
1.232 +def Node_createAttribute(node, name):
1.233 + # NOTE: Need to convert from Unicode.
1.234 + name = from_unicode(name)
1.235 +
1.236 + return TemporaryNode(None, name)
1.237 +
1.238 +def Node_createTextNode(node, value):
1.239 + # NOTE: Need to convert from Unicode.
1.240 + value = from_unicode(value)
1.241 +
1.242 + return libxml2.newText(value)
1.243 +
1.244 +def Node_createComment(node, value):
1.245 + # NOTE: Need to convert from Unicode.
1.246 + value = from_unicode(value)
1.247 +
1.248 + return libxml2.newComment(value)
1.249 +
1.250 +def _add_node(node, tmp):
1.251 + if tmp.ns is not None:
1.252 + child = node.newNsProp(None, Node_localName(tmp), None)
1.253 + ns = child.newNs(Node_namespaceURI(tmp), Node_prefix(tmp))
1.254 + child.setNs(ns)
1.255 + else:
1.256 + child = node.newProp(None, tmp.name, None)
1.257 +
1.258 + return child
1.259 +
1.260 +def Node_insertBefore(node, tmp, oldNode):
1.261 + if isinstance(tmp, TemporaryNode):
1.262 + child = _add_node(tmp)
1.263 + else:
1.264 + child = tmp
1.265 + return oldNode.addPrevSibling(child)
1.266 +
1.267 +def Node_replaceChild(node, tmp, oldNode):
1.268 + if isinstance(tmp, TemporaryNode):
1.269 + child = _add_node(tmp)
1.270 + else:
1.271 + child = tmp
1.272 + return oldNode.replaceNode(child)
1.273 +
1.274 +def Node_appendChild(node, tmp):
1.275 + return node.addChild(tmp)
1.276 +
1.277 +def Node_removeChild(node, child):
1.278 + child.unlinkNode()
1.279 +
1.280 +def Node_xpath(node, expr, variables=None, namespaces=None):
1.281 + context = Node_ownerDocument(node).xpathNewContext()
1.282 + context.setContextNode(node)
1.283 + # NOTE: Discover namespaces from the node.
1.284 + for prefix, ns in (namespaces or {}).items():
1.285 + context.xpathRegisterNs(prefix, ns)
1.286 + # NOTE: May need to tidy up the context.
1.287 + return context.xpathEval(expr)
1.288 +
1.289 +# Utility functions.
1.290 +
1.291 +def createDocumentType(localName, publicId, systemId):
1.292 + return None
1.293 +
1.294 +def createDocument(namespaceURI, localName, doctype):
1.295 + # NOTE: Fixed to use version 1.0 only.
1.296 + d = libxml2.newDoc("1.0")
1.297 + if localName is not None:
1.298 + root = Node_createElementNS(d, namespaceURI, localName)
1.299 + Node_appendChild(d, root)
1.300 + return d
1.301 +
1.302 +def parse(stream_or_string):
1.303 + if hasattr(stream_or_string, "read"):
1.304 + stream = stream_or_string
1.305 + return parseString(stream.read())
1.306 + else:
1.307 + return parseFile(stream_or_string)
1.308 +
1.309 +def parseFile(s):
1.310 + # NOTE: Switching off validation and remote DTD resolution.
1.311 + context = libxml2.createFileParserCtxt(s)
1.312 + context.validate(0)
1.313 + context.ctxtUseOptions(0)
1.314 + context.parseDocument()
1.315 + return context.doc()
1.316 +
1.317 +def parseString(s):
1.318 + # NOTE: Switching off validation and remote DTD resolution.
1.319 + context = libxml2.createMemoryParserCtxt(s, len(s))
1.320 + context.validate(0)
1.321 + context.ctxtUseOptions(0)
1.322 + context.parseDocument()
1.323 + return context.doc()
1.324 +
1.325 +def parseURI(uri):
1.326 + return libxml2.parseURI(uri)
1.327 +
1.328 +# vim: tabstop=4 expandtab shiftwidth=4