📄 generatehtml.py
字号:
#!/usr/bin/env python
import string, os, sys
try:
from xml.dom import Node
from xml.dom.ext.reader import Sax
Reader = Sax.FromXmlFile
except ImportError:
print 'You need to have PyXML installed to run this program'
sys.exit(1)
def Generate(fileName,
output_dir=None,
program_name=None
):
output_dir = output_dir or '.'
dom = Reader(fileName)
header = CreateHeader(dom, program_name)
classes = dom.getElementsByTagName('class')
outfiles = []
for klass in classes:
outfiles.append(GenClassFile(klass, header, output_dir))
return outfiles
def CreateHeader(dom, prog_name):
result = ''
header = dom.getElementsByTagName('header')
if header:
result = result + string.strip(header[0].childNodes[0].data)
result = result + '\n\n'
if prog_name:
add_str = ' by ' + prog_name
else:
add_str = ''
result = result + '### This file is automatically generated%s.\n' % add_str
result = result + '### DO NOT EDIT!\n\n'
copyright = dom.getElementsByTagName('copyright')
if copyright:
result = result + '"""\n'
result = result + string.strip(copyright[0].childNodes[0].data) + '\n'
result = result + '"""\n\n'
return result
# Helper function for indenting Python
def indent(count, text, tab=' '*4):
return tab*count + text
# Get/Set routines for DOMString attributes
def stringGetAttr(name, value):
return indent(2, 'return self.getAttribute("%s")\n\n' % name)
def stringSetAttr(name):
return indent(2, 'self.setAttribute("%s", value)\n\n' % name)
# Routines for boolean attributes
def boolGetAttr(name, value):
return indent(2, 'return self.hasAttribute("%s")\n\n' % name)
def boolSetAttr(name):
result = indent(2, 'if value:\n')
result = result + indent(3, 'self.setAttribute("%s", "%s")\n' % (name, name))
result = result + indent(2, 'else:\n')
result = result + indent(3, 'self.removeAttribute("%s")\n\n' % name)
return result
# Routines for number attributes
def longGetAttr(name, value):
result = indent(2, 'value = self.getAttribute("%s")\n' % name)
result = result + indent(2, 'if value:\n')
result = result + indent(3, 'return int(value)\n')
result = result + indent(2, 'return 0\n\n')
return result
def longSetAttr(name):
return indent(2, 'self.setAttribute("%s", str(value))\n\n' % name)
# Routines for value-list attributes
def listGetAttr(name, value):
return indent(2, 'return string.capitalize(self.getAttribute("%s"))\n\n' % name)
# Routines for attributes mapped to Text nodes
def nodeGetAttr(dummy, value):
result = indent(2, 'if not self.firstChild:\n')
result = result + indent(3, 'return ''\n')
result = result + indent(2, 'if self.firstChild == self.lastChild:\n')
result = result + indent(3, 'return self.firstChild.data\n')
result = result + indent(2, 'self.normalize()\n')
result = result + indent(2, 'text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes)\n')
result = result + indent(2, 'return text[0].data\n\n')
return result
def nodeSetAttr(dummy):
result = indent(2, 'text = None\n')
result = result + indent(2, 'for node in self.childNodes:\n')
result = result + indent(3, 'if not text and node.nodeType == Node.TEXT_NODE:\n')
result = result + indent(4, 'text = node\n')
result = result + indent(3, 'else:\n')
result = result + indent(4, 'self.removeChild(node)\n')
result = result + indent(2, 'if text:\n')
result = result + indent(3, 'text.data = value\n')
result = result + indent(2, 'else:\n')
result = result + indent(3, 'text = self.ownerDocument.createTextNode(value)\n')
result = result + indent(3, 'self.appendChild(text)\n\n')
return result
#Routines for constant attributes
def constGetAttr(name, value):
if not value:
value = 'None'
else:
value = '"%s"' % value
return indent(2, 'return %s\n\n' % value)
#Routines for form based classes
def formGetAttr(dummy,dummy2):
result = indent(2, 'parent = self.parentNode\n')
result = result + indent(2, 'while parent:\n')
result = result + indent(3, 'if parent.nodeName == "FORM":\n')
result = result + indent(4, 'return parent\n')
result = result + indent(3, 'parent = parent.parentNode\n')
result = result + indent(2, 'return None\n\n')
return result
g_valueTypeMap = {
'bool' : (boolGetAttr, boolSetAttr),
'long' : (longGetAttr, longSetAttr),
'list' : (listGetAttr, stringSetAttr),
'node' : (nodeGetAttr, nodeSetAttr),
'string' : (stringGetAttr, stringSetAttr),
'form' : (formGetAttr, None),
'const' : (constGetAttr, None)
}
def GenClassFile(klass, header, output_dir):
class_name = 'HTML%sElement' % klass.getAttribute('name')
fileName = os.path.join(output_dir,class_name + '.py')
file = open(fileName, 'w')
# General header stuff
file.write(string.replace(header, '$FILE$', class_name))
# Import statements
file.write('import string\n')
file.write('from xml.dom import Node\n')
baseclass = klass.getElementsByTagName('baseclass')[0].getAttribute('name')
base_name = string.split(baseclass, '.')[-1]
file.write('from %s import %s\n' % (baseclass, base_name))
file.write('\n')
# Class declaration
file.write('class %s(%s):\n\n' % (class_name, base_name))
# Constructor
file.write(indent(1, 'def __init__(self, ownerDocument, nodeName'))
multiple = klass.getAttribute('multiple')
tag_name = klass.getAttribute('tagname')
if not multiple:
if not tag_name:
tag_name = string.upper(klass.getAttribute('name'))
file.write('="%s"' % tag_name)
file.write('):\n')
file.write(indent(2, '%s.__init__(self, ownerDocument, nodeName)\n\n' % base_name))
# Attributes
file.write(indent(1, '### Attribute Methods ###\n\n'))
attrs = klass.getElementsByTagName('attribute')
read_attrs = []
write_attrs = []
for attr in attrs:
dom_name = attr.getAttribute('name')
value_type = attr.getAttribute('type')
html_name = attr.getAttribute('htmlname')
if not html_name:
html_name = string.upper(dom_name)
value = attr.getAttribute('value') # for const value-type
permissions = attr.getElementsByTagName('permissions')[0]
readable = int(permissions.getAttribute('readable'))
writeable = int(permissions.getAttribute('writeable'))
if readable:
file.write(indent(1, 'def _get_%s(self):\n' % dom_name))
get_func = g_valueTypeMap[value_type][0]
file.write(get_func(html_name, value))
read_attrs.append(dom_name)
if writeable:
file.write(indent(1, 'def _set_%s(self, value):\n' % dom_name))
set_func = g_valueTypeMap[value_type][1]
try:
file.write(set_func(html_name or value))
except:
raise "Set function '%s' in class %s, attribute %s" % (value_type, class_name, dom_name)
write_attrs.append(dom_name)
# Methods
methods = klass.getElementsByTagName('method')
if methods:
file.write(indent(1, '### Methods ###\n\n'))
for method in methods:
method_name = method.getAttribute('name')
params = method.getElementsByTagName('params')[0].childNodes
param_list = []
for param in params:
arg = param.getAttribute('name')
default = param.firstChild
param_list.append((arg,default))
file.write(indent(1, 'def %s(self' % method_name))
for arg,default in param_list:
file.write(', %s' % arg)
if default:
file.write('=%s' % default.data)
file.write('):\n')
# The function code
code = method.getElementsByTagName('code')[0].firstChild
if code:
lines = string.split(string.strip(code.data), '\n')
for line in lines:
writeTab(file, 2, line)
else:
file.write(indent(2, 'pass\n'))
file.write('\n')
# Attribute access control
file.write(indent(1, '### Attribute Access Mappings ###\n\n'))
file.write(indent(1, '_readComputedAttrs = %s._readComputedAttrs.copy()\n' % base_name))
if len(read_attrs):
file.write(indent(1, '_readComputedAttrs.update({\n'))
for attr in read_attrs[:-1]:
file.write(indent(2, '"%s" : _get_%s,\n' % (attr, attr)))
attr = read_attrs[-1]
file.write(indent(2, '"%s" : _get_%s\n' % (attr, attr)))
file.write(indent(2, '})\n\n'))
file.write(indent(1, '_writeComputedAttrs = %s._writeComputedAttrs.copy()\n' % base_name))
if len(write_attrs):
file.write(indent(1, '_writeComputedAttrs.update({\n'))
for attr in write_attrs[:-1]:
file.write(indent(2, '"%s" : _set_%s,\n' % (attr, attr)))
attr = write_attrs[-1]
file.write(indent(2, '"%s" : _set_%s\n' % (attr, attr)))
file.write(indent(2, '})\n\n'))
file.write(indent(1, '_readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k),\n'))
file.write(indent(1, ' %s._readOnlyAttrs + _readComputedAttrs.keys())\n\n' % base_name))
return fileName
if __name__ == '__main__':
program_name = os.path.basename(sys.argv[0])
output_dir = None
if len(sys.argv) < 2:
print 'Usage: %s input_file [output_dir]' % program_name
sys.exit(1)
elif len(sys.argv) == 3:
output_dir = sys.argv[2]
input_file = sys.argv[1]
Generate(input_file,output_dir,program_name)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -