Syntax
PathExpression ::= Expression [ '|' Expression ]*
PathSegmentExpression ::= FirstPathToken [ '/' NextPathToken ]*
FirstPathToken ::= StringLiteral | NumericLiteral | BooleanLiteral | ListExpression | FunctionExpression | VariableExpression | ArrayExpression
StringLiteral ::= '/'' StringLiteralChar* '/''
StringLiteralChar ::= any character except '''
NumericLiteral ::= Numeric+
BooleanLiteral ::= true | false
ListExpression ::= '[' Expression ']'
RangeExpression ::= Numeric* ':' Numeric+ [ ':' Numeric+ ]
FunctionExpression ::= Name '(' [ ArgumentList ] ')'
VariableExpression ::= Name
ArrayExpression ::= Expression ArrayAccessor
ArrayAccessor ::= '[' Expression+ ']'
NextPathToken ::= IndirectionExpression | MethodExpression | PropertyExpression | ArrayAccessor
IndirectionExpression ::= '?' Name
MethodExpression ::= Name '(' [ ArgumentList ] ')'
PropertyExpression ::= Name
ArgumentList ::= Expression [ ',' Expression ]*
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 one of these:
- a string literal,
- a numeric literal,
- a boolean literal,
- a list expression,
- a function expression,
- an array expression,
- or a variable name (a built-in variable or a user defined variable).
The remaining strings, the path segments, may be:
- an indirection,
- a method name,
- an array accessor,
- or a property name.
When a path expression is evaluated, ZPT-JS 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 sub-object named by the path segment.
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 function, 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:
user/name | 'Anonymous Coward'
is a valid path expression. This is useful chiefly for providing default values, such as strings and numbers, which are not expressible 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.
Note: some parts extracted from Zope Page Templates Reference.
Differences with ZPT
- ZPT-JS includes more types of path expressions, such as method, array, list or range expressions.
- ZPT uses python expressions for a lot of tasks, but these are not supported in ZPT-JS.
Examples
The neccesary javascript code:
import { zpt } from './zpt-esm.js';
var dictionary = {
number100: 100,
aString: "string",
function3: function( ){
return 3;
},
add: function( a, b ){
return a + b;
},
user: {
name: "Bob",
age: function(){
return 25;
},
birth: function(){
return {
day: 3,
month: 3,
year: 1977,
aFunction: function(){
return {
another: 'yes!'
};
}
};
},
addMethod: function( a, b ){
return a + b;
}
},
items: [ 'first', 'second', 'third' ],
from1To3: [ 1, 2, 3 ],
property: "name"
};
// Parse template
zpt.run({
root: document.body,
dictionary: dictionary
});
Literals
Literals are constant values. They can be number, string or boolean values:
<span data-content="'this is a string literal'">a string</span>
<span data-content="123">an integer</span>
<span data-content="123.45">a float</span>
<span data-content="true">not false</span>
<span data-content="false">not true</span>
Functions
Invoking functions:
<span data-content="function3()">must be 3</span>
<span data-content="add( 1, 2 )">must be 1 + 2 = 3</span>
<span data-content="add( 1, number100 )">must be 1 + number100 = 101</span>
<span data-content="add( 1, (*: 2 2 ) )">must be 1 + 2 * 2 = 5</span>
Variables
Using simple variables:
<span data-content="number100">must be 100</span>
<span data-content="aString">must be string</span>
Properties
Using properties of objects:
<span data-content="user/name">must be Bob</span>
Methods
Using methods of objects:
<span data-content="user/age()">must be 25</span>
<span data-content="user/addMethod( 1, 2 )">must be 1 + 2 = 3</span>
Arrays
Arrays are supported too:
<span data-content="items[2]">must be third</span>
<span data-content="items">must be first, second, third</span>
<span data-content="+: from1To3 4">must be 1 + 2 + 3 + 4 = 10</span>
Maps
Maps support makes it easy to access defined in variables properties:
<span data-content="user['name']">must be Bob</span>
<span data-define="property 'name'" data-content="user[ property ]">must be Bob again</span>
Lists
Lists are very versatile:
<span data-content="[1 20 3 number100]">must be 1,20,3,100</span>
<span data-content="+: [1 20 3 number100]">must be 1 + 20 + 3 + 100 = 124</span>
<ol>
<li data-repeat="c [1 20 3 number100]">
Iterating element <span data-content="c">1/20/3/100</span>
</li>
</ol>
<ol>
<li data-repeat="c [1 'a string' number100]">
Iterating element <span data-content="c">1/a string/100</span>
</li>
</ol>
Ranges
Ranges makes it easy buildin numeric lists:
<ol>
<li data-repeat="c [1:5]">
Iterating element <span data-content="c">1/2/3/4/5</span>
</li>
</ol>
<ol>
<li data-repeat="c [1:7:2]">
Iterating element <span data-content="c">1/3/5/7</span>
</li>
</ol>
<ol>
<li data-repeat="c [:5]">
Iterating element <span data-content="c">0/1/2/3/4/5</span>
</li>
</ol>
Indirections
<span data-content="user/?property">must be Bob if property is name</span>