The types

The suppored types are:

Scalars

These are the basic, simple kind of values. They can be:

Bear in mind that FreeMarker distinguishes strings from numbers, booleans and date-like values. For example, while the string "150" looks like the number 150, a string is still just arbitrary sequence of characters, and you can't do arithmetic with it, can't compare it with another number, etc.

Containers

These are the values whose purpose is to contain other variables; they are just containers. The contained variables are often referred as sub variables. The container types are:

Note that since a value can have multiple types, it is possible for a value to be both a hash and a sequence, in which case it would support index-based access as well as access by lookup name. However, typically a container will be either a hash or a sequence, not both.

As the value of the variables stored in hashes and sequences (and collections) can be anything, it can be a hash or sequence (or collection) as well. This way you can build arbitrarily deep structures.

The data-model itself (or better said the root of it) is a hash.

FreeMarker templates don't support modifying the contents of containers (such as adding, removing or replacing sub variables), and it assumes that their content won't change during template processing. (But you can make new container values by adding together two existing container values with +; see that in the chapter about expressions, and please note the performance consequences.)

Subroutines

Methods and functions

A value that is a method or a function is used to calculate another value, influenced by the parameters you give to it.

For programmer types: Methods/functions are first-class values, just like in functional programming languages. This means that functions/methods can be the parameters or return values of other functions/methods, you can assign them to variables, and so on.

Suppose that programmers have put the method variable avg in the data-model that can be used to calculate the average of numbers. If you give the 3 and 5 as parameters when you access avg, then you get the value 4.

The usage of methods will be explained later, but perhaps this example helps to understand what methods are:

The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of a python and an elephant is:
${avg(animals.python.price, animals.elephant.price)}

this will output:

The average of 3 and 5 is: 4
The average of 6 and 10 and 20 is: 12
The average of the price of a python and an elephant is:
4999.5

What is the difference between a method and a function? As far as the template author is concerned, nothing. Well not really nothing, as methods typically come from the data-model (as they reflect the methods of Java objects), and functions are defined in templates (with the function directive -- an advanced topic), but both can be used on the same way.

User-defined directives

A value of this type can be used as user-defined directive (with other words, as FreeMarker tag). An user-defined directive is a subroutine, something like a little reusable template fragment. But this is an advanced topic that will be explained later in its own chapter.

For programmer types: user-defined directives (such as macros), are first-class values too, just like functions/methods are.

Just to get an idea about user-defined directives (so just ignore this if you won't understand), assume we have a variable, box, whose value is a user-defined directive that prints some kind of fancy HTML message box with a title bar and a message in it. The box variable could be used in the template like this (for example):

<@box title="Attention!">
  Too much copy-pasting may leads to
  maintenance headaches.
</@box>

Function/method versus user-defined directive

This is for advanced users again (so ignore it if you don't understand). It's a frequent dilemma if you should use a function/method or an user-defined directive to implement something. The rule of thumb is: Implement the facility as user-defined directive instead of as function/method if:

The Java methods of FreeMarker-unaware Java objects are normally visible as methods in templates, regardless of the nature of the Java method; you have no choice there.

Miscellaneous

Nodes

Node variables represent a node in a tree structure, and are used mostly with XML processing, which is an advanced, and specialized topic.

Still, a quick overview for advanced users: A node is similar to a sequence that stores other nodes, which are often referred as the children nodes. A node stores a reference to its container node, which is often referred as the parent node. The main point of being a node is the topological information; other data must be stored by utilizing that a value can have multiple types. Like, a value may be both a node and a number, in which case it can store a number as the "pay-load". Apart from the topological information, a node can store some metainformation as well: a node name, a node type (string), and a node namespace (string). For example, if the node symbolizes a h1 element in an XHTML document, then its name could be "h1", it's node type could be "element", and it's namespace could be "http://www.w3.org/1999/xhtml". But it's up to the designer of the data-model if what meaning these metainformations have, and if they are used at all. The way of retrieving the topological and metainformations is described in a later chapter (that you don't have to understand at this point).

Markup output

This type is related to auto-escaping mechanism introduced FreeMarker 2.3.24; you can read about this type there. But in short, this is a value that stores text that's already in the output markup format (like HTML, XML, RTF, etc.), and hence must not be auto-escaped.

Values of this type are usually produced inside the templates (like with no_esc built-in or output capturing assignments), but can also be part of the data-model. Such values in the data-model are useful for example if you have message resources that sometimes contain the message in HTML format, rather than in plain text. If the data-model uses HTML markup output values for those messages instead of strings, then the template author need not know which messages contain HTML and which plain text, as double escaping will be avoided automatically when the message is inserted with ${...}.

上一章 首页 下一章