Appendix C: Zope Page Templates Reference
Zope Page Templates are an HTML/XML generation tool. This appendix is a reference to Zope Page Templates standards: Tag Attribute Language (TAL), TAL Expression Syntax (TALES), and Macro Expansion TAL (METAL). It also describes some ZPT-specific behaviors that are not part of the standards.
snell - Nov. 15, 2003 5:20 am: There is no reference to metal:block in: Zope Page Templates Reference Page Templates Advanced Page Templates What is it for?
Anonymous User - Nov. 23, 2003 3:01 pm: tal:block or metal:block can be used on tag-level if you have no html-tag to put your tal/metal code on.
Anonymous User - Nov. 23, 2003 3:02 pm: for instance, outside of the html-tag.
Anonymous User - Apr. 14, 2004 10:17 am: I have found a tal function that is never used or described in any of these pages or the WWW after a search on 5 searchpages. Except in a subproduct for Zope (Plone) (but they don't explain tal usage on their site so I'll ask it here) <tal:datetime define="today python:DateTime().earliestTime()"> ... </tal:datetime> First thing that intrigues me: There is no standard html tag around this tal, I thought only tal:block could do that? Second thing I noticed: All the code that remained between those tags (represented by "...") appeared in the resulting page without problem, but there remained nothing visible of these "tal:datetime" tags. Third thing I noticed: straight after the tal:datetime statement comes define="...", clearly working as the tal:define explained later in this apendix. Why has there been no need to write "tal:" in front of it? Is this some faulty page template code, yet still beeing accepted by the browser? Could this code have been replaced by a simple <tal:block tal:define="..."> ... </tal:block> or <span tal:omit-tag tal:define="..."> ... </span>? Or is there a possibility to extend the tal-statements and why isn't it told here then?
Anonymous User - Apr. 14, 2004 10:30 am: You need to understand namespaces. In an HTML page, the default namespace is that of HTML. The browser will attempt to parse all tags in this namespace. To put a tag in a different namespace, which will be ignored by the browser, prefix it with the namespace, e.g. to put a tag in the 'tal' namespace, write: <tal:XXXX ... /> The same goes for attributes. To put an attribute in the 'tal' namespace, write: <span tal:define="..." /> If an element is in the 'tal' namespace, all its attributes are also in that namespace. That is why it is *not* necessary to write: <tal:datetime tal:define="..." /> The second 'tal:' is redundant. The next thing to understand: TAL (the Template ATTRIBUTE language) only pays attention to *attributes*. It ignores tags. Therefor the XXX in <tal:XXX ...> can be anything -- it will be ignored by the TAL parser. It's a good idea to make it something descriptive.
Anonymous User - Aug. 6, 2005 6:52 pm: test
Anonymous User - Aug. 12, 2005 5:02 pm: hahaha
inflatables - Oct. 14, 2005 11:42 pm: test ---------- http://www.inflatables-china.net
TAL Overview
The Tag Attribute Language (TAL) standard is an attribute language used to create dynamic templates. It allows elements of a document to be replaced, repeated, or omitted.
The statements of TAL are XML attributes from the TAL namespace. These attributes can be applied to an XML or HTML document in order to make it act as a template.
A TAL statement has a name (the attribute name) and a body (the
attribute value). For example, a content
statement might look
like tal:content="string:Hello"
. The element on which a statement
is defined is its statement element. Most TAL statements
require expressions, but the syntax and semantics of these
expressions are not part of TAL. TALES is recommended for this
purpose.
TAL Namespace
The TAL namespace URI and recommended alias are currently defined as:
xmlns:tal="http://xml.zope.org/namespaces/tal"
snell - Nov. 2, 2003 8:34 am: The first two paragraphs of The Zope Book seem to have been forgotten in the recent past. They read: "Preface Welcome to The Zope Book. This book is designed to introduce you to Zope, the open source web application server. To make effective use of the book, you should know how to use a web browser and you should have a basic understanding of HTML (Hyper Text Markup Language) and URLs (Uniform Resource Locators). You don't need to be a highly-skilled programmer in order to use Zope, but some programming background (particularly object-oriented programming) will be extremely helpful. " This statement calls for a return to that philosophy. TAL syntax basics are not explained in this document; therefore, the new student - who has been directed to that fact that TAL avoids many problems of dtml and, therefore, wants to learn it - finds it inaccessible. Two months into Zope I discovered an archive document which explained TAL syntax structure and would offer that here as a pointer. However, I cannot find it a second time!
Anonymous User - Nov. 3, 2003 10:57 am: Here is what is missing: http://dev.zope.org/Wikis/DevSite/Projects/ZPT/AttributeLanguage AttributeLanguage Attribute Languages An attribute language is a programming language designed to mesh in a particular way with documents written using tag-structured markup, such as HTML and XML. The statements of the language are document tags with special attributes, and look like this: <p ns:command="argument">Some Text</p> The attribute ns:command="argument" is the statement attribute, and the entire paragraph tag is the statement element, the portion of the document on which this statement operates. Each statement attribute has three parts: the namespace prefix, the name, and the argument. The prefix identifies the language, and must be introduced by an XML namespace declaration in XML and XHTML documents, like this: xmlns:ns="http://language.creator.com/namespaces/MyAttributeLanguage" HTML should include these declarations, but an implementation may allow you to omit them. The statement name determines which language statement to apply to the statement element, and the argument determines how it is applied. The name is always a simple identifier, but the argument can contain just about anything, depending on the statement. How to Specify an Attribute Language If you create an attribute language, you need to define the following: The URI of the XML namespace, and (optionally) a recommended alias. The names, argument syntax, and meaning of the possible statements. The order in which statements on the same element are processed, and restrictions on which statements can share the same element.
This is not a URL, but merely a unique identifier. Do not expect a browser to resolve it successfully.
Zope does not require an XML namespace declaration when creating
templates with a content-type of text/html
. However, it does
require an XML namespace declaration for all other content-types.
TAL Statements
- tal:attributes - dynamically change element attributes.
- tal:define - define variables.
- tal:condition - test conditions.
- tal:content - replace the content of an element.
- tal:omit-tag - remove an element, leaving the content of the element.
- tal:on-error - handle errors.
- tal:repeat - repeat an element.
- tal:replace - replace the content of an element and remove the element leaving the content.
Expressions used in statements may return values of any type, although most statements will only accept strings, or will convert values into a string representation. The expression language must define a value named nothing that is not a string. In particular, this value is useful for deleting elements or attributes.
Anonymous User - May 10, 2004 10:18 pm: deleting elements or attributes? when and where? this value refered to is nothing?
remiq - May 28, 2005 6:16 pm: delete atributes: tal:attributes - dynamically change element attributes. delete elements: tal:omit-tag - remove an element, leaving the content of the element.
Order of Operations
When there is only one TAL statement per element, the order in which they are executed is simple. Starting with the root element, each element's statements are executed, then each of its child elements is visited, in order, to do the same.
Any combination of statements may appear on the same elements,
except that the content
and replace
statements may not appear
together.
Anonymous User - Aug. 6, 2005 6:51 pm: test
Due to the fact that TAL sees statements as XML attributes, even in HTML documents, it cannot use the order in which statements are written in the tag to determine the order in which they are executed. TAL must also forbid multiples of the same kind of statement on a single element, so it is sufficient to arrange the kinds of statement in a precendence list.
When an element has multiple statements, they are executed in this order:
-
define
-
condition
-
repeat
-
content
orreplace
-
attributes
-
omit-tag
Since the on-error
statement is only invoked when an error occurs,
it does not appear in the list.
Anonymous User - Nov. 24, 2003 11:31 am: Add: It may not be apparent that there needs to be an ordering. The reason that there must be one is that TAL is XML based. The XML specification specifically states that XML processors are free to rewrite the terms. In particular, you cannot assume that attributes of an XML statement will be processed in the order written, particularly if there is another preprocessor involved. To avoid needless proliferation of tags, and still permit unambigous execution of complex TAL, a precedence order was chosen according to the following rationalle.
The reasoning behind this ordering goes like this: You often want
to set up variables for use in other statements, so define
comes
first. The very next thing to do is decide whether this element
will be included at all, so condition
is next; since the
condition may depend on variables you just set, it comes after
define
. It is valuable be able to replace various parts of an
element with different values on each iteration of a repeat, so
repeat
is next. It makes no sense to replace attributes and
then throw them away, so attributes
is last. The remaining
statements clash, because they each replace or edit the statement
element.
See Also
attributes: Replace element attributes
Syntax
argument ::= attribute_statement [';' attribute_statement]* attribute_statement ::= attribute_name expression attribute_name ::= [namespace-prefix ':'] Name namespace-prefix ::= Name
*Note: If you want to include a semi-colon (;) in an expression
,
it must be escaped by doubling it (;;).*
Description
The tal:attributes
statement replaces the value of an attribute
(or creates an attribute) with a dynamic value. You can qualify an
attribute name with a namespace prefix, for example html:table
, if
you are generating an XML document with multiple namespaces. The
value of each expression is converted to a string, if necessary.
If the expression associated with an attribute assignment evaluates to nothing, then that attribute is deleted from the statement element. If the expression evaluates to default, then that attribute is left unchanged. Each attribute assignment is independent, so attributes may be assigned in the same statement in which some attributes are deleted and others are left alone.
Anonymous User - Dec. 19, 2003 12:58 pm: This seems to contradict the Order of Operations, above, where it says that attribution takes place after replacement. That way seems better than ignoring the attribution altogether.
Anonymous User - Jan. 16, 2004 8:41 am: Performing attribution after replacement wouldn't make any sense; tal:replace completely replaces the element, where would the attribute changes be made then?
If you use tal:attributes
on an element with an active
tal:replace
command, the tal:attributes
statement is ignored.
If you use tal:attributes
on an element with a tal:repeat
statement, the replacement is made on each repetition of the
element, and the replacement expression is evaluated fresh for each
repetition.
Examples
<a href="/sample/link.html" tal:attributes="href here/sub/absolute_url">
Anonymous User - June 4, 2004 9:34 am: path <code>here/sub/absolute_url</code> wont work for me (zope 2.7). <code>here/absolute_url</code> works fine
<textarea rows="80" cols="20" tal:attributes="rows request/rows;cols request/cols">
condition: Conditionally insert or remove an element
Syntax
argument ::= expression
Description
The tal:condition
statement includes the statement element in the
template only if the condition is met, and omits it otherwise. If
its expression evaluates to a true value, then normal processing
of the element continues, otherwise the statement element is
immediately removed from the template. For these purposes, the
value nothing is false, and default has the same effect as
returning a true value.
Note: Zope considers missing variables, None, zero, empty strings, and empty sequences false; all other values are true.
Examples
Test a variable before inserting it (the first example tests for existence and truth, while the second only tests for existence):
<p tal:condition="request/message | nothing" tal:content="request/message">message goes here</p> <p tal:condition="exists:request/message" tal:content="request/message">message goes here</p>
Anonymous User - July 16, 2004 3:26 pm: In tal:condition="request/message | nothing", is the pipe used to explicitly define the default value, as with traditional OR syntax, or is it just considered part of this particular conditional statement? Or is the default value defined as the content already stated between the tags? In this case, "message goes here"?
Test for alternate conditions:
<div tal:repeat="item python:range(10)"> <p tal:condition="repeat/item/even">Even</p> <p tal:condition="repeat/item/odd">Odd</p> </div>
content: Replace the content of an element
Syntax
argument ::= (['text'] | 'structure') expression
Description
Rather than replacing an entire element, you can insert text or
structure in place of its children with the tal:content
statement. The statement argument is exactly like that of
tal:replace
, and is interpreted in the same fashion. If the
expression evaluates to nothing, the statement element is left
childless. If the expression evaluates to default, then the
element's contents are unchanged.
The default replacement behavior is text
, which replaces
angle-brackets and ampersands with their HTML entity equivalents.
The structure
keyword passes the replacement text through
unchanged, allowing HTML/XML markup to be inserted. This can
break your page if the text contains unanticipated markup (eg.
text submitted via a web form), which is the reason that it is
not the default.
Examples
<p tal:content="user/getUserName">Fred Farkas</p>
Anonymous User - Apr. 30, 2004 11:32 am: Following this example, how could I write in TAL a condition that checks if the current user is, for example, "smith" ?
Anonymous User - Oct. 19, 2004 4:17 pm: try this: <p tal:condition="python:user.getUserName=='smith'"></p>
<p tal:content="structure here/getStory">marked <b>up</b> content goes here.</p>
See Also
define: Define variables
Syntax
argument ::= define_scope [';' define_scope]* define_scope ::= (['local'] | 'global') define_var define_var ::= variable_name expression variable_name ::= Name
*Note: If you want to include a semi-colon (;) in an expression
,
it must be escaped by doubling it (;;).*
Description
The tal:define
statement defines variables. You can define two
different kinds of TAL variables: local and global. When you
define a local variable in a statement element, you can only use
that variable in that element and the elements it contains. If
you redefine a local variable in a contained element, the new
definition hides the outer element's definition within the inner
element. When you define a global variables, you can use it in
any element processed after the defining element. If you redefine
a global variable, you replace its definition for the rest of the
template.
Note: local variables are the default
If the expression associated with a variable evaluates to nothing, then that variable has the value nothing, and may be used as such in further expressions. Likewise, if the expression evaluates to default, then the variable has the value default, and may be used as such in further expressions.
Examples
tal:define="global company_name string:Zope Corp, Inc."
Defining two variables, where the second depends on the first:
tal:define="mytitle template/title; tlen python:len(mytitle)"
omit-tag: Remove an element, leaving its contents
Syntax
argument ::= [ expression ]
Description
The tal:omit-tag
statement leaves the contents of an
element in place while omitting the surrounding start and end tags.
If the expression evaluates to a false value, then normal processing of the element continues and the tags are not omitted. If the expression evaluates to a true value, or no expression is provided, the statement element is replaced with its contents.
Zope treats empty strings, empty sequences, zero, None, and nothing as false. All other values are considered true, including default.
Examples
Unconditionally omitting a tag:
<div tal:omit-tag="" comment="This tag will be removed"> <i>...but this text will remain.</i> </div>
<b tal:omit-tag="not:bold">I may be bold.</b>
The above example will omit the b
tag if the variable bold
is
false.
Creating ten paragraph tags, with no enclosing tag:
<tal:block repeat="n python:range(10)"> <p tal:content="n">1</p> </tal:block>
on-error: Handle errors
Syntax
argument ::= (['text'] | 'structure') expression
Description
The tal:on-error
statement provides error handling for your
template. When a TAL statement produces an error, the TAL
interpreter searches for a tal:on-error
statement on the same
element, then on the enclosing element, and so forth. The first
tal:on-error
found is invoked. It is treated as a tal:content
statement.
error
is set. This variable has these
attributes:
-
type
- the exception type
-
value
- the exception instance
-
traceback
- the traceback object
Anonymous User - Apr. 26, 2004 4:12 pm: Despite what the documentation claims, there does not seem to be a traceback object. A browse of the source code in TALDefs.py shows type, value, lineno and offset, but no traceback.
The simplest sort of tal:on-error
statement has a literal error
string or nothing for an expression. A more complex handler may
call a script that examines the error and either emits error text
or raises an exception to propagate the error outwards.
Examples
<b tal:on-error="string: Username is not defined!" tal:content="here/getUsername">Ishmael</b>
Removing elements with errors:
<b tal:on-error="nothing" tal:content="here/getUsername">Ishmael</b>
Calling an error-handling script:
<div tal:on-error="structure here/errorScript"> ... </div>
Here's what the error-handling script might look like:
## Script (Python) "errHandler" ##bind namespace=_ ## error=_['error'] if error.type==ZeroDivisionError: return "<p>Can't divide by zero.</p>" else return """<p>An error ocurred.</p> <p>Error type: %s</p> <p>Error value: %s</p>""" % (error.type, error.value)
See Also
Python Tutorial: Errors and Exceptions
repeat: Repeat an element
Syntax
argument ::= variable_name expression variable_name ::= Name
Description
The tal:repeat
statement replicates a sub-tree of your document
once for each item in a sequence. The expression should evaluate
to a sequence. If the sequence is empty, then the statement
element is deleted, otherwise it is repeated for each value in the
sequence. If the expression is default, then the element is
left unchanged, and no new variables are defined.
The variable_name
is used to define a local variable and a
repeat variable. For each repetition, the local variable is set to
the current sequence element, and the repeat variable is set to an
iteration object.
Repeat Variables
You use repeat variables to access information about the current
repetition (such as the repeat index). The repeat variable has
the same name as the local variable, but is only accessible
through the built-in variable named repeat
.
nvram - May 19, 2005 6:22 pm: This section desperately needs an example of how to use 'repeat' within a 'pyton:' clause (in my case I want a string with the repeat/item/index ordinal for a form input name). All of my guesses have been wrong, and ~50 documentation searches in vain. It's gotta be simple, but it's not obvious. Something like: <table> <tr tal:repeat="item here/cart"> <td tal:content="python:('%03d' % repeat.item.number) ">001</td> <td tal:content="item/description">Widget</td> <td tal:content="item/price">$1.50</td> </tr> </table>
Anonymous User - Oct. 28, 2005 10:15 am: This is the correct way of doing it: <table> <tr tal:repeat="item here/cart"> <td tal:content="python:('%03d' % repeat['item'].number) ">001</td> <td tal:content="item/description">Widget</td> <td tal:content="item/price">$1.50</td> </tr> </table>
The following information is available from the repeat variable:
- index - repetition number, starting from zero.
- number - repetition number, starting from one.
- even - true for even-indexed repetitions (0, 2, 4, ...).
- odd - true for odd-indexed repetitions (1, 3, 5, ...).
- start - true for the starting repetition (index 0).
- end - true for the ending, or final, repetition.
- first - true for the first item in a group - see note below
- last - true for the last item in a group - see note below
- length - length of the sequence, which will be the total number of repetitions.
- letter - repetition number as a lower-case letter: "a" - "z", "aa" - "az", "ba" - "bz", ..., "za" - "zz", "aaa" - "aaz", and so forth.
- Letter - upper-case version of letter.
- roman - repetition number as a lower-case roman numeral: "i", "ii", "iii", "iv", "v", etc.
- Roman - upper-case version of roman.
You can access the contents of the repeat variable using path
expressions or Python expressions. In path expressions, you write
a three-part path consisting of the name repeat
, the statement
variable's name, and the name of the information you want, for
example, repeat/item/start
. In Python expressions, you use
normal dictionary notation to get the repeat variable, then
attribute access to get the information, for example,
"python:repeat['item'].start".
With the exception of start
, end
, and index
, all of the
attributes of a repeat variable are methods. Thus, when you
use a Python expression to access them, you must call them, as in
"python:repeat['item'].length()".
Note that first
and last
are intended for use with sorted
sequences. They try to divide the sequence into group of items
with the same value. If you provide a path, then the value
obtained by following that path from a sequence item is used for
grouping, otherwise the value of the item is used. You can
provide the path by passing it as a parameter, as in
"python:repeat['item'].first(color
)", or by appending it to the
path from the repeat variable, as in "repeat/item/first/color".
Examples
Iterating over a sequence of strings::
<p tal:repeat="txt python:'one', 'two', 'three'"> <span tal:replace="txt" /> </p>
Inserting a sequence of table rows, and using the repeat variable to number the rows:
<table> <tr tal:repeat="item here/cart"> <td tal:content="repeat/item/number">1</td> <td tal:content="item/description">Widget</td> <td tal:content="item/price">$1.50</td> </tr> </table>
<table border="1"> <tr tal:repeat="row python:range(10)"> <td tal:repeat="column python:range(10)"> <span tal:define="x repeat/row/number; y repeat/column/number; z python:x*y" tal:replace="string:$x * $y = $z">1 * 1 = 1</span> </td> </tr> </table>
Insert objects. Seperates groups of objects by meta-type by drawing a rule between them:
<div tal:repeat="object objects"> <h2 tal:condition="repeat/object/first/meta_type" tal:content="object/meta_type">Meta Type</h2> <p tal:content="object/getId">Object ID</p> <hr tal:condition="repeat/object/last/meta_type" /> </div>
Note, the objects in the above example should already be sorted by meta-type.
replace: Replace an element
Syntax
argument ::= (['text'] | 'structure') expression
Description
The tal:replace
statement replaces an element with dynamic
content. It replaces the statement element with either text or a
structure (unescaped markup). The body of the statement is an
expression with an optional type prefix. The value of the
expression is converted into an escaped string if you prefix the
expression with text
or omit the prefix, and is inserted
unchanged if you prefix it with structure
. Escaping consists of
converting "&" to "&", "<" to "<", and
">" to ">".
If the value is nothing, then the element is simply removed. If the value is default, then the element is left unchanged.
Examples
The two ways to insert the title of a template:
<span tal:replace="template/title">Title</span> <span tal:replace="text template/title">Title</span>
<div tal:replace="structure table" />
<div tal:replace="nothing">This element is a comment.</div>
See Also
TALES Overview
The Template Attribute Language Expression Syntax (TALES) standard describes expressions that supply TAL and METAL with data. TALES is one possible expression syntax for these languages, but they are not bound to this definition. Similarly, TALES could be used in a context having nothing to do with TAL or METAL.
TALES expressions are described below with any delimiter or quote markup from higher language layers removed. Here is the basic definition of TALES syntax:
Expression ::= [type_prefix ':'] String type_prefix ::= Name
Here are some simple examples:
a/b/c path:a/b/c nothing path:nothing python: 1 + 2 string:Hello, ${user/getUserName}
The optional type prefix determines the semantics and syntax of the expression string that follows it. A given implementation of TALES can define any number of expression types, with whatever syntax you like. It also determines which expression type is indicated by omitting the prefix.
If you do not specify a prefix, Zope assumes that the expression is a path expression.
TALES Expression Types
These are the TALES expression types supported by Zope:
- path expressions - locate a value by its path.
- exists expressions - test whether a path is valid.
- nocall expressions - locate an object by its path.
- not expressions - negate an expression
- string expressions - format a string
- python expressions - execute a Python expression
Built-in Names
These are the names that always available to TALES expressions in Zope:
- nothing - special value used by to represent a non-value (e.g. void, None, Nil, NULL).
- default - special value used to specify that existing text should not be replaced. See the documentation for individual TAL statements for details on how they interpret default.
- options - the keyword arguments passed to the template. These are generally available when a template is called from Methods and Scripts, rather than from the web.
- repeat - the
repeat
variables; see the tal:repeat documentation. - attrs - a dictionary containing the initial values of the attributes of the current statement tag.
- CONTEXTS - the list of standard names (this list). This can be used to access a built-in variable that has been hidden by a local or global variable with the same name.
- root - the system's top-most object: the Zope root folder.
- here - the object to which the template is being applied.
- container - The folder in which the template is located.
- template - the template itself.
- request - the publishing request object.
- user - the authenticated user object.
- modules - a collection through which Python modules and packages can be accessed. Only modules which are approved by the Zope security policy can be accessed.
Note the names root
, here
, container
, template
, request
,
user
, and modules
are optional names supported by Zope, but
are not required by the TALES standard.
See Also
TALES Exists expressions
Syntax
exists_expressions ::= 'exists:' path_expression
Description
Exists expressions test for the existence of paths. An exists expression returns true when the path expressions following it expression returns a value. It is false when the path expression cannot locate an object.
Examples
Testing for the existence of a form variable:
<p tal:condition="not:exists:request/form/number"> Please enter a number between 0 and 5 </p>
Note that in this case you can't use the expression,
not:request/form/number
, since that expression will be true if
the number
variable exists and is zero.
TALES Nocall expressions
Syntax
nocall_expression ::= 'nocall:' path_expression
Description
Nocall expressions avoid rendering the results of a path expression.
An ordinary path expression tries to render the object that it fetches. This means that if the object is a function, Script, Method, or some other kind of executable thing, then expression will evaluate to the result of calling the object. This is usually what you want, but not always. For example, if you want to put a DTML Document into a variable so that you can refer to its properties, you can't use a normal path expression because it will render the Document into a string.
Examples
Using nocall to get the properties of a document:
<span tal:define="doc nocall:here/aDoc" tal:content="string:${doc/getId}: ${doc/title}"> Id: Title</span>
Using nocall expressions on a functions:
<p tal:define="join nocall:modules/string/join">
This example defines a variable join
which is bound to the
string.join
function.
TALES Not expressions
Syntax
not_expression ::= 'not:' expression
Description
Not expression evaluate the expression string (recursively) as a full expression, and returns the boolean negation of its value. If the expression supplied does not evaluate to a boolean value, not will issue a warning and coerce the expression's value into a boolean type based on the following rules:
- the number 0 is false
- positive and negative numbers are true
- an empty string or other sequence is false
- a non-empty string or other sequence is true
- a non-value (e.g. void, None, Nil, NULL, etc) is false
- all other values are implementation-dependent.
If no expression string is supplied, an error should be generated.
Zope considers all objects not specifically listed above as false to be true.
Examples
<p tal:condition="not:here/objectIds"> There are no contained objects. </p>
TALES Path expressions
Syntax
PathExpr ::= Path [ '|' Expression ] Path ::= variable [ '/' PathSegment ]* variable ::= Name PathSegment ::= ( '?' variable ) | PathChar+ PathChar ::= AlphaNumeric | ' ' | '_' | '-' | '.' | ',' | '~'
Description
A path expression consists of a path optionally followed by a vertical bar (|) and alternate expression. A path consists of one or more non-empty strings separated by slashes. The first string must be a variable name (a built-in variable or a user defined variable), and the remaining strings, the path segments, may contain letters, digits, spaces, and the punctuation characters underscore, dash, period, comma, and tilde.
A limited amount of indirection is possible by using a variable name
prefixed with ?
as a path segment. The variable must contain a
string, which replaces that segment before the path is traversed.
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
When a path expression is evaluated, Zope attempts to traverse the path, from left to right, until it succeeds or runs out of paths segments. To traverse a path, it first fetches the object stored in the variable. For each path segment, it traverses from the current object to the subobject named by the path segment. Subobjects are located according to standard Zope traversal rules (via getattr, getitem, or traversal hooks).
Once a path has been successfully traversed, the resulting object is the value of the expression. If it is a callable object, such as a method or template, it is called.
If a traversal step fails, and no alternate expression has been specified, an error results. Otherwise, the alternate expression is evaluated.
The alternate expression can be any TALES expression. For example,
request/name | string:Anonymous Coward
is a valid path expression.
This is useful chiefly for providing default values, such as strings
and numbers, which are not expressable as path expressions. Since
the alternate expression can be a path expression, it is possible to
"chain" path expressions, as in first | second | third | nothing
.
If no path is given the result is nothing.
Since every path must start with a variable name, you need a set of starting variables that you can use to find other objects and values. See the TALES overview for a list of built-in variables. Variable names are looked up first in locals, then in globals, then in the built-in list, so the built-in variables act just like built-ins in Python; They are always available, but they can be shadowed by a global or local variable declaration. You can always access the built-in names explicitly by prefixing them with CONTEXTS. (e.g. CONTEXTS/root, CONTEXTS/nothing, etc).
Examples
Inserting a cookie variable or a property:
<span tal:replace="request/cookies/pref | here/pref"> preference </span>
<p tal:content="user/getUserName"> User name </p>
TALES Python expressions
Syntax
Any valid Python language expression
Description
Python expressions evaluate Python code in a security-restricted environment. Python expressions offer the same facilities as those available in Python-based Scripts and DTML variable expressions.
Security Restrictions
Python expressions are subject to the same security restrictions as Python-based scripts. These restrictions include:
- access limits
- Python expressions are subject to Zope permission and role security restrictions. In addition, expressions cannot access objects whose names begin with underscore.
- write limits
- Python expressions cannot change attributes of Zope objects.
Despite these limits malicious Python expressions can cause problems. See The Zope Book for more information.
Built-in Functions
Python expressions have the same built-ins as Python-based Scripts with a few additions.
These standard Python built-ins are available: 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
.
The range
and pow
functions are available and work the same
way they do in standard Python; however, they are limited to
keep them from generating very large numbers and sequences. This
limitation helps protect against denial of service attacks.
In addition, these utility functions are available: DateTime
,
test
, and same_type
. See DTML
functions for more
information on these functions.
Finally, these functions are available in Python expressions, but not in Python-based scripts:
holdenweb - Nov. 13, 2004 11:08 am: Is there some way to stop the HTML escaping of path: values so this can be used as a substitution mechanism, or is there some other better mechanism to use?
-
path(string)
- Evaluate a TALES path expression.
-
string(string)
- Evaluate a TALES string expression.
-
exists(string)
- Evaluates a TALES exists expression.
-
nocall(string)
- Evaluates a TALES nocall expression.
Python Modules
A number of Python modules are available by default. You can
make more modules available. You can access modules either via
path expressions (for example modules/string/join
) or in
Python with the modules
mapping object (for example
modules["string"].join
). Here are the default modules:
woller - Jan. 24, 2004 5:38 pm: It is not clear at all where to go to "see ZTUtils" for instance. Or any of the other references.... There should really be some links here!
-
string
- The standard Python string module. Note: most of the functions in the module are also available as methods on string objects.
-
random
- The standard Python random module.
-
math
- The standard Python math module.
-
sequence
- A module with a powerful sorting function. See sequence for more information.
-
Products.PythonScripts.standard
- Various HTML formatting functions available in DTML. See Products.PythonScripts.standard for more information.
-
ZTUtils
- Batch processing facilities similar to those
offered by
dtml-in
. See ZTUtils for more information. -
AccessControl
- Security and access checking facilities. See AccessControl for more information.
Examples
Using a module usage (pick a random choice from a list):
<span tal:replace="python:modules['random'].choice(['one', 'two', 'three', 'four', 'five'])"> a random number between one and five </span>
Anonymous User - May 28, 2004 4:26 pm: When do you use that syntax instead of an earlier example that used a path ("python:modules/string/join") to get at a function? Is it just author preference which to use?
String processing (capitalize the user name):
<p tal:content="python:user.getUserName().capitalize()"> User Name </p>
Basic math (convert an image size to megabytes):
<p tal:content="python:image.getSize() / 1048576.0"> 12.2323 </p>
String formatting (format a float to two decimal places):
<p tal:content="python:'%0.2f' % size"> 13.56 </p>
Anonymous User - Mar. 24, 2004 12:17 am: How create 12345 to 12,345.00
Anonymous User - May 28, 2004 3:08 pm: One way: <p tal:define="ps python:modules['Products.PythonScripts.standard']; varA python:12345; varB python:'%0.2f' % ( varA ); varC python:ps.thousands_commas( varB )" tal:content="string:$$$varC"> Will print $12,345.00 </p>
TALES String expressions
Syntax
string_expression ::= ( plain_string | [ varsub ] )* varsub ::= ( '$' Path ) | ( '${' Path '}' ) plain_string ::= ( '$$' | non_dollar )* non_dollar ::= any character except '$'
Description
String expressions interpret the expression string as text. If no
expression string is supplied the resulting string is empty. The
string can contain variable substitutions of the form $name
or
${path}
, where name
is a variable name, and path
is a
path expression.
The escaped string value of the path expression is inserted into
the string. To prevent a $
from being interpreted this way, it
must be escaped as $$
.
Examples
<span tal:replace="string:$this and $that"> Spam and Eggs </span>
<p tal:content="string:total: ${request/form/total}"> total: 12 </p>
<p tal:content="string:cost: $$$cost"> cost: $42.00 </p>
METAL Overview
The Macro Expansion Template Attribute Language (METAL) standard is a facility for HTML/XML macro preprocessing. It can be used in conjunction with or independently of TAL and TALES.
Macros provide a way to define a chunk of presentation in one template, and share it in others, so that changes to the macro are immediately reflected in all of the places that share it. Additionally, macros are always fully expanded, even in a template's source text, so that the template appears very similar to its final rendering.
Anonymous User - Nov. 17, 2003 4:25 am: NOT MENTIONED: A single Page Template can accomodate multiple macros. The method employed to mark the beginning and, above all, the end of one macro is not discussed here. Therefore, a second macro can accidently be called inadvertently when calling the first one.
METAL Namespace
The METAL namespace URI and recommended alias are currently defined as:
xmlns:metal="http://xml.zope.org/namespaces/metal"
Just like the TAL namespace URI, this URI is not attached to a web page; it's just a unique identifier.
Zope does not require an XML namespace declaration when creating
templates with a content-type of text/html
. However, it does
require an XML namespace declaration for all other content-types.
METAL Statements
METAL defines a number of statements:
- metal:define-macro - Define a macro.
- metal:use-macro - Use a macro.
- metal:define-slot - Define a macro customization point.
- metal:fill-slot - Customize a macro.
Although METAL does not define the syntax of expression non-terminals, leaving that up to the implementation, a canonical expression syntax for use in METAL arguments is described in TALES Specification.
See Also
define-macro: Define a macro
Syntax
argument ::= Name
Description
The metal:define-macro
statement defines a macro. The macro is
named by the statement expression, and is defined as the element
and its sub-tree.
Anonymous User - Nov. 17, 2003 4:27 am: NOT MENTIONED: Sub-tree, where does it end?
In Zope, a macro definition is available as a sub-object of a
template's macros
object. For example, to access a macro named
header
in a template named master.html
, you could use the path
expression master.html/macros/header
.
Examples
<p metal:define-macro="copyright"> Copyright 2001, <em>Foobar</em> Inc. </p>
See Also
define-slot: Define a macro customization point
Syntax
argument ::= Name
Description
The metal:define-slot
statement defines a macro customization
point or slot. When a macro is used, its slots can be replaced,
in order to customize the macro. Slot definitions provide default
content for the slot. You will get the default slot contents if
you decide not to customize the macro when using it.
The metal:define-slot
statement must be used inside a
metal:define-macro
statement.
Anonymous User - Nov. 17, 2003 4:30 am: NOT MENTIONED: "inside" a metal:define-macro implies that the macro has a beginning and an end. Inside is then before the end. How does one mark the end of a macro?
Anonymous User - Dec. 8, 2003 4:01 pm: by the closing tag
Slot names must be unique within a macro.
Examples
<p metal:define-macro="hello"> Hello <b metal:define-slot="name">World</b> </p>
This example defines a macro with one slot named name
. When you
use this macro you can customize the b
element by filling the
name
slot.
See Also
fill-slot: Customize a macro
Syntax
argument ::= Name
Description
The metal:fill-slot
statement customizes a macro by replacing a
slot in the macro with the statement element (and its content).
The metal:fill-slot
statement must be used inside a
metal:use-macro
statement.
Slot names must be unique within a macro.
If the named slot does not exist within the macro, the slot contents will be silently dropped.
Examples
<p metal:define-macro="hello"> Hello <b metal:define-slot="name">World</b> </p>
Anonymous User - Oct. 17, 2004 1:45 am: One looks like an example of usage in an HTML template and the other is an example of usage in an xml template.
Anonymous User - June 14, 2004 3:41 pm: the tag <metal:headslot ...> ... </metal:headslot> is an XML / XHTML compliant tag entity, but will not be rendered by most browsers ('metal:headslot' is not a standard HTML tag). Regardless, the TAL parser will parse the tag for any logic it contains... By putting the metal: at the beginning, the tag's attribute scope falls under the METAL namespace; this essentially means that any metal attributes within the opening tag don't need to have 'metal:' attached to them (example: <metal:some-block define-slot="..."> ... </metal:some-block> rather than <metal:some-other-block metal:define-slot="..."> ... </metal:some-block>)
Anonymous User - Apr. 8, 2004 4:52 pm: Why do some define-slots look like: <p metal:define-slot="head_slot" /> while others look like: <metal:headslot define-slot="head_slot" /> what is that "headslot" thingie? It's not the same as "head_slot"...
You can fill the name
slot like so:
<p metal:use-macro="container/master.html/macros/hello"> Hello <b metal:fill-slot="name">Kevin Bacon</b> </p>
whijo - Mar. 24, 2005 12:15 am: I find that I stil can't get to grips with constructs like this: <metal:cssslot fill-slot="css_slot"> <metal:cssslot define-slot="css_slot" /> </metal:cssslot> I understand it to somehow cater for a default fill which might be overwritten by another template...but I'm not confident with that one! Unfortunately the only reference I've found to it, in the so-called "Definitive Guide to Plone" fails to get the point through (to me at least). Is this actually a way to allow target templates to add their own css to those that may already be provided via the containing template?
See Also
use-macro: Use a macro
Syntax
argument ::= expression
Description
The metal:use-macro
statement replaces the statement element
with a macro. The statement expression describes a macro
definition.
In Zope the expression will generally be a path expression referring to a macro defined in another template. See "metal:define-macro" for more information.
The effect of expanding a macro is to graft a subtree from another document (or from elsewhere in the current document) in place of the statement element, replacing the existing sub-tree. Parts of the original subtree may remain, grafted onto the new subtree, if the macro has slots. See metal:define-slot for more information. If the macro body uses any macros, they are expanded first.
When a macro is expanded, its metal:define-macro
attribute is
replaced with the metal:use-macro
attribute from the statement
element. This makes the root of the expanded macro a valid
use-macro
statement element.
Examples
<p metal:use-macro="container/other.html/macros/header"> header macro from defined in other.html template </p>
This example refers to the header
macro defined in the
other.html
template which is in the same folder as the current
template. When the macro is expanded, the p
element and its
contents will be replaced by the macro. Note: there will still be
a metal:use-macro
attribute on the replacement element.
Anonymous User - July 14, 2004 1:31 pm: Is there any way to pass arguments to a macro explicitly instead of relying on the implicit attributes from the context from which the macro is called?
See Also
ZPT-specific Behaviors
The behavior of Zope Page Templates is almost completely described by the TAL, TALES, and METAL specifications. ZPTs do, however, have a few additional features that are not described in the standards.
HTML Support Features
When the content-type of a Page Template is set to text/html
,
Zope processes the template somewhat differently than with any
other content-type. As mentioned under TAL Namespace, HTML
documents are not required to declare namespaces, and are provided
with tal
and metal
namespaces by default.
HTML documents are parsed using a non-XML parser that is somewhat
more forgiving of malformed markup. In particular, elements that
are often written without closing tags, such as paragraphs and list
items, are not treated as errors when written that way, unless they
are statement elements. This laxity can cause a confusing error in
at least one case; A <div>
element is block-level, and
therefore technically not allowed to
be nested in a <p>
element, so it will cause the paragraph to be
implicity closed. The closing </p>
tag will then cause a
NestingError, since it is not matched up with the opening tag. The
solution is to use <span>
instead.
Unclosed statement elements are always treated as errors, so as
not to cause subtle errors by trying to infer where the element
ends. Elements which normally do not have closing tags in
HTML, such as image and input elements, are not required to have
a closing tag, or to use the XHTML <tag />
form.
Certain boolean attributes, such as checked
and
selected
, are treated differently by tal:attributes
.
The value is treated as true or false (as defined by
tal:condition
). The attribute is set to attr="attr"
in the
true case and omitted otherwise. If the value is default
, then
it is treated as true if the attribute already exists, and false if
it does not. For example, each of the following lines:
<input type="checkbox" checked tal:attributes="checked default"> <input type="checkbox" tal:attributes="checked string:yes"> <input type="checkbox" tal:attributes="checked python:42">
<input type="checkbox" checked="checked">
<input type="checkbox" tal:attributes="checked default"> <input type="checkbox" tal:attributes="checked string:"> <input type="checkbox" tal:attributes="checked nothing">
<input type="checkbox">
nederhoed - May 12, 2005 4:26 am: To create a <select> tag in a zpt page that reselects the selected value on submit, you can use the following code: <select size="1" name="person"> <option value="tammo" tal:attributes="selected python:request.get('person')=='tammo'">Tammo</option> <option value="anita" tal:attributes="selected python:request.get('person')=='anita'">Anita</option> </select>
This works correctly in all browsers in which it has been tested.