File: transformer.py

package info (click to toggle)
python-xml 0.4.19981014-1
  • links: PTS
  • area: main
  • in suites: slink
  • size: 2,124 kB
  • ctags: 3,099
  • sloc: ansic: 9,075; python: 8,150; xml: 7,940; makefile: 84; sh: 41
file content (107 lines) | stat: -rw-r--r-- 2,293 bytes parent folder | download
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