# HG changeset patch # User paulb # Date 1105717143 0 # Node ID 014f4a1693149544dc03d8ef8a37bc2fa3004052 # Parent 6462196b007b01ec110a2853e1021d73c96a2b46 [project @ 2005-01-14 15:39:02 by paulb] Added the beginnings of a macro library variant of libxml2dom. diff -r 6462196b007b -r 014f4a169314 libxml2dom/macrolib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libxml2dom/macrolib.py Fri Jan 14 15:39:03 2005 +0000 @@ -0,0 +1,116 @@ +#!/usr/bin/env python + +""" +DOM macros for libxml2. +""" + +__version__ = "0.1.2" + +import xml.dom +import libxml2 +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 + +_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 Node_nodeType(node): + global _nodesTypes + return _nodeTypes[node.type] + +def Node_childNodes(node): + + # NOTE: Consider a generator instead. + + child_nodes = [] + node = node.children + while node is not None: + child_nodes.append(node) + node = node.next + return child_nodes + +def _getNs(node): + + "Internal namespace information retrieval." + + try: + return node.ns() + except libxml2.treeError: + return None + +def Node_namespaceURI(node): + ns = _getNs(node) + if ns is not None: + return to_unicode(ns.content) + else: + return None + +def Node_nodeValue(node): + return to_unicode(node.content) + +def Node_prefix(node): + ns = _getNs(node) + if ns is not None: + return to_unicode(ns.name) + else: + return None + +def Node_nodeName(node): + prefix = Node_prefix(node) + if prefix is not None: + return prefix + ":" + Node_localName(node) + else: + return Node_localName(node) + +def Node_tagName(node): + if node.type == "element": + return Node_nodeName(node) + else: + return None + +def Node_localName(node): + return to_unicode(node.name) + +def Node_parentNode(node): + if node.type == "document_xml": + return None + else: + return node.parent + +def Node_previousSibling(node): + if node.prev is not None: + return node.prev + else: + return None + +def Node_nextSibling(node): + if node.next is not None: + return node.next + else: + return None + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 6462196b007b -r 014f4a169314 libxml2macro.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libxml2macro.py Fri Jan 14 15:39:03 2005 +0000 @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +import compiler + +def process_nodes(root_node, prefix): + + """ + Under the 'root_node', process all suitable expression nodes which employ + Name nodes using the given 'prefix'. + """ + + for node in root_node.getChildNodes(): + # Identify suitable names and add such nodes + if isinstance(node, compiler.ast.CallFunc): + process_callfunc(node, prefix) + elif isinstance(node, compiler.ast.Getattr): + process_getattr(node, prefix, root_node) + else: + process_nodes(node, prefix) + +def process_callfunc(node, prefix): + # Check the target. + target = node.node + if isinstance(target, compiler.ast.Getattr): + process_getattr(target, prefix, node) + else: + process_nodes(node, prefix) + +def process_getattr(node, prefix, parent): + # Check the target. + target = node.expr + if isinstance(target, compiler.ast.Name) and target.name.startswith(prefix): + + # Replace CallFunc plus Getattr occurrences: + # node.attr(args) -> Node_attr(node, args) + + if isinstance(parent, compiler.ast.CallFunc): + parent.node = compiler.ast.Name("Node_%s" % node.attrname) + parent.args.insert(0, compiler.ast.Name(target.name)) + + # Replace plain Getattr nodes: + # node.attr -> Node_attr(node) + # NOTE: Nasty but necessary rewiring of the parent node required. + + else: + replacement = compiler.ast.CallFunc( + compiler.ast.Name("Node_%s" % node.attrname), + [node.expr] + ) + for key, value in parent.__dict__.items(): + # Detect lists. + try: + if node in value: + index = value.index(node) + value[index] = replacement + except TypeError: + if value is node: + parent.__dict__[key] = replacement + else: + process_nodes(node, prefix) + +def process_file(filename, prefix="x2_"): + + """ + Process the module given by the specified 'filename'. The optional special + 'prefix' marks those variables to be processed. + """ + + # Open the module as an AST. + + module = compiler.parseFile(filename) + + # Find references to special variables. + + process_nodes(module, prefix) + return module + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 6462196b007b -r 014f4a169314 macrotest.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/macrotest.py Fri Jan 14 15:39:03 2005 +0000 @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +"A test of macros." + +from libxml2dom.macrolib import * +import libxml2 +import xml.dom +import sys + +x2_d = libxml2.parseFile(sys.argv[1]) +x2_root = None +for x2_n in x2_d.childNodes: + if x2_n.nodeType == xml.dom.Node.ELEMENT_NODE: + x2_root = x2_n + break + +print x2_root.localName, x2_root.namespaceURI, x2_root.getAttributeNS(None, "xmlns") + +# vim: tabstop=4 expandtab shiftwidth=4