Templess 模板系统
项目描述
本文件适用于 Templess 0.3。
这是什么?
Templess 是一种用于 Python 的 XML 模板语言,它非常紧凑和简单,快速,并且逻辑和设计有非常严格的分离。它与其他模板语言的不同之处在于,它不是“从模板请求”数据,而是“告诉”模板要渲染的内容,模板只提供占位符。
指令
Templess 中只有 5 个指令,所有这些指令都定义为 XML 节点的属性(见下面的示例)
- content
当一个XML节点具有templess:content属性时,将使用该属性的值作为键,在上下文中执行查找(见下面的示例)。如果找不到键,将引发KeyError。如果找到的值是字符串,它将被用作节点的文本内容。如果找到的值是模板.render()生成的‘lazyrenderer’实例,它将被用作元素的新内容(即,您可以使用template.render()生成要放入其他树中的XML片段)。如果值是列表节点,则将重复元素的内容,将当前项插入到元素的 内容中(见下面的列表插值)。
- 替换
与content相同,但不是“填充”节点,而是将节点替换为插值的结果。
- attr
XML节点上可选的templess:attr的值将在;处分割,形成成对(字符串),每个字符串将在空格(' ')处分割,形成键值对(因此“foo bar;baz qux”将产生两个对,('foo','bar'),('baz','qux'),其中每个对的第一项是键,第二项是值)。对于这些对中的每一个,都会向XML节点添加一个属性,键名作为名称,值作为在上下文中查找的结果。
- cond
如果XML节点上templess:cond条件的值解析为false,则将完全从文档中删除该节点。
- not
cond的逆,仅在值为false时使节点被渲染。
列表插值
如果为templess:content或templess:replace属性找到的插值值是字符串或节点类型,则该值将简单地添加到节点中。如果项的值是列表类型,则将复制节点,并重复执行插值,对列表中的每个项执行一次,使用节点作为根,当前值作为上下文。对于每个列表项,它将以以下方式响应
如果项的值是字符串类型,则将值用作当前元素的文本属性。
如果项的值是节点类型,它将被附加到节点的子节点。
如果项的值是字典类型,内容插值将以与完整模板完全相同的行递归,使用当前元素作为根,当前上下文值作为上下文(请注意,根上下文不再可用)。
当所有节点都复制后,如果使用的指令是templess:content,则将它们附加到树中;如果使用的指令是templess:replace,则仅将它们的内容附加到树中。
示例
以下所有示例都假设我们在某个地方的脚本中,如下所示
>>> from templess import templess
示例 1:简单的插值
作为第一个示例,我们将文本“bar”插值到一个简单的XML文档中的“foo”节点。
>>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:content="foodata" /> ... </doc> ... """ >>> context = { ... 'foodata': 'bar', ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <foo>bar</foo> </doc>
在调用“render()”时,模板将搜索任何Templess指令,并在某个时候找到“t:content”指令。当发生这种情况时,它将在作为参数传递的上下文中查找是否有与属性值对应的键。在我们的情况下,属性的值是“foodata”,因此它将查找键“foodata”,并找到值“bar”。由于此值为字符串类型,因此将其设置为节点的文本值,并在完成后删除该属性。
请注意,如果使用的指令是templess:replace,则doc元素将获得文本内容,foo节点将被删除,因此XML将类似于<doc>bar</doc>。
示例 2:节点插值
在这个示例中,我们将一个新XML节点插值到文档中。此功能提供了一种简单的方法来重用模板。
请注意(XXX目前?)节点需要是一个特殊的Templess节点才能进行插值。将来将提供更方便的方式添加节点(例如使用不那么特定于Templess的API,或者允许来自其他库的XML节点)。
>>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:content="foodata" /> ... </doc> ... """ >>> context = { ... 'foodata': templess.elnode('bar', {}, None), ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <foo><bar /></foo> </doc>
与字符串的情况完全相同,只是将节点文本值设置为上下文的字符串值,而不是将元素节点用作节点的新内容。
一个更有用的例子是插值另一个模板的结果(类似于其他系统中宏的某种程度)
>>> xml_bar = """\ ... <?xml version="1.0" ?> ... <bar xmlns:t="http://johnnydebris.net/xmlns/templess" ... t:content="bardata" /> ... """ >>> context_bar = { ... 'bardata': 'baz', ... } >>> t_bar = templess.template(xml_bar) >>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:content="foodata" /> ... </doc> ... """ >>> context = { ... 'foodata': t_bar.render(context_bar) ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <foo><bar>baz</bar></foo> </doc>
示例3:字符串值的列表插值
在这个例子中,我们将在文档内部重复某个元素,并将数组的每个实例的内容进行插值。
>>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:content="foodata" /> ... </doc> ... """ >>> context = { ... 'foodata': ['foo', 'bar'], ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <foo>foo</foo><foo>bar</foo> </doc>
当Templess引擎注意到值是列表类型时,它将遍历它,为每个迭代创建节点的副本。从那时起,插值工作方式与正常一样,但是在副本上而不是在原始节点上。当它完成列表迭代后,原始节点将被删除。
注意:节点插值(templess.node子类)的工作方式完全相同,也可以像以前一样使用templess:replace。
注意:当列表的值不是字符串类型时,节点上的插值行为不会相同,请参阅下一个示例。
示例4:字典值的列表插值
在这个例子中,我们将使用字典值作为列表,实际上是在插值过程中递归。递归的上下文是当前上下文值(当前的字典),递归的根是当前元素。
>>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:content="foodata"><bar t:content="bardata" /></foo> ... </doc> ... """ >>> context = { ... 'foodata': [ ... {'bardata': 'baz'}, ... {'bardata': 'qux'}, ... ], ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <foo><bar>baz</bar></foo><foo><bar>qux</bar></foo> </doc>
当然,这也可以用templess.node实例代替字符串,并且会无限递归,因此您也可以使用列表作为值。当指令是t:replace时,它也会像您预期的那样表现。
示例5:条件渲染
这是一个非常简单的条件渲染示例,因为它是一个非常简单的指令。最终结果将类似于<doc><bar /></doc>。
>>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:cond="foodata" /><bar t:cond="bardata" /> ... </doc> ... """ >>> context = { ... 'foodata': False, ... 'bardata': True, ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <bar /> </doc>
当t:cond解析为True时,元素保持不变,当它解析为False时,它将从文档中完全删除。有一个名为“not”的相反指令,它的效果与“cond”正好相反,因此您不是在True值上添加节点,而是在True值上删除它。
示例6:设置属性
设置属性也不太难。'attr'指令为每个包含项生成属性,使用上下文中的值作为属性的值。如果上下文值解析为False,则跳过属性(除非值是'',那么它将产生一个空属性)。
>>> xml = """\ ... <?xml version="1.0" ?> ... <doc xmlns:t="http://johnnydebris.net/xmlns/templess"> ... <foo t:attr="bar bardata; baz bazdata; qux quxdata" /> ... </doc> ... """ >>> context = { ... 'bardata': 'quux', ... 'bazdata': 'quuux', ... 'quxdata': False, ... } >>> t = templess.template(xml) >>> print t.unicode(context) <doc> <foo bar="quux" baz="quuux" /> </doc>
项目详情
templess-0.3.tar.gz的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e4a991b77b4b4486274bbbabae3cc8b2bb3270889c8593cab89a4eb65f03a183 |
|
MD5 | 10c31bac14790b91986ef7140ff77c5b |
|
BLAKE2b-256 | 0270146bd00e36c3aff07e0c6c844c9fc4bc7d5f658d13c03bacff16df6c532e |