Mercurial > mez_xml
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mez_xml.py Wed Feb 13 22:33:51 2008 +0800 @@ -0,0 +1,304 @@ +from xml.dom.minidom import parse +import re + +reo_attr_rep = re.compile('\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}') +reserved_keywords = {'commit': None, 'gen_doc': None} + +def clz_name(fn): + from os import path + return path.basename(fn).split('.')[0] + +def _check_reserved(name): + if name.startswith('_') or reserved_keywords.has_key(name): + raise NameError, '%s is a reserved keyword' % (name,) + pass + +class mez_xml(object): + def __init__(self): + super(mez_xml, self).__init__() + pass + + def template_head(self): + self.output_cmd_line('from mez_xml.tools import nez_web') + self.output_cmd_line('') + self.output_cmd_line('class %s(nez_web):' % (self.cname,)) + self.dig() + self.output_cmd_line('def __init__(self, ofo):') + self.dig() + self.output_cmd_line('super(%s, self).__init__()' % (self.cname,)) + self.output_cmd_line('self.ofo = ofo') + self.output_cmd_line('pass') + self.back() + self.output_cmd_line('') + pass + + def template_tail(self): + self.output_cmd_line('pass') + self.back() + self.output_cmd_line('') + pass + + def subtree_start(self, cname): + self.output_cmd_line('def %s(self, pdata, cdata):' % (cname)) + self.dig() + self.output_cmd_line('def temp(data):') + self.dig() + self.frag_start() + pass + + def subtree_stop(self, cname): + self.frag_stop() + self.output_cmd_line('pass') + self.back() + self.output_cmd_line('self._feed_subtree(temp, pdata, cdata)') + self.output_cmd_line('pass') + self.back() + self.output_cmd_line('') + pass + + def _expand_vars(self, data, _tp): + mo = reo_attr_rep.search(data) + pos = 0 + while mo: + if pos != mo.start(): + self.output(data[pos:mo.start()]) + pass + self.frag_stop() + name = mo.group(1) + subnames = name.split('.') + first = subnames[0] + self.output_cmd_line('odata = data.setdefault(\'%s\', {})' % (first)) + for subname in subnames[1:]: + self.output_cmd_line('odata = odata.setdefault(\'%s\', {})' % (subname)) + pass + self.output_cmd_line('self.ofo.write(self._esc_%s(odata))' % (_tp)) + self.frag_start() + pos = mo.end() + for subname in subnames: + _check_reserved(subname) + pass + #if not self.all_names.has_key(name): + #if not self.all_attrnames.has_key(name): + # self.travel_q.append((name, None)) + # self.all_attrnames[name] = None + # pass + #pass + #else: + #raise NameError, '%s is redefined' % (name,) + mo = reo_attr_rep.search(data, pos) + pass + self.output(data[pos:]) + pass + + def _expand_comm(self, data): + self._expand_vars(data, 'comm') + pass + + def _expand_param(self, data): + self._expand_vars(data, 'param') + pass + + def _expand_text(self, data,): + self._expand_vars(data, 'text') + pass + + def _expand_cdata(self, data): + self._expand_vars(data, 'cdata') + pass + + def gen_attrs(self, attrs): + for i in range(attrs.length): + attr = attrs.item(i) + self.output(' ' + attr.name) + val = attr.nodeValue + if val: + self.output('="') + self._expand_param(val) + self.output('"') + pass + pass + pass + + def tag_start(self, no): + from xml.dom import Node + nt = no.nodeType + if nt == Node.CDATA_SECTION_NODE: + self.output('<![CDATA[') + self._expand_cdata(no.data) + self.output(']]>') + elif nt == Node.COMMENT_NODE: + self.output('<!--') + self._expand_comm(no.data); + self.output('-->') + elif nt == Node.TEXT_NODE: + self._expand_text(no.data); + elif nt == Node.ELEMENT_NODE: + self.output('<' + no.tagName) + self.gen_attrs(no.attributes) + self.output('>') + pass + + def tag_stop(self, no): + from xml.dom import Node + nt = no.nodeType + if nt == Node.ELEMENT_NODE: + self.output('</%s>' % (no.tagName,)) + pass + pass + + def frag_start(self): + self.output_cmd('self.ofo.write(\'\'\'') + pass + + def frag_stop(self): + self.output_raw('\'\'\')\n') + pass + + def call_subtree(self, no): + name = no.getAttribute('ezid') + self.frag_stop() + subnames = name.split('.') + first = subnames[0] + self.output_cmd_line('cdata = data.setdefault(\'%s\', {})' % (first)) + for subname in subnames[1:]: + self.output_cmd_line('cdata = cdata.setdefault(\'%s\', {})' % (subname)) + pass + last = subnames[-1] + self.output_cmd_line('self.%s(data, cdata)' % (last)) + self.frag_start() + pass + + def gen_node_template(self, name, node): + from xml.dom import Node + fw_q = [node] + + def trackback(no): + while no != node and no.parentNode and not no.nextSibling: + no = no.parentNode + self.tag_stop(no) + pass + pass + + first = True + while fw_q: + no = fw_q.pop() + if (not first) and no.nodeType == Node.ELEMENT_NODE and no.hasAttributes() and no.hasAttribute('ezid'): + name = no.getAttribute('ezid').split('.')[-1] + _check_reserved(name) + if not self.all_names.has_key(name) and not self.all_attrnames.has_key(name): + self.travel_q.append((name, no)) + self.all_names[name] = None + else: + raise NameError, '%s is redefined' % (name,) + self.call_subtree(no) + trackback(no) + else: + self.tag_start(no) + if not no.hasChildNodes(): + self.tag_stop(no) + trackback(no) + else: + children = [no.childNodes.item(i) for i in range(no.childNodes.length)] + children.reverse() + fw_q.extend(children) + pass + pass + first = False + pass + pass + + def dig(self): + self.indent = self.indent + 4 + pass + + def back(self): + self.indent = self.indent - 4 + pass + + def output_cmd(self, msg): + self.ofo.write(' ' * self.indent) + self.ofo.write(msg) + pass + + def output_cmd_line(self, msg): + self.ofo.write(' ' * self.indent) + self.ofo.write(msg) + self.ofo.write('\n') + pass + + def output_raw(self, msg): + self.ofo.write(msg) + pass + + def output(self, msg): + parts = msg.split('\\') + if len(parts) > 0: + msg = '\\\\'.join(parts) + pass + if len(msg) > 0 and msg[-1] == '\'': + msg = msg[:-1] + '\\\'' + pass + parts = msg.split('\'\'\'') + if len(parts) > 1: + msg = '\\\'\\\'\\\''.join(parts) + pass + self.ofo.write(msg) + pass + + def start(self, fn, ifo, ofo): + self.ofo = ofo + self.indent = 0 + + cname = clz_name(fn) + dom = parse(ifo) + self.travel_q = [('_root', dom)] + self.cname = cname + self.all_names = {} + self.all_attrnames = {} + + self.travel_tree() + pass + + def travel_tree(self): + self.template_head() + + travel_q = self.travel_q + while travel_q: + name, node = travel_q[0] + self.subtree_start(name) + del travel_q[0] + if node: + self.gen_node_template(name, node) + pass + self.subtree_stop(name) + pass + + self.template_tail() + pass + pass + +if __name__ == '__main__': + import sys + import locale + + if len(sys.argv) != 2: + sys.exit(1) + pass + + class fakefile(object): + pass + + fn = sys.argv[1] + fo = file(fn, 'r') + encoding = locale.getpreferredencoding() + stdout = fakefile() + oldwrite = sys.stdout.write + stdout.write = lambda x: oldwrite(x.encode(encoding)) + + if encoding != 'ascii': + print >> stdout, '# -*- coding: %s' % (encoding,) + pass + + mex = mez_xml() + mex.start(fn, fo, stdout) + pass