通用Python 脚本生成模板引擎

-- Zoom.Quiet [DateTime(2004-08-22T02:37:51Z)] TableOfContents

目标

040823 根据个人开发感受,整理模板实现思路

实现途径

XSLT

EXSLT

XSLT有些简单,复杂的数据操作还是不行,但是已经有新的标准进行扩展了!

已有的模板系统

世上无难事,只怕有心人!只要找,总会找到的:

import org.jostraca.resource.SimpleDataObject; import org.jostraca.resource.SimpleDataObjectReader; %> }}}

OtTool解析类

不食嗟来之食! 自力更生!创造自个儿的Py代码模板包!

模板文件可以执行

模板文件不用执行

小新的字典匹配

Zoomq的XML驱动

Limodou的set嵌套

   1 #coding=utf-8
   2 
   3 import re
   4 import sets
   5 import copy
   6 import types
   7 
   8 class T:
   9         def __init__(self, string):
  10                 self.text = string
  11                 
  12         def getText(self):
  13                 return self.text
  14         
  15 class Template:
  16         def __init__(self, beginchars='<#', endchars='#>'):
  17                 self.beginchars = beginchars    #define template var's left delimeter chars
  18                 self.endchars = endchars        #define template var's right delimeter chars
  19         
  20         def load(self, tplname):
  21                 mod = __import__(tplname)
  22                 components = tplname.split('.')
  23                 for comp in components[1:]:
  24                         mod = getattr(mod, comp)
  25 
  26                 self.vars = {}
  27                 self.nodes = {}
  28                 for vn in dir(mod):
  29                         v = getattr(mod, vn)
  30                         if hasattr(v, '__class__') and v.__class__.__name__ == 'T':
  31                                 self.vars[vn] = v
  32                                 self.nodes[vn] = self._get_rely_on_node(v.getText())
  33 
  34         #取模板元素的相关集
  35         def _get_rely_on_node(self, s): #search for %(name)s format, make a dict
  36                 re_node = re.compile(r'%s(\w+)%s' % (self.beginchars, self.endchars))
  37 
  38                 return list(sets.Set(re_node.findall(s)))
  39                 
  40         #取模板元素的生成顺序
  41         def _get_list(self, path, target):
  42                 if not self.vars.has_key(target):
  43                         return
  44                 if target not in path:
  45                         path.append(target)
  46                 for i in self.nodes[target]:
  47                         self._get_list(path, i)
  48                 return
  49 
  50         #生成模板值
  51         #values应为字典的字典。即每一个模板元素如果引用有外部的变量,那么在values中应有此模板元素的一个键。
  52         #同时它的值应为所有外部变量的一个字典
  53         def value(self, target='main', values=None):
  54                 path = []
  55                 self._get_list(path, target)
  56                 path.reverse()
  57                 vals = {}
  58                 for i in path:
  59                         value = self._getElementValue(i, vals, values)
  60                         vals[i] = value
  61                 return vals[target]
  62         
  63         def _replace(self, text, values):
  64                 def dosup(matchobj, values=values):
  65                         if values:
  66                                 return values.get(matchobj.groups()[0], matchobj.group())
  67                         else:
  68                                 return matchobj.group()
  69                 #先将所有已经存在的模板元素进行替换
  70                 return re.sub(r'%s(\w+)%s' % (self.beginchars, self.endchars), dosup, text)
  71                 
  72 
  73         def _getElementValue(self, name, elements, values=None):
  74                 text = self.vars[name].getText()
  75                 text = self._replace(text, elements)
  76                 #再根据外部引用变量的类型决定是否进行循环
  77                 if values and values.has_key(name):
  78                         if len(values[name]) == 1:      #是字典则只进行一次替换
  79                                 text = self._replace(text, values[name])
  80                         else:
  81                                 s = []
  82                                 for v in values[name]:
  83                                         s.append(self._replace(text, v))
  84                                 text = ''.join(s)
  85                                 
  86                 return text
  87 
  88 if __name__ == '__main__':
  89         vars = dict(hello=[{'var':'var1'},{'var':'var2'},{'var':'var3'}])
  90         template = Template()
  91         template.load('tmp2')
  92         print template.value('program', vars)

from Template import T

hello = T("Hello, <#var#> \n")
message = T("Please input yourname:")
program = T("""name = input_raw("<#message#>")
print '''<#hello#>'''
        """)