Mercurial > mez_xml
comparison mez_xml.py @ 0:3679d2d8443a
Import from CVS and goto mez_xml-0.4
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Wed, 13 Feb 2008 22:33:51 +0800 |
parents | |
children | d310e097c6de |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3679d2d8443a |
---|---|
1 from xml.dom.minidom import parse | |
2 import re | |
3 | |
4 reo_attr_rep = re.compile('\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}') | |
5 reserved_keywords = {'commit': None, 'gen_doc': None} | |
6 | |
7 def clz_name(fn): | |
8 from os import path | |
9 return path.basename(fn).split('.')[0] | |
10 | |
11 def _check_reserved(name): | |
12 if name.startswith('_') or reserved_keywords.has_key(name): | |
13 raise NameError, '%s is a reserved keyword' % (name,) | |
14 pass | |
15 | |
16 class mez_xml(object): | |
17 def __init__(self): | |
18 super(mez_xml, self).__init__() | |
19 pass | |
20 | |
21 def template_head(self): | |
22 self.output_cmd_line('from mez_xml.tools import nez_web') | |
23 self.output_cmd_line('') | |
24 self.output_cmd_line('class %s(nez_web):' % (self.cname,)) | |
25 self.dig() | |
26 self.output_cmd_line('def __init__(self, ofo):') | |
27 self.dig() | |
28 self.output_cmd_line('super(%s, self).__init__()' % (self.cname,)) | |
29 self.output_cmd_line('self.ofo = ofo') | |
30 self.output_cmd_line('pass') | |
31 self.back() | |
32 self.output_cmd_line('') | |
33 pass | |
34 | |
35 def template_tail(self): | |
36 self.output_cmd_line('pass') | |
37 self.back() | |
38 self.output_cmd_line('') | |
39 pass | |
40 | |
41 def subtree_start(self, cname): | |
42 self.output_cmd_line('def %s(self, pdata, cdata):' % (cname)) | |
43 self.dig() | |
44 self.output_cmd_line('def temp(data):') | |
45 self.dig() | |
46 self.frag_start() | |
47 pass | |
48 | |
49 def subtree_stop(self, cname): | |
50 self.frag_stop() | |
51 self.output_cmd_line('pass') | |
52 self.back() | |
53 self.output_cmd_line('self._feed_subtree(temp, pdata, cdata)') | |
54 self.output_cmd_line('pass') | |
55 self.back() | |
56 self.output_cmd_line('') | |
57 pass | |
58 | |
59 def _expand_vars(self, data, _tp): | |
60 mo = reo_attr_rep.search(data) | |
61 pos = 0 | |
62 while mo: | |
63 if pos != mo.start(): | |
64 self.output(data[pos:mo.start()]) | |
65 pass | |
66 self.frag_stop() | |
67 name = mo.group(1) | |
68 subnames = name.split('.') | |
69 first = subnames[0] | |
70 self.output_cmd_line('odata = data.setdefault(\'%s\', {})' % (first)) | |
71 for subname in subnames[1:]: | |
72 self.output_cmd_line('odata = odata.setdefault(\'%s\', {})' % (subname)) | |
73 pass | |
74 self.output_cmd_line('self.ofo.write(self._esc_%s(odata))' % (_tp)) | |
75 self.frag_start() | |
76 pos = mo.end() | |
77 for subname in subnames: | |
78 _check_reserved(subname) | |
79 pass | |
80 #if not self.all_names.has_key(name): | |
81 #if not self.all_attrnames.has_key(name): | |
82 # self.travel_q.append((name, None)) | |
83 # self.all_attrnames[name] = None | |
84 # pass | |
85 #pass | |
86 #else: | |
87 #raise NameError, '%s is redefined' % (name,) | |
88 mo = reo_attr_rep.search(data, pos) | |
89 pass | |
90 self.output(data[pos:]) | |
91 pass | |
92 | |
93 def _expand_comm(self, data): | |
94 self._expand_vars(data, 'comm') | |
95 pass | |
96 | |
97 def _expand_param(self, data): | |
98 self._expand_vars(data, 'param') | |
99 pass | |
100 | |
101 def _expand_text(self, data,): | |
102 self._expand_vars(data, 'text') | |
103 pass | |
104 | |
105 def _expand_cdata(self, data): | |
106 self._expand_vars(data, 'cdata') | |
107 pass | |
108 | |
109 def gen_attrs(self, attrs): | |
110 for i in range(attrs.length): | |
111 attr = attrs.item(i) | |
112 self.output(' ' + attr.name) | |
113 val = attr.nodeValue | |
114 if val: | |
115 self.output('="') | |
116 self._expand_param(val) | |
117 self.output('"') | |
118 pass | |
119 pass | |
120 pass | |
121 | |
122 def tag_start(self, no): | |
123 from xml.dom import Node | |
124 nt = no.nodeType | |
125 if nt == Node.CDATA_SECTION_NODE: | |
126 self.output('<![CDATA[') | |
127 self._expand_cdata(no.data) | |
128 self.output(']]>') | |
129 elif nt == Node.COMMENT_NODE: | |
130 self.output('<!--') | |
131 self._expand_comm(no.data); | |
132 self.output('-->') | |
133 elif nt == Node.TEXT_NODE: | |
134 self._expand_text(no.data); | |
135 elif nt == Node.ELEMENT_NODE: | |
136 self.output('<' + no.tagName) | |
137 self.gen_attrs(no.attributes) | |
138 self.output('>') | |
139 pass | |
140 | |
141 def tag_stop(self, no): | |
142 from xml.dom import Node | |
143 nt = no.nodeType | |
144 if nt == Node.ELEMENT_NODE: | |
145 self.output('</%s>' % (no.tagName,)) | |
146 pass | |
147 pass | |
148 | |
149 def frag_start(self): | |
150 self.output_cmd('self.ofo.write(\'\'\'') | |
151 pass | |
152 | |
153 def frag_stop(self): | |
154 self.output_raw('\'\'\')\n') | |
155 pass | |
156 | |
157 def call_subtree(self, no): | |
158 name = no.getAttribute('ezid') | |
159 self.frag_stop() | |
160 subnames = name.split('.') | |
161 first = subnames[0] | |
162 self.output_cmd_line('cdata = data.setdefault(\'%s\', {})' % (first)) | |
163 for subname in subnames[1:]: | |
164 self.output_cmd_line('cdata = cdata.setdefault(\'%s\', {})' % (subname)) | |
165 pass | |
166 last = subnames[-1] | |
167 self.output_cmd_line('self.%s(data, cdata)' % (last)) | |
168 self.frag_start() | |
169 pass | |
170 | |
171 def gen_node_template(self, name, node): | |
172 from xml.dom import Node | |
173 fw_q = [node] | |
174 | |
175 def trackback(no): | |
176 while no != node and no.parentNode and not no.nextSibling: | |
177 no = no.parentNode | |
178 self.tag_stop(no) | |
179 pass | |
180 pass | |
181 | |
182 first = True | |
183 while fw_q: | |
184 no = fw_q.pop() | |
185 if (not first) and no.nodeType == Node.ELEMENT_NODE and no.hasAttributes() and no.hasAttribute('ezid'): | |
186 name = no.getAttribute('ezid').split('.')[-1] | |
187 _check_reserved(name) | |
188 if not self.all_names.has_key(name) and not self.all_attrnames.has_key(name): | |
189 self.travel_q.append((name, no)) | |
190 self.all_names[name] = None | |
191 else: | |
192 raise NameError, '%s is redefined' % (name,) | |
193 self.call_subtree(no) | |
194 trackback(no) | |
195 else: | |
196 self.tag_start(no) | |
197 if not no.hasChildNodes(): | |
198 self.tag_stop(no) | |
199 trackback(no) | |
200 else: | |
201 children = [no.childNodes.item(i) for i in range(no.childNodes.length)] | |
202 children.reverse() | |
203 fw_q.extend(children) | |
204 pass | |
205 pass | |
206 first = False | |
207 pass | |
208 pass | |
209 | |
210 def dig(self): | |
211 self.indent = self.indent + 4 | |
212 pass | |
213 | |
214 def back(self): | |
215 self.indent = self.indent - 4 | |
216 pass | |
217 | |
218 def output_cmd(self, msg): | |
219 self.ofo.write(' ' * self.indent) | |
220 self.ofo.write(msg) | |
221 pass | |
222 | |
223 def output_cmd_line(self, msg): | |
224 self.ofo.write(' ' * self.indent) | |
225 self.ofo.write(msg) | |
226 self.ofo.write('\n') | |
227 pass | |
228 | |
229 def output_raw(self, msg): | |
230 self.ofo.write(msg) | |
231 pass | |
232 | |
233 def output(self, msg): | |
234 parts = msg.split('\\') | |
235 if len(parts) > 0: | |
236 msg = '\\\\'.join(parts) | |
237 pass | |
238 if len(msg) > 0 and msg[-1] == '\'': | |
239 msg = msg[:-1] + '\\\'' | |
240 pass | |
241 parts = msg.split('\'\'\'') | |
242 if len(parts) > 1: | |
243 msg = '\\\'\\\'\\\''.join(parts) | |
244 pass | |
245 self.ofo.write(msg) | |
246 pass | |
247 | |
248 def start(self, fn, ifo, ofo): | |
249 self.ofo = ofo | |
250 self.indent = 0 | |
251 | |
252 cname = clz_name(fn) | |
253 dom = parse(ifo) | |
254 self.travel_q = [('_root', dom)] | |
255 self.cname = cname | |
256 self.all_names = {} | |
257 self.all_attrnames = {} | |
258 | |
259 self.travel_tree() | |
260 pass | |
261 | |
262 def travel_tree(self): | |
263 self.template_head() | |
264 | |
265 travel_q = self.travel_q | |
266 while travel_q: | |
267 name, node = travel_q[0] | |
268 self.subtree_start(name) | |
269 del travel_q[0] | |
270 if node: | |
271 self.gen_node_template(name, node) | |
272 pass | |
273 self.subtree_stop(name) | |
274 pass | |
275 | |
276 self.template_tail() | |
277 pass | |
278 pass | |
279 | |
280 if __name__ == '__main__': | |
281 import sys | |
282 import locale | |
283 | |
284 if len(sys.argv) != 2: | |
285 sys.exit(1) | |
286 pass | |
287 | |
288 class fakefile(object): | |
289 pass | |
290 | |
291 fn = sys.argv[1] | |
292 fo = file(fn, 'r') | |
293 encoding = locale.getpreferredencoding() | |
294 stdout = fakefile() | |
295 oldwrite = sys.stdout.write | |
296 stdout.write = lambda x: oldwrite(x.encode(encoding)) | |
297 | |
298 if encoding != 'ascii': | |
299 print >> stdout, '# -*- coding: %s' % (encoding,) | |
300 pass | |
301 | |
302 mex = mez_xml() | |
303 mex.start(fn, fo, stdout) | |
304 pass |