分类: Python/Ruby
2008-03-27 15:05:54
模板属性语言(TAL)标准是一种属性语言,用于创建动态模板。它可以实现文档元素的替换、重复或忽略。
TAL中的语句是XML属性。这些属性可以在XMl或HTML中使用,从而实现页面模板的功能。
TAL语句由属性和数值组成。例如,content语句可以这样:
tal:content="string:Hello"
大多数的语句需要表达式,但表达式句法并不属于TAL,而是属于TALES。
TAL名称空间URI定义为:
xmlns:tal=""
当在Zope中创建模板时,不需要用内容类型text/html声明XML名称空间,对于其它内容类型时才需要声明。
TAL语句包括:
语句中的表达式可以返回任何类型的数值,大多数语句只使用字符型数据。表达式语言必须定义一个名为nothing的数值,它不是字符串。这个数值适用于删除元素或属性。
如果每个元素中只有一个TAL语句,执行的顺序很简单。从根元素开始,顺序执行每个元素语句。
在同一元素中可以结合多个语句。但content和replace不能一起使用。
由于TAL把语句看作是XML属性,即使在HTML文档中,不能按照编写的顺序来决定执行的顺序。因此需要对执行的顺序进行规定。
当一个元素中含有多个语句时,按照以下顺序执行:
由于on-error语句只有发生错误时才用到,因此没有在此列出来。
按照这样的顺序执行,原因是:由于其它语句会用到变量,因此define先执行。接下来需要判断是否需要使用当前的元素,因此接下来是 condition;另外condition依赖于刚才定义的变量,所以define后边是condition。由于通过循环的方式用不同值替换某些元素 更具有价值,因此接下来是repeat。由于替换属性没有更多的意义,因此放在后边。
TALES 概述
METAL 概述
tal:attributes
tal:define
tal:condition
tal:content
tal:omit-tag
tal:on-error
tal:repeat
tal:replace
tal:attributes 句法:
argument ::= attribute_statement [';' attribute_statement]*
attribute_statement ::= attribute_name expression
attribute_name ::= [namespace-prefix ':'] Name
namespace-prefix ::= Name
tal:attributes语句用一个动态数值替换(或创建一个属性)属性值。如果你通过多个名称空间生成XML文档,需要在属性中加上名称空间前缀,比如 html:table。如果需要 的话,每个表达式的值会转换成字符串。
如果表达式结果为nothing,那么就从语句元素中删除。如果表达式结果为默认值,则属性保持不变。每个属性是独立的,因此可以在同一语句中处理多个属性。
如果在一个元素中使用了tal:attributes语句,还使用了tal:replace,则tal:attributes将忽略。
如果同时使用了tal:attributes和tal:repeat语句,每次循环都进行属性替换。
tal:condition 句法:
argument ::= expression
根据tal:condition语句,如果符合条件,则在模板中插入元素,否则忽略。如果它的表达式求值为真,则继续处理元素,否则立即从模板中删除。nothing为假,default等同于返回真。
注意:Zope认为缺少变量,None,0,空字符串和空序列为假,其它的值为真。
在插入变量前先测试(第一个例子测试是否存在并求值,第二个例子只测试是否存在):
tal:content="request/message">message goes here
tal:content="request/message">message goes here
测试多个条件:
Even
Odd
tal:content 句法:
argument ::= (['text'] | 'structure') expression
不是替换整个元素,而是在元素内容部分用tal:content替换,插入文本或结构(structure)。这个语句的参数和tal:replace相同。如果表达式结果为nothing,内容部分为空。如果表达式结果为默认值,则内容部分保持不变。
默认的替换方式是文本替换。通过使用structure关键字,可以保持文本不变,即可以插入HTML/XML标记符。
插入用户名称:
Fred Farkas
插入HTML/XML:
marked up
content goes here.
tal:replace
tal:define 句法:
argument ::= define_scope [';' define_scope]*
define_scope ::= (['local'] | 'global') define_var
define_var ::= variable_name expression
variable_name ::= Name
tal:define用于定义变量。你可以定义两种类型的TAL变量:本地变量和全局变量。当你在一个元素中定义了一个本地变量,则只能在那个元素 和所包含的元素中使用。如果在所包含的元素中重新定义本地变量,那么新的定义替换原来的定义。当你定义了一个全局变量,就可以在定义以后在任何位置使用变 量。如果你重新定义了全局变量,从重新定义的位置开始有效。
注意:默认为本地变量。
如果表达式求值结果为nothing,那么变量的值为nothing。如果求值结果为默认值,则变量的值为默认值。
定义一个全局变量:
tal:define="global company_name string:Zope Corp, Inc."
定义两个变量,第二个变量依赖于第一个:
tal:define="mytitle template/title; tlen python:len(mytitle)"
tal:omit-tag 句法:
argument ::= [ expression ]
tal:omit-tag语句保留元素中的内容,同时删除起始和结尾部分的标记符。
如果表达式求值结果为假,则继续处理,标记符不删除。如果表达式求值结果为真,或没有提供表达式,则替换元素中的内容。
Zope认为空字符串、空序列、0、None和nothing为假,其它值为真,包括默认值。
无条件忽略一个标记符:
...but this text will remain.
有条件忽略一个标记符:
I may be bold.
上边的例子中,如果变量bold为假,则忽略b标记符。
创建10个p标记符,没有合拢标记符:
tal:omit-tag="">
1
tal:on-error 句法:
argument ::= (['text'] | 'structure') expression
tal:on-error语句用于处理错误。当一个TAL语句产生错误时,会搜索tal:on-error语句,调用第一个找到的tal:on-error。使用方法如同tal:content。
本地变量error有三个属性:
常见的错误是文字错误或表达式为nothing。更复杂一点的处理错误的方式是调用一个脚本。
显示简单的错误消息:
tal:content="here/getUsername">Ishmael
删除元素:
tal:content="here/getUsername">Ishmael
调用一个脚本:
...
处理错误的脚本可以这样:
## Script (Python) "errHandler"
##bind namespace=_
##
error=_['error']
if error.type==ZeroDivisionError:
return "Can't divide by zero.
"
else
return """An error ocurred.
Error type: %s
Error value: %s
""" % (error.type,
error.value)
注意 这里的 namespace=_ 可在Script(Python)对象的Bingings标签页面中设置。 namespace表示调用方提供的名字空间。
Python Tutorial: Errors and Exceptions
Python Built-in Exceptions
tal:repeat 句法:
argument ::= variable_name expression
variable_name ::= Name
tal:repeat语句根据序列中的每个数据项重复处理元素。表达式求值结果应该为一个序列。如果序列为空,那么这个语句所在的元素被删除,否则重复处理序列中的每一项。如果表达式为默认值,那么不发生改变,并且没有新定义的变量。
使用循环变量可访问当前循环相关信息,比如循环的序号。循环变量和本地变量一样,但是只能通过内建的变量repeat来调用。
循环变量包括以下信息:
你可以通过路径表达式或Python表达式访问循环变量。在路径表达式中,需要用三部分组成名称,即repeat、语句变量名称和要访问的变量名称。比如:
repeat/item/start
在Python表达式中,使用字典方法来访问信息,比如:
python:repeat['item'].start
除了start、end和index,所有repeat变量的属性都是方法。因此,当你用Python表达式时,必须这样来调用:
python:repeat['item'].length()
** 注意 ** first和last适用于过滤序列。它们试图根据相同值把序列分成组。如果提供了一个路径,那么根据这个路径取得的数值进行分组,否则使用数据项的值。 你可以通过传递参数提供路径,比如"python:repeat['item'].first(color)",或通过repeat变量附加路径,比如, "repeat/item/first/color"。
对字符串序列进行循环:
插入表格行,使用变量repeat显示行号:
1 | Widget | $1.50 |
嵌套的循环:
tal:replace="string:$x * $y = $z">1 * 1 = 1 |
插入对象,按照meta-type进行分组:
tal:content="object/meta_type">Meta Type
Object ID
注意,上边例子中的对象应该已经按照meta-type进行了排序。
tal:replace 句法:
argument ::= (['text'] | 'structure') expression
tal:replace语句的作用是用动态内容替换一个元素。替换的内容可以是文本或结构。表达式中可加上类型前缀。表达式结果会自动转换成字符类 型。如果使用了前缀structure,则会在输出文本中保持特殊字符不变;否则会进行转换:即把 "&" 转换成 "&", 把"<" 转换成 "<", 把">" 转换成 ">"。
如果为nothing,则只删除元素。如果为默认值,元素保持不变。
插入模板标题的两种方式:
Title
Title
插入HTML/XML:
插入nothing(空):
This element is a comment.
tal:content
模板属性语言表达式句法(TALES)描述了用于TAL和METAL的表达式。TALES提供了多种表达类型。
以下是基本的TALES句法:
Expression ::= [type_prefix ':'] String
type_prefix ::= Name
以下是一些例子:
a/b/c
path:a/b/c
nothing
path:nothing
python: 1 + 2
string:Hello,
${user/getUserName}
表达式前边可加上可选的类型前缀。如果不指定一个前缀,默认为路径表达式。
TALES表达式中可使用以下名称:
注意 root, here, container, template, request, user, 和 modules是可选的名称,TALES标准中不要求必须使用。
TAL Overview
METAL Overview
exists expressions
nocall expressions
not expressions
string expressions
path expressions
python expressions
Exists 表达式句法:
exists_expressions ::= 'exists:' path_expression
Exists表达式测试路径是否存在。如果路径存在返回真。当不能定位一个对象时,返回假。
测试一个表单变量:
Please enter a number between 0 and 5
注意,此时不能使用 not:request/form/number,这是由于如果变量number存在并为0,表达式值将为真。
Nocall 表达式句法:
nocall_expression ::= 'nocall:' path_expression
Nocall 表达式避免了调用路径表达式的结果。
通常路径表达式会调用对象。也就是说,如果对象是函数、脚本方法或其它可执行对象,则表达式会调用这些对象运行的结果。大多数情况下需要这样,但不 总需要这样。例如,如果你想通过一个变量使用DTML文档,然后调用它的属性,此时就不能使用通常的路径表达式,否则会得到文档运行后的字符串。
使用nocall得到文档属性:
tal:content="string:${doc/getId}: ${doc/title}">
Id: Title
对一个函数使用nocall表达式:
这个例子定义了一个变量join,它绑定给string.join函数。
Not 表达式句法:
not_expression ::= 'not:' expression
Not表达式先对expression字符串求值,然后返回它的布尔中的逻辑非值。如果提供的表达式求值后不是一个布尔值,则会根据以下规则转换成布尔类型:
如果没有提供expression字符串,会引发错误。
测试一个序列:
There are no contained objects.
Path 表达式句法:
PathExpr ::= Path [ '|' Expression ]
Path ::= variable [ '/' PathSegment ]*
variable ::= Name
PathSegment ::= ( '?' variable ) | PathChar+
PathChar ::= AlphaNumeric | ' ' | '_' | '-' | '.' | ',' | '~'
路径表达式由一个路径组成,也可以在后边通过竖线符号(|)增加另外一个表达式,如果前一个表达式无效则使用后一个。路径由一个或多个非空字符串组 成,用/分开。第一个字符串必须为一个变量名称(内建变量或用户定义的变量),其余部分可以包含字母、数字、空格和符号"_","-",".","~"。
表达式中可以使用符号?表示一个动态变量,这个变量必须是一个字符串,运行时会替换成对应的字符串。
例如:
request/cookies/oatmeal
nothing
here/some-file 2001_02.html.tar.gz/foo
root/to/branch | default
request/name | string:Anonymous Coward
here/?tname/macros/?mname
当对表达式求值时,从左到右依次处理路径。
如果出现错误,显示错误信息。
附加的表达式可以是任何TALES表达式。比如,request/name | string:Anonymous Coward,就是一个有效的路径表达式。通过这个表达式,可以提供默认值。也可以提供多个附加的路径表达式,比如,first | second | third | nothing。
如果没有路径,则为nothing。
由于每个路径必须以一个变量名称开始,因此这个起始变量应该能够找到相应的对象才行。参见前边列出的内建变量。变量名称先在本地搜索,然后在内建变 量列表中搜索,因此内建变量就像Python中内建的变量一样。也可以在变量名称前声明范围。你也可以直接通过CONTEXTS访问内建变量,比如, CONTEXTS/root, CONTEXTS/nothing。
插入一个cookie变量或一个属性:
preference
插入用户名称:
User name
Python 表达式句法:
任何有效的Python语言表达式
Python表达式在安全限制环境内对Python代码求值。Python表达式和脚本对象和DTML中的变量表达式一样。
Python表达式的限制和脚本对象中的一样,这些限制包括:
Python表达式和脚本对象中的内建函数一样,但增加了一些。
标准的内建函数包括: None, abs, apply, callable, chr, cmp, complex, delattr, divmod, filter, float, getattr, hash, hex, int, isinstance, issubclass, list, len, long, map, max, min, oct, ord, repr, round, setattr, str, tuple.
range和pow函数不能生成非常巨大的数值和序列。
另外,还可以使用:DateTime,test,same_type。参考 DTML 函数部分。
最后,可以在Python表达式中使用这些函数:
可以使用默认提高的模块,也可以增加模块。访问模块的方式可以通过路径表达式,比如:modules/string/join,也可以在Python中使用module映射对象,比如:modules['string'].join。以下是默认的模块:
使用一个模块,从列表中随机选择一个数据项:
a random number between one and five
字符串处理,把用户名变成大写格式:
User Name
数学处理,把图像大小转换成兆字节:
12.2323
处理字符串格式,把浮点型格式为两个小数位:
13.56
String 表达式句法:
string_expression ::= ( plain_string | [ varsub ] )*
varsub ::= ( '$' Path ) | ( '${' Path '}' )
plain_string ::= ( '$$' | non_dollar )*
non_dollar ::= any character except '$'
字符串表达式按照文本处理字符串。如果没有提供字符串,则为空。字符串中可以通过$name或${path}格式使用变量,其中name为变量名称,path为路径表达式。如果要插入$符号,需要使用$$。
处理字符串:
Spam and Eggs
使用路径:
total: 12
包含一个$符号:
cost: $42.00
宏扩展模板属性语言(METAL)用于处理HTML/XML宏(Macro)。它可以结合TAL和TALES一起使用。
宏提供了一种共享模板数据的方式。如果宏发生了变化,那么相应的共享数据也会发生变化。另外,宏可以扩展,从而具有最终结果的样子,方便编辑处理。
METAL名称空间URI定义为:
xmlns:metal=""
当创建内容类型具有text/html的模板时,Zope不要求声明XML名称空间。但对于其它类型则需要声明。
METAL定义的语句包括:
TAL Overview
TALES Overview
metal:define-macro
metal:use-macro
metal:define-slot
metal:fill-slot
metal:define-macro 句法:
argument ::= Name
metal:define-macro语句定义一个宏。通过语句表达式进行定义,有效返回是当前所在的元素和下级元素。
可以通过模板的macros对象调用宏定义。比如,在模板master.html中定义了宏header,那么你可以使用路径表达式master.html/macros/header访问这个宏。
简单的宏定义:
Copyright 2001, Foobar Inc.
metal:use-macro
metal:define-slot
metal:define-slot 句法:
argument ::= Name
metal:define-slot语句定义了一个宏定制点,或内容块(slot)。当使用一个宏时,这个内容块可以替换成其它内容。内容块定义提供了默认的内容。如果不调用内容块,则显示默认的内容。
metal:define-slot语句必须在metal:define-macro 之中。
内容块的名称必须唯一。
简单的内容块定义:
Hello World
这个例子定义了一个宏和一个名为name的内容块。当你使用这个宏的时候,可以在b元素中添加进定制的内容。
metal:fill-slot
metal:fill-slot 句法:
argument ::= Name
metal:fill-slot语句通过替换宏中的内容块来定制宏。
metal:fill-slot 语句必须在metal:use-macro中使用。
内容块名称必须唯一。
如果宏中不存在指定的内容块,则删除这个内容块。
先定义宏:
Hello World
你可以这样来填充内容块name:
Hello Kevin Bacon
metal:define-slot
metal:use-macro 句法:
argument ::= expression
metal:use-macro语句用宏替换当前元素中的内容。expression描述了一个宏定义。
expression将生成一个路径表达式,用来指向另外一个模板中定义的宏。参见metal:define-macro部分。
扩展宏的效果就是从另外一个文档或当前文档中提取部分内容,然后放进当前元素之中,即替换当前的内容。原来的内容保持不变,如果使用了内容块,则内容块中使用新的内容。
当扩展宏时,使用metal:use-macro语句。
基本用法:
header macro from defined in other.html template
这个例子引用了在other.html模板中定义的header。当扩展这个宏时,p元素和它的内容将替换成宏中的内容。
metal:define-macro
metal:fill-slot
Zope页面模板的行为几乎完全可以通过TAL、TALES和METAL进行描述。但还有一些特定的行为。
当一个页面模板的内容类型设置为text/html,处理过程会有些不同于其它内容类型。在TAL名称空间中讲过,HTML不需要声明名称空间,默认>提供TAL和METAL名称空间。
HTML文档采用非XML解析器,因此可以处理一些不符合XML要求的标记符。特别是那些没有结束标记符的元素,比如段落和列表,但还不能认为 > 是错误,除非它们是语句元素。这样就容易导致错误,比如使用用
中,此时由于< /p>标记符,则会引发一个NestingError错误。因此解决的方法是使用。
没有合拢的语句元素通常认为是错误,因此应该尽量指明合拢的标记符。对于那些没有结束标记符的元素,比如image和input元素,不要求加>上合拢标记符或使用XHTML中的
某些布尔属性,比如checked和selected,在tal:attributes中处理方式不同。数值为真或假。如果为真,则会处理成 attr="attr"格式,如果为假,则会忽略。如果值为default,则此时,如果属性已经存在认为是真,不存在为假。比如:
结果为:
对于:
将生成:
这种处理方式可以在所有的浏览器中正确显示。