Plugin note

This functionality is contained within an expression evaluator plugin. As such, it is available only when the corresponding plugin is installed.

Plugin assembly

CSF.Zpt.ExpressionEvaluators.PathExpressions.dll

Plugin classes

CSF.Zpt.ExpressionEvaluators.PathExpressions.PathExpressionEvaluator & CSF.Zpt.ExpressionEvaluators.PathExpressions.LocalVariablePathExpressionEvaluator

Expression prefixes

path: & local:

TALES 'path' expressions

TALES path: expressions are the lifeblood of TALES, and are the default expression type where no expression prefix has been provided.

Path expressions indicate a traversal through an object model - the current TALES context. This context includes a set of built in variables as well as any other variables added by either the environment or by TAL define/TAL repeat attributes.

A special variant of path expressions uses the prefix local:. These local path expressions function identically to other path expressions (as described on this page), except that they only consider variables defined with local scope.

Structure of a path expression

Each expression must begin with a variable name, which relates to a reference within the current TALES content. The object exposed by the variable name may be traversed, exposing its members, via forward-slashes: /.

The TALES context

The TALES context indicates the variables which are available at a given HTML/XML element. This consists of:

  • All of the local variables added via tal:define attributes. This is variables defined within the current element, as well as variables defined upon parent elements in the DOM.
  • All of the global variables added via tal:define attributes. This is variables defined within the current element, as well as variables defined upon elements which preceed the current element in document order.
  • All of the built-in root variables provided by TALES.
  • The special root variable (which is a reserved word and may not be defined as a local or global variable): CONTEXTS. This variable provides access to the built-in root variables (include any supplemental root variables). The CONTEXTS variable exists in case any of the root variables have been hidden by being overwritten. For example CONTEXTS/nothing will always provide access to a null reference, even if a local/global variable named nothing has been defined.

Providing multiple paths

It is possible to provide multiple TALES paths within a single expression, separated by the pipe/vertical bar character: | and optionally whitespace. For example the following is a legal path expression: Model/Foo/Bar | Model/Alternative/Path | backupValue.

When evaluating such a path expression, an attempt is made to traverse each path starting with the first. If a path is traversed successfully then the result from that path is returned as the result of the path expression and no further paths are traversed.

If a path cannot be traversed - for example, an exception such as a NullReferenceException is raised during traversal - then traversal of that path ceases and an attempt is made to traverse the next path in the expression.

Once a path within the expression yields a result then further paths are not used. If, alternatively, none of the paths in an expression yield a result then an evaluation error is raised. Thus, providing multiple paths within a single expression is a useful as a manner of guarding against errors, or providing fall-back values.

Example

Consider the following example. If the current user were null then, instead of raising an error when displaying the user's name, some fallback text would be displayed.

<p tal:define="unknownUser string:an unknown user;
               currentUser Model/CurrentUser">
  You are logged in as
  <span tal:content="currentUser/Name | unknownUser">Joseph Bloggs</span>.
</p>

Path traversal

The precise meaning of traversal through a path is as follows. The path to traverse is separated into fragments - individual pieces of the path, as separated by slashes.

  1. First, the starting point of the traversal is retrieved from the current TALES context, using the first path fragment. This value becomes "the current object to be traversed".
  2. The next path fragment (if there is one) is used for traversal using the rules below.
    • If the traversal is a failure (either an exception is raised, or a traversal rule indicates failure) then the evaluation of the current path stops. If there are more paths in the expression then traversal begins again with the next path. If there are no more paths, then the evaluation of the path expression is a failure and a TALES Exception is raised.
    • If the traversal is not a failure then it is considered a success. The result of the traversal is stored as "the current object to be traversed" and the traversal continues.
  3. If there are no more path fragments in the current path, then "the current object to be traversed" is returned as the result of the path expression.
  4. If there are more path fragments in the current path then the process returns to step 2, using the new "current object to be traversed".

Traversing a path fragment

The rules for traversing each path fragment are as follows:

  1. If the current object to be traversed implements CSF.Zpt.Tales.ITalesPathHandler then its HandleTalesPath(string, out object, RenderingContext) method is called, using the path fragment as the first parameter. The System.Boolean return of the method is used to determine whether traversal was a success or not. In the case of a success, the System.Object exposed via the second parameter is used as the result of the traversal.
  2. If the current object to be traversed has an indexer of type System.String then that indexer is used. The path fragment (as a string literal) is used as a parameter for that indexer. The return value from the indexer is used as the result of the traversal.
  3. If the current object to be traversed has a method, taking no parameters, matching the name of the path fragment, than that method is executed. Its return value is used as the result of the traversal.
  4. If the current object to be traversed has a gettable property, matching the name of the path fragment, than that property getter is invoked. Its value is used as the result of the traversal.
  5. If the current object to be traversed has a field, matching the name of the path fragment, than the value is retrieved from that field. This is used as the result of the traversal.
  6. If the current object to be traversed has an indexer of type System.Int32 then that indexer is used. The path fragment is parsed as an integer and used as a parameter for that indexer. The return value from the indexer is used as the result of the traversal.
  7. If none of the above are true, then the traversal is unsuccessful.

Interpolated path fragments

When traversing a path, a path fragment may optionally be prefixed with a question mark symbol: ?. This signifies that the path fragment is interpolated by evaluating the name of that fragment as a single variable reference from the TALES context. The result of that evaluation is converted to a System.String and used as the text of the fragment for continuing traversal.

Only single variables may be evaluated in this manner, so interpolated path fragments do not trigger traversal themselves.

Example

The example below shows a sample list of filenames uploaded by the current user. However, in this case, the list of uploaded files is not available as a property of the 'CurrentUser' object, rather as a property of a 'SharedUploads' object, using the user-name as a key.

The user-name is stored within the variable userName via the tal:define attribute, and then referenced as an interpolated path fragment within the expression used in the tal:repeat attribute.

<ul tal:define="userName Model/CurrentUser/Name">
  <li tal:repeat="file Model/SharedUploads/?userName/Files"
      tal:content="file/Name">Sample filename</li>
</ul>