1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
'''transform.py: Document / grove transformation framework.
This module provides:
- a Transformer abstract base class, meant to be subclassed with ``do_*''
methods, where ``*'' stands for possible element tag names.
- various helper functions.
Issues: currently, the document or grove passed to a transformer is
tranformed in place, it might be better to keep the original.
'''
from xml.dom.core import *
def having(list, condition):
'Filter nodes in <list> having <condition>.'
#code = compile(condition)
res = []
for x in list:
try:
if eval(condition, {'this' : x}, {}):
res.append(x)
except:
pass
return res
def cdata(list):
'Flatten a node list.'
s = ''
for node in list:
if node.NodeType == TEXT:
s = s + node.data
elif node.NodeType == ELEMENT:
s = s + cdata(node.getChildren())
return s
class Transformer:
simple_map = {}
def __init__(self, factory=None):
if factory:
self.dom_factory = factory
else:
self.dom_factory = DOMFactory()
def transform(self, x):
'Tranform document or subtree.'
if x.NodeType == DOCUMENT:
root_element = x.documentElement
else:
root_element = x
res = self._transform_node(root_element)[0]
if x.NodeType == DOCUMENT:
x.documentElement = res
return x
else:
return res
def _transform_node(self, node):
'Transform node (currently, only elements are affected).'
if node.NodeType == ELEMENT:
new_children = []
for child in node.getChildren():
new_children = new_children + self._transform_node(child)
node._children = new_children
repl = self.simple_map.get(node.tagName)
if repl:
return self.transform_simple(node, repl)
if hasattr(self, 'do_' + node.tagName):
return getattr(self, 'do_' + node.tagName)(node)
if hasattr(self, 'do_ANY'):
return self.do_ANY(node)
return [node]
def transform_simple(self, node, repl):
"Transform element using `simple' replacement."
l = string.split(repl, '/')
l.reverse()
new_node = None
for tag in l:
new_new_node = self.dom_factory.createElement(tag, {})
if new_node:
new_node.insertBefore(new_new_node, None)
else:
for child in node.getChildren():
new_new_node.insertBefore(child, None)
new_node = new_new_node
return [new_node]
# vim:ts=2:ai
|