blob: 9edc8da640a1d1013e0960f4f3ba8d0a77793d9c [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<book conformance="docgen" version="5.0" xml:lang="en"
xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:ns5="http://www.w3.org/1999/xhtml"
xmlns:ns4="http://www.w3.org/2000/svg"
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
xmlns:ns="http://docbook.org/ns/docbook">
<info>
<title>Apache FreeMarker Manual</title>
<titleabbrev>Manual</titleabbrev>
<productname>Freemarker 2.3.29</productname>
</info>
<preface role="index.html" xml:id="preface">
<title>What is Apache FreeMarker?</title>
<para>FreeMarker is a <emphasis>template engine</emphasis>: a generic tool
to generate text output (HTML web pages, e-mails, configuration files,
source code, etc.) based on templates and changing data. It's not an
application for end-users in itself, but a Java library, a component that
programmers can embed into their products.</para>
<para>Templates are written in the FreeMarker Template Language (FTL).
It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
programming language like PHP. You are meant to prepare the data to
display in a real programming language, like issue database queries and do
business calculations, and then the template displays that already
prepared data. In the template you are focusing on how to present the
data, and outside the template you are focusing on what data to
present.</para>
<mediaobject>
<imageobject>
<imagedata fileref="figures/overview.png"/>
</imageobject>
</mediaobject>
<para>This approach is often referred to as the <link
linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
particularly popular for dynamic web pages. It helps in separating web
page designers (HTML authors) from developers (Java programmers usually).
Designers won't face complicated logic in templates, and can change the
appearance of a page without programmers having to change or recompile
code.</para>
<para>While FreeMarker was originally created for generating HTML pages in
MVC web application frameworks, it isn't bound to servlets or HTML or
anything web-related. It's used in non-web application environments as
well.</para>
<para>FreeMarker is <link
xlink:href="http://www.fsf.org/philosophy/free-sw.html">Free</link>,
released under the Apache License, Version 2.0.</para>
</preface>
<part xml:id="dgui">
<title>Template Author's Guide</title>
<chapter xml:id="dgui_quickstart">
<title>Getting Started</title>
<para>This chapter is a very rough introduction to FreeMarker. The
chapters after this will go over things in much greater detail.
Nonetheless, once you have read this chapter, you will be able to write
simple but useful FreeMarker templates.</para>
<section xml:id="dgui_quickstart_basics">
<title>Template + data-model = output</title>
<para>Let's assume that you need a HTML page on a website, similar to
this:</para>
<programlisting role="output">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Welcome!&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Welcome <emphasis>John Doe</emphasis>!&lt;/h1&gt;
&lt;p&gt;Our latest product:
&lt;a href="<emphasis>products/greenmouse.html</emphasis>"&gt;<emphasis>green mouse</emphasis>&lt;/a&gt;!
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>But the user's name ("John Doe" above) depends on who the
logged-in user is, and the latest product information should come from
a database. Because this data changes, you cannot use static HTML.
Instead, you can use a <emphasis role="term">template</emphasis> of
the desired output. The template is the same as the static HTML would
be, except that it contains some instructions to FreeMarker that makes
it dynamic:</para>
<programlisting role="template" xml:id="example.first">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Welcome!&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Welcome <emphasis>${user}</emphasis>!&lt;/h1&gt;
&lt;p&gt;Our latest product:
&lt;a href="<emphasis>${latestProduct.url}</emphasis>"&gt;<emphasis>${latestProduct.name}</emphasis>&lt;/a&gt;!
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>The template is stored on the Web server, usually just like the
static HTML page would be. But whenever someone visits this page,
FreeMarker will step in and transform the template on-the-fly to plain
HTML by replacing the
<literal>${<replaceable>...</replaceable>}</literal>-s with up-to-date
content, and send the result to the visitor's Web browser. So the
visitor's Web browser will receive something like the first example
HTML (i.e., plain HTML without FreeMarker instructions), and it will
not perceive that FreeMarker is used on the server. (Of course, the
template file stored on the Web server is not changed by this; the
substitutions only appear in the Web server's response.)</para>
<para>Note that the template doesn't contain the programming logic to
find out who the current visitor is, or to query the database to get
the latest product. The data to be displayed is prepared outside
FreeMarker, usually by parts written in some <quote>real</quote>
programming language like Java. The template author needn't know how
these values were calculated. In fact, the way these values are
calculated can be completely changed while the templates can remain
exactly the same, and also, the look of the page can be completely
changed without touching anything but the template. This separation of
presentation logic and business logic can be especially useful when
the template authors (designers) and the programmers are different
individuals, but also helps managing application complexity if they
are the same person. Keeping templates focused on presentation issues
(visual design, layout and formatting) is a key for using template
engines like FreeMarker efficiently.</para>
<para><indexterm>
<primary>data-model</primary>
</indexterm>The totality of data that was prepared for the template
is called the <emphasis role="term">data-model</emphasis>. As far as
the template author is concerned, the data-model is a tree-like
structure (like folders and files on your hard disk), which, in this
case, could be visualized as:</para>
<programlisting role="dataModel">(root)
|
+- <emphasis>user</emphasis> = "Big Joe"
|
+- <emphasis>latestProduct</emphasis>
|
+- <emphasis>url</emphasis> = "products/greenmouse.html"
|
+- <emphasis>name</emphasis> = "green mouse"</programlisting>
<note>
<para>The above is just a visualization; the data-model is not in a
textual format, it's from Java objects. For the Java programmers,
the root is perhaps a Java object with <literal>getUser()</literal>
and <literal>getLatestProduct()</literal> methods, or maybe a Java
<literal>Map</literal> with <literal>"user"</literal> and
<literal>"latestProducts"</literal> keys. Similarly,
<literal>latestProduct</literal> is perhaps a Java Object with
<literal>getUrl()</literal> and <literal>getName()</literal>
methods.</para>
</note>
<para>Earlier, you have picked values from this data-model, with the
<literal>user</literal> and <literal>latestProduct.name</literal>
expressions. If we go on with the analogy that the data model is like
a file system, then <quote>(root)</quote> and
<literal>latestProduct</literal> correspond to directories (folders),
and <literal>user</literal>, <literal>url</literal> and
<literal>name</literal> are files in those directories.</para>
<para>To recapitulate, a template and a data-model is needed for
FreeMarker to generate the output (like the HTML shown first):</para>
<para><phrase role="markedTemplate">Template</phrase> + <phrase
role="markedDataModel">data-model</phrase> = <phrase
role="markedOutput">output</phrase></para>
</section>
<section xml:id="dgui_quickstart_datamodel">
<title>The data-model at a glance</title>
<para>As you have seen, the data-model is basically a tree. This tree
can be arbitrarily complicated and deep, for example:</para>
<programlisting role="dataModel"
xml:id="example.qStart.dataModelWithHashes">(root)
|
+- animals
| |
| +- mouse
| | |
| | +- size = "small"
| | |
| | +- price = 50
| |
| +- elephant
| | |
| | +- size = "large"
| | |
| | +- price = 5000
| |
| +- python
| |
| +- size = "medium"
| |
| +- price = 4999
|
+- message = "It is a test"
|
+- misc
|
+- foo = "Something"</programlisting>
<para>The variables that act like directories (the root,
<literal>animals</literal>, <literal>mouse</literal>,
<literal>elephant</literal>, <literal>python</literal>,
<literal>misc</literal>) are called <emphasis
role="term">hashes</emphasis>. Hashes store other variables (the so
called <anchor xml:id="topic.dataModel.subVar"/><emphasis>sub
variables</emphasis>) by a lookup name (e.g., <quote>animals</quote>,
<quote>mouse</quote> or <quote>price</quote>).</para>
<para>The variables that store a single value
(<literal>size</literal>, <literal>price</literal>,
<literal>message</literal> and <literal>foo</literal>) are called
<emphasis role="term">scalars</emphasis>.</para>
<para><anchor xml:id="topic.qStart.accessVariables"/>When you want to
use a subvariable in a template, you specify its path from the root,
and separate the steps with dots. To access the
<literal>price</literal> of a <literal>mouse</literal>, you start from
the root and go into <literal>animals</literal>, and then go into
<literal>mouse</literal> then go into <literal>price</literal>. So you
write <literal>animals.mouse.price</literal>.</para>
<para>Another important kind of variables are <emphasis
role="term">sequences</emphasis>. They store subvariables like hashes,
but here subvariables doesn't have a name, they are just items in a
list. For example, in this data-model, <literal>animals</literal> and
<literal>misc.fruits</literal> are sequences:</para>
<programlisting role="dataModel"
xml:id="example.qStart.dataModelWithSequences">(root)
|
+- animals
| |
| +- (1st)
| | |
| | +- name = "mouse"
| | |
| | +- size = "small"
| | |
| | +- price = 50
| |
| +- (2nd)
| | |
| | +- name = "elephant"
| | |
| | +- size = "large"
| | |
| | +- price = 5000
| |
| +- (3rd)
| |
| +- name = "python"
| |
| +- size = "medium"
| |
| +- price = 4999
|
+- misc
|
+- fruits
|
+- (1st) = "orange"
|
+- (2nd) = "banana"</programlisting>
<para>To access a subvariable of a sequence you use a numerical index
in square brackets. Indexes start from 0 (it's a programmer tradition
to start with 0), thus the index of the 1st item is 0, the index of
the 2nd item is 1, and so on. So to get the name of the first animal
you write <literal>animals[0].name</literal>. To get the second item
in <literal>misc.fruits</literal> (the string
<literal>"banana"</literal>) you write
<literal>misc.fruits[1]</literal>. (In practice, you usually just walk
through sequences in order, not caring about the index, but that will
be <link linkend="topic.tutorial.list">shown later</link>.)</para>
<para>Scalars can be further divided into these categories:</para>
<itemizedlist>
<listitem>
<para>String: Text, that is, an arbitrary sequence of characters
such as ''m'', ''o'', ''u'', ''s'', ''e'' above. For example the
<literal>name</literal>-s and <literal>size</literal>-s are
strings above.</para>
</listitem>
<listitem>
<para>Number: It's a numerical value, like the
<literal>price</literal>-s above. The string
<literal>"50"</literal> and the number <literal>50</literal> are
two totally different things in FreeMarker. The former is just a
sequence of two characters (which happens to be readable as a
number for humans), while the latter is a numerical value that you
can use in arithmetical calculations.</para>
</listitem>
<listitem>
<para>Date-like: Either a date-time (stores a date with time of
the day), or a date (no time of day), or a time (time of day, no
date).</para>
</listitem>
<listitem>
<para>Boolean: A true/false (yes/no, on/off, etc.) thing. Like
animals could have a <literal>protected</literal> subvariable,
which store if the animal is protected or not.</para>
</listitem>
</itemizedlist>
<para>Summary:</para>
<itemizedlist>
<listitem>
<para>The data-model can be visualized as a tree.</para>
</listitem>
<listitem>
<para>Scalars store a single value. The value can be a string or a
number or a date-time/date/time or a boolean.</para>
</listitem>
<listitem>
<para>Hashes are containers that store other variables and
associate them with a unique lookup name.</para>
</listitem>
<listitem>
<para>Sequences are containers that store other variables in an
ordered sequence. The stored variables can be retrieved via their
numerical index, starting from 0.</para>
</listitem>
</itemizedlist>
<note>
<para>There are other, more advanced value types that we don't cover
here, such as methods and directives.</para>
</note>
</section>
<section xml:id="dgui_quickstart_template">
<title>The template at a glance</title>
<para>The simplest template is a plain HTML file (or whatever text
file; FreeMarker is not confined to HTML). When the client visits that
page, FreeMarker will send that HTML to the client as is. However if
you want that page to be more dynamic then you begin to put special
parts into the HTML which will be understood by FreeMarker:</para>
<itemizedlist>
<listitem>
<para><literal>${<replaceable>...</replaceable>}</literal>:
FreeMarker will replace it in the output with the actual value of
the expression inside the curly brackets. They are called
<emphasis role="term">interpolation</emphasis>s.</para>
</listitem>
<listitem>
<para><emphasis role="term">FTL tags</emphasis> (for FreeMarker
Template Language tags): FTL tags are a bit similar to HTML tags,
but they are instructions to FreeMarker and will not be printed to
the output. The name of these tags start with
<literal>#</literal>. (User-defined FTL tags use
<literal>@</literal> instead of <literal>#</literal>, but they are
an advanced topic.)</para>
</listitem>
<listitem>
<para><emphasis role="term">Comments:</emphasis> Comments are
similar to HTML comments, but they are delimited by
<literal>&lt;#--</literal> and <literal>--&gt;</literal>. Unlike
HTML comments, FTL comments won't get into the output (won't be
visible in the page source for the visitor), because FreeMarker
skips them.</para>
</listitem>
</itemizedlist>
<para>Anything not an FTL tag or an interpolation or comment is
considered static text and will not be interpreted by FreeMarker; it
is just printed to the output as-is.</para>
<para>With FTL tags you refer to so-called <emphasis
role="term">directives</emphasis>. This is the same kind of
relationship as between HTML tags (e.g.:
<literal>&lt;table&gt;</literal> and
<literal>&lt;/table&gt;</literal>) and HTML elements (e.g., the
<literal>table</literal> element) to which you refer to with the HTML
tags. (If you don't understand this difference then consider "FTL tag"
and "directive" synonyms.)</para>
<note>
<para>You can easily try writing templates on <link
xlink:href="http://freemarker-online.kenshoo.com/">http://freemarker-online.kenshoo.com/</link></para>
</note>
<section>
<title>Some basic directives</title>
<para>Here we will look at some of the most commonly used directives
(<link linkend="ref_directives">but there are much
more</link>).</para>
<section>
<title>The if directive</title>
<para>With the <literal>if</literal> directive you can
conditionally skip a section of the template. For example, assume
that in the <link linkend="example.first">very first
example</link> you want to greet your boss, Big Joe, differently
than other users:</para>
<programlisting role="template">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Welcome!&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;
Welcome ${user}<emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>, our beloved leader<emphasis>&lt;/#if&gt;</emphasis>!
&lt;/h1&gt;
&lt;p&gt;Our latest product:
&lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>Here you have told FreeMarker that the <quote>, our beloved
leader</quote> should be there only if the value of the variable
<literal>user</literal> is equal to the string <literal>"Big
Joe"</literal>. In general, things between <literal>&lt;#if
<replaceable>condition</replaceable>&gt;</literal> and
<literal>&lt;/#if&gt;</literal> tags are skipped if
<literal><replaceable>condition</replaceable></literal> is false
(the boolean value).</para>
<para>Let's look at
<literal><replaceable>condition</replaceable></literal> more
closely: <literal>==</literal> is an operator that tests if the
values at its left and right side are equivalent, and the results
is a boolean value, true or false accordingly. On the left side of
<literal>==</literal> I have <link
linkend="topic.qStart.accessVariables">referenced a
variable</link> with the syntax that should be already familiar;
this will be replaced with the value of the variable. In general,
unquoted words inside directives or interpolations are treated as
references to variables. On the right side I have specified a
literal string. Literal strings in templates must
<emphasis>always</emphasis> be put inside quotation marks.</para>
<para>This will print <quote>Pythons are free today!</quote> if
their price is 0:</para>
<programlisting role="template">&lt;#if animals.python.price == <emphasis>0</emphasis>&gt;
Pythons are free today!
&lt;/#if&gt;</programlisting>
<para>Similarly as earlier when a string was specified directly,
here a number is specified directly (<literal>0</literal>). Note
that the number is <emphasis>not</emphasis> quoted. If you quoted
it (<literal>"0"</literal>), FreeMarker would misinterpret it as a
string literal, and because the price to compare it to is a
number, you get an error.</para>
<para>This will print "Pythons are not free today!" if their price
is not 0:</para>
<programlisting role="template">&lt;#if animals.python.price <emphasis>!=</emphasis> 0&gt;
Pythons are not free today!
&lt;/#if&gt;</programlisting>
<para>As you probably guessed, <literal>!=</literal> means
<quote>not equals</quote>.</para>
<para>You can write things like this too (using <link
linkend="example.qStart.dataModelWithHashes">the data-model used
to demonstrate hashes</link>):</para>
<programlisting role="template">&lt;#if <emphasis>animals.python.price &lt; animals.elephant.price</emphasis>&gt;
Pythons are cheaper than elephants today.
&lt;/#if&gt;</programlisting>
<para>With the <literal>&lt;#else&gt;</literal> tag you can
specify what to do if the condition is false. For example:</para>
<programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
Pythons are cheaper than elephants today.
<emphasis>&lt;#else&gt;</emphasis>
Pythons are not cheaper than elephants today.
&lt;/#if&gt;</programlisting>
<para>This prints <quote>Pythons are cheaper than elephants
today.</quote> if the price of python is less than the price of
elephant, or else it prints <quote>Pythons are not cheaper than
elephants today.</quote> You can refine this further by using
<literal>elseif</literal>:</para>
<programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
Pythons are cheaper than elephants today.
<emphasis>&lt;#elseif animals.elephant.price &lt; animals.python.price&gt;</emphasis>
Elephants are cheaper than pythons today.
&lt;#else&gt;
Elephants and pythons cost the same today.
&lt;/#if&gt;</programlisting>
<para>If you have a variable with boolean value (a true/false
thing) then you can use it directly as the
<literal><replaceable>condition</replaceable></literal> of
<literal>if</literal>:</para>
<programlisting role="template">&lt;#if animals.python.protected&gt;
Pythons are protected animals!
&lt;/#if&gt;</programlisting>
</section>
<section>
<title>The list directive</title>
<anchor xml:id="topic.tutorial.list"/>
<para>This is needed when you want to list something. For example
if you merge this template with the <link
linkend="example.qStart.dataModelWithSequences">data-model used
earlier to demonstrate sequences</link>:</para>
<programlisting role="template">&lt;p&gt;We have these animals:
&lt;table border=1&gt;
<emphasis>&lt;#list animals as animal&gt;</emphasis>
&lt;tr&gt;&lt;td&gt;${<emphasis>animal</emphasis>.name}&lt;td&gt;${<emphasis>animal</emphasis>.price} Euros
<emphasis>&lt;/#list&gt;</emphasis>
&lt;/table&gt;</programlisting>
<para>then the output will be:</para>
<programlisting role="output">&lt;p&gt;We have these animals:
&lt;table border=1&gt;
<emphasis>&lt;tr&gt;&lt;td&gt;mouse&lt;td&gt;50 Euros
&lt;tr&gt;&lt;td&gt;elephant&lt;td&gt;5000 Euros
&lt;tr&gt;&lt;td&gt;python&lt;td&gt;4999 Euros</emphasis>
&lt;/table&gt;</programlisting>
<para>The generic form of the <literal>list</literal> directive
is:<literal> &lt;#list <replaceable>sequence</replaceable> as
<replaceable>loopVariable</replaceable>&gt;<replaceable>repeatThis</replaceable>&lt;/#list&gt;</literal>.
The <literal><replaceable>repeatThis</replaceable></literal> part
will be repeated for each item in the sequence that you have
specified with
<literal><replaceable>sequence</replaceable></literal>, one after
the other, starting from the first item. In all repetitions
<literal><replaceable>loopVariable</replaceable></literal> will
hold the value of the current item. This variable exists only
between the <literal>&lt;#list
<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#list&gt;</literal> tags.</para>
<para>The <literal><replaceable>sequence</replaceable></literal>
can be any kind of expression. For example we could list the
fruits of the example data model like this:</para>
<programlisting role="template">&lt;ul&gt;
<emphasis>&lt;#list misc.fruits as fruit&gt;</emphasis>
&lt;li&gt;${fruit}
<emphasis>&lt;/#list&gt;</emphasis>
&lt;/ul&gt;</programlisting>
<para>The <literal>misc.fruits</literal> expression should be
familiar to you; it <link
linkend="topic.qStart.accessVariables">references a variable in
the data-model</link>.</para>
<para>A problem with the above example is that if we happen to
have 0 fruits, it will still print an empty
<literal>&lt;ul&gt;&lt;/ul&gt;</literal> instead of just nothing.
To avoid that, you can use this form of
<literal>list</literal>:</para>
<programlisting role="template">&lt;#list misc.fruits&gt;
&lt;ul&gt;
<emphasis> &lt;#items as fruit&gt;</emphasis>
&lt;li&gt;${fruit}
<emphasis> &lt;/#items&gt;</emphasis>
&lt;/ul&gt;
&lt;/#list&gt;</programlisting>
<para>Here, the <literal>list</literal> directive represents the
listing as a whole, and only the part inside the
<literal>items</literal> directive is repeated for each fruit. If
we have 0 fruits, everything inside <literal>list</literal> is
skipped, hence we will not have <literal>ul</literal> tags in
case.</para>
<para>Another frequent listing-related task: let's list the fruits
separating them with something, like a comma:</para>
<programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}<emphasis>&lt;#sep&gt;, </emphasis>&lt;/#list&gt;</programlisting>
<programlisting role="output">&lt;p&gt;Fruits: orange, banana</programlisting>
<para>The section covered by <literal>sep</literal> (which we
could be written like this too:
<literal><replaceable>...</replaceable>&lt;#sep&gt;,
&lt;/#sep&gt;&lt;/#list&gt;</literal>) will be only executed when
there will be a next item. Hence there's no comma after the last
fruit.</para>
<para>Here again, what if we have 0 fruits? Just printing
<quote>Fruits:</quote> and then nothing is awkward. A
<literal>list</literal>, just like an <literal>if</literal>, can
have an <literal>else</literal>, which is executed if there were 0
list items:</para>
<programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}&lt;#sep&gt;, <emphasis>&lt;#else&gt;None</emphasis>&lt;/#list&gt;</programlisting>
<note>
<para>As a matter of fact, this simplistic example could be
written like this, but it uses language devices that are off
topic here:</para>
<programlisting role="template">&lt;p&gt;Fruits: ${fruits?join(", ", "None")}</programlisting>
</note>
<para>All these directives (<literal>list</literal>,
<literal>items</literal>, <literal>sep</literal>,
<literal>else</literal>) can be used together:</para>
<programlisting role="template">&lt;#list misc.fruits&gt;
&lt;p&gt;Fruits:
&lt;ul&gt;
&lt;#items as fruit&gt;
&lt;li&gt;${fruit}&lt;#sep&gt; and&lt;/#sep&gt;
&lt;/#items&gt;
&lt;/ul&gt;
&lt;#else&gt;
&lt;p&gt;We have no fruits.
&lt;/#list&gt;</programlisting>
<note>
<para>You can read more about these directives <link
linkend="ref_directive_list">in the Reference</link>.</para>
</note>
</section>
<section>
<title>The include directive</title>
<para>With the <literal>include</literal> directive you can insert
the content of another file into the template.</para>
<para>Suppose you have to show the same copyright notice on
several pages. You can create a file that contains the copyright
notice only, and insert that file everywhere where you need that
copyright notice. Say, you store this copyright notice in
<literal>copyright_footer.html</literal>:</para>
<programlisting role="template">&lt;hr&gt;
&lt;i&gt;
Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
&lt;br&gt;
All Rights Reserved.
&lt;/i&gt;</programlisting>
<para>Whenever you need that file you simply insert it with the
<literal>include</literal> directive:</para>
<programlisting role="template">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Test page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Test page&lt;/h1&gt;
&lt;p&gt;Blah blah...
<emphasis> &lt;#include "/copyright_footer.html"&gt;</emphasis>
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>and the output will be:</para>
<programlisting role="output">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Test page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Test page&lt;/h1&gt;
&lt;p&gt;Blah blah...
<emphasis>&lt;hr&gt;
&lt;i&gt;
Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
&lt;br&gt;
All Rights Reserved.
&lt;/i&gt;</emphasis>
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>If you change the <literal>copyright_footer.html</literal>,
then the visitor will see the new copyright notice on all
pages.</para>
<note>
<para>A much more powerful way of reusing snippets is using
macros, but that's an advanced topic <link
linkend="dgui_misc_userdefdir">discussed later</link>.</para>
</note>
</section>
</section>
<section>
<title>Using directives together</title>
<para>You can use directives as many times on a page as you want,
and you can nest directives into each other freely. For example,
here you nest <literal>if</literal> directive inside a
<literal>list</literal> directive:</para>
<programlisting role="template"><emphasis>&lt;#list animals as animal&gt;</emphasis>
&lt;div<emphasis>&lt;#if animal.protected&gt;</emphasis><emphasis> </emphasis>class="protected"<emphasis>&lt;/#if&gt;</emphasis>&gt;
${animal.name} for ${animal.price} Euros
&lt;/div&gt;
<emphasis>&lt;/#list&gt;</emphasis></programlisting>
<para>Note that since FreeMarker does not interpret text outside FTL
tags, interpolations and FTL comments, above you could use the FTL
tags inside HTML attributes without problem.</para>
</section>
<section>
<title>Using built-ins</title>
<para>The so-called built-ins are like subvariables (or rather like
methods, if you know that Java term) that aren't coming from the
data-model, but added by FreeMarker to the values. In order to make
it clear where subvariables comes from, you have to use
<literal>?</literal> (question mark) instead of <literal>.</literal>
(dot) to access them. <anchor
xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most
commonly used built-ins:</para>
<itemizedlist>
<listitem>
<para><literal>user?upper_case</literal> gives the upper case
version of the value of <literal>user</literal> (like
<quote>JOHN DOE</quote> instead of <quote>John
Doe</quote>)</para>
</listitem>
<listitem>
<para><literal>animal.name?cap_first</literal> give the
<literal>animal.name</literal> with its first letter converted
to upper case (like <quote>Mouse</quote> instead of
<quote>mouse</quote>)</para>
</listitem>
<listitem>
<para><literal>user?length</literal> gives the number of
<emphasis>characters</emphasis> in the value of
<literal>user</literal> (8 for <quote>John Doe</quote>)</para>
</listitem>
<listitem>
<para><literal>animals?size</literal> gives the number of
<emphasis>items</emphasis> in the <literal>animals</literal>
sequence (3 in our example data-model)</para>
</listitem>
<listitem>
<para>If you are between <literal>&lt;#list animals as
animal&gt;</literal> and the corresponding
<literal>&lt;/#list&gt;</literal> tag:</para>
<itemizedlist>
<listitem>
<para><literal>animal?index</literal> gives the 0-based
index of <literal>animal</literal> inside
<literal>animals</literal></para>
</listitem>
<listitem>
<para><literal>animal?counter</literal> is like
<literal>index</literal>, but gives the 1-based index</para>
</listitem>
<listitem>
<para><literal>animal?item_parity</literal> gives the
strings <quote>odd</quote> or <quote>even</quote>, depending
on the current counter parity. This is commonly used for
coloring rows with alternating colors, like in
<literal>&lt;td
class="${animal?item_parity}Row"&gt;</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>Some built-ins require parameters to specify the behavior
more, for example:</para>
<itemizedlist>
<listitem>
<para><literal>animal.protected?string("Y", "N")</literal>
return the string <quote>Y</quote> or <quote>N</quote> depending
on the boolean value of
<literal>animal.protected</literal>.</para>
</listitem>
<listitem>
<para><literal>animal?item_cycle('lightRow',
'darkRow')</literal> is the more generic variant of
<literal>item_parity</literal> from earlier.</para>
</listitem>
<listitem>
<para><literal>fruits?join(", ")</literal>: converts the list to
a string by concatenating items, and inserting the parameter
separator between each items (like <quote>orange,
banana</quote>)</para>
</listitem>
<listitem>
<para><literal>user?starts_with("J")</literal> gives boolean
true of false depending on if <literal>user</literal> starts
with the letter <quote>J</quote> or not.</para>
</listitem>
<listitem>
<para><literal>animals?filter(it -&gt; it.protected)</literal>
gives the list of protected animals. To list protected animals
only, you could use <literal>&lt;#list animals?filter(it -&gt;
it.protected) as
animal&gt;<replaceable>...</replaceable>&lt;/#list&gt;</literal>.</para>
</listitem>
</itemizedlist>
<para>Built-in applications can be chained, like
<literal>fruits?join(", ")?upper_case</literal> will first convert
the list a to a string, then converts it to upper case. (This is
just like you can chain <literal>.</literal>-s (dots) too.)</para>
<para>You can find the <link linkend="ref_builtins">full set of
built-ins in the Reference</link>.</para>
</section>
<section>
<title>Dealing with missing variables</title>
<para>The data-model often has variables that are optional (i.e.,
sometimes missing). To spot some typical human mistakes, FreeMarker
doesn't tolerate references to missing variables unless you tell
explicitly what to do if the variable is missing. Here we will show
the two most typical ways of doing that.</para>
<para><phrase role="forProgrammers">Note for programmers: A
non-existent variable and a variable with <literal>null</literal>
value is the same for FreeMarker. The "missing" term used here
covers both cases.</phrase></para>
<para>Wherever you refer to a variable, you can specify a default
value for the case the variable is missing by following the variable
name with a <literal>!</literal> and the default value. Like in the
following example, when <literal>user</literal> is missing from data
model, the template will behave like if <literal>user</literal>'s
value were the string <literal>"visitor"</literal>. (When
<literal>user</literal> isn't missing, this template behaves exactly
like with <literal>${user}</literal>):</para>
<programlisting role="template">&lt;h1&gt;Welcome ${user<emphasis>!"visitor"</emphasis>}!&lt;/h1&gt;</programlisting>
<para>You can ask whether a variable isn't missing by putting
<literal>??</literal> after its name. Combining this with the
already introduced <literal>if</literal> directive you can skip the
whole greeting if the <literal>user</literal> variable is
missing:</para>
<programlisting role="template">&lt;#if <emphasis>user??</emphasis>&gt;&lt;h1&gt;Welcome ${user}!&lt;/h1&gt;&lt;/#if&gt;</programlisting>
<para>Regarding variable accessing with multiple steps, like
<literal>animals.python.price</literal>, writing
<literal>animals.python.price!0</literal> is correct only if
<literal>animals.python</literal> is never missing and only the last
subvariable, <literal>price</literal>, is possibly missing (in which
case here we assume it's <literal>0</literal>). If
<literal>animals</literal> or <literal>python</literal> is missing,
the template processing will stop with an "undefined variable"
error. To prevent that, you have to write
<literal>(animals.python.price)!0</literal>. In that case the
expression will be <literal>0</literal> even if
<literal>animals</literal> or <literal>python</literal> is missing.
Same logic goes for <literal>??</literal>;
<literal>animals.python.price??</literal> versus
<literal>(animals.python.price)??</literal>.</para>
</section>
<section xml:id="dgui_quickstart_template_autoescaping">
<title>Escaping for HTML, XML and other markup</title>
<para>Let's say the template generates HTML, and you insert values
with <literal>${<replaceable>...</replaceable>}</literal> that are
plain text (not HTML), like company names coming from a database.
Characters that has special meaning in HTML must be
<emphasis>escaped</emphasis> in such values, like if
<literal>name</literal> is <quote>Someone &amp; Co.</quote> then
<literal>${name}</literal> should print <quote>Someone
<emphasis>&amp;amp;</emphasis> Co.</quote>.</para>
<para>FreeMarker automatically escapes all values printed with
<literal>${<replaceable>...</replaceable>}</literal> <emphasis>if
it's properly configured</emphasis> (that's the responsibility of
the programmers; <link
linkend="pgui_config_outputformatsautoesc">see here how</link>). The
recommended practice is using <literal>ftlh</literal> file extension
to activate HTML auto-escaping, and <literal>ftlx</literal> file
extension to activate XML auto-escaping.</para>
<para>You can try if auto-escaping is on like
<literal>${"&lt;"}</literal> and then checking the raw output (for
HTML or XML escaping). If it's not, and the configuration won't be
adjusted, add this as the very first line of the template:</para>
<programlisting role="template">&lt;#ftl output_format="HTML"&gt;</programlisting>
<para>(Use <literal>"XML"</literal> instead of
<literal>"HTML"</literal> above if you generate XML.)</para>
<para>If the string value to print deliberately contains markup,
auto-escaping must be prevented like
<literal>${<replaceable>value</replaceable>?no_esc}</literal>.</para>
<para>You can find out much more about auto-escaping and output
formats <link linkend="dgui_misc_autoescaping">here...</link></para>
<note>
<para>The kind of automatic escaping described here requires at
least FreeMarker 2.3.24. If you have to use an earlier version,
use the deprecated <link
linkend="ref_directive_escape"><literal>escape</literal>
directive</link> instead.</para>
</note>
</section>
</section>
</chapter>
<chapter xml:id="dgui_datamodel">
<title>Values, Types</title>
<section xml:id="dgui_datamodel_basics">
<title>Basics</title>
<note>
<para>It is assumed that you have already read the <xref
linkend="dgui_quickstart"/> chapter.</para>
</note>
<para>Understanding the concept of values and types is crucial for the
understanding of data-models. However, the concept of values and types
is not confined to data-models, as you will see.</para>
<section xml:id="topic.value">
<title>What is a value?</title>
<indexterm>
<primary>value</primary>
</indexterm>
<para><phrase role="forProgrammers">Real programmers can safely skip
this section.</phrase></para>
<para>Examples of <emphasis>values</emphasis> as you know the term
from the everyday math are 16, 0.5, and so on, i.e. numbers. In the
case of computer languages the value term has a wider meaning, as a
value needn't be a number. For example, take this data-model:</para>
<programlisting role="dataModel" xml:id="example.stdDataModel">(root)
|
+- user = "Big Joe"
|
+- today = Jul 6, 2007
|
+- todayHoliday = false
|
+- lotteryNumbers
| |
| +- (1st) = 20
| |
| +- (2nd) = 14
| |
| +- (3rd) = 42
| |
| +- (4th) = 8
| |
| +- (5th) = 15
|
+- cargo
|
+- name = "coal"
|
+- weight = 40
</programlisting>
<para>We say that the <emphasis>value</emphasis> of the the
<literal>user</literal> variable is "Big Joe" (a string), the
<emphasis>value</emphasis> of <literal>today</literal> is Jul 6,
2007 (a date), the <emphasis>value</emphasis> of
<literal>todayHoliday</literal> is false (a boolean, ie. a yes/no
thing). The <emphasis>value</emphasis> of
<literal>lotteryNumbers</literal> is the sequence that contains 20,
14, 42, 8, 15. Surely <literal>lotteryNumbers</literal> is multiple
values in the sense that it <emphasis>contains</emphasis> multiple
values (for example, the 2nd item in it is a the
<emphasis>value</emphasis> 14), but still,
<literal>lotteryNumbers</literal> itself is a single value. It's
like a box that contains many other items; the whole box can be seen
as a single item. Last not least we also have the
<emphasis>value</emphasis> of <literal>cargo</literal>, which is a
hash (a box-like thing again).So, a value is something that can be
stored in a variable (e.g., in <literal>user</literal> or
<literal>cargo</literal> or <literal>cargo.name</literal>). But a
value need not be stored in a variable to be called a value, for
example we have the value 100 here:</para>
<programlisting role="template">&lt;#if cargo.weight &lt; <emphasis>100</emphasis>&gt;Light cargo&lt;/#if&gt;</programlisting>
<para>The temporaly result of a calculations are also called values,
like 20 and 120 when this template is executed (it will print
120):</para>
<programlisting role="template">${cargo.weight / 2 + 100}</programlisting>
<para>Explanation for this last: As the result of dividing the two
values, 40 (the weight of the cargo) and 2, a new value 20 is
created. Then 100 is added to it, so the value 120 is created. Then
120 is printed
(<literal>${<replaceable>...</replaceable>}</literal>), and the
template execution goes on and all these values gone.</para>
<para>Certainly now you feel what the value term means.</para>
</section>
<section>
<title>What is type?</title>
<para>Values have an important aspect, their type. For example the
type of the value of the <literal>user</literal> variable is string,
and the type of the value of the <literal>lotteryNumbers</literal>
variable is sequence. The type of a value is important because it
determines to a large extent how and where you can use the value.
Like <literal>${user / 2}</literal> is an error, but
<literal>${cargo.weight / 2}</literal> works and prints 20, since
division only does make sense for a number, but not for a string.
Or, using dot like in <literal>cargo.name</literal> does make sense
only if <literal>cargo</literal> is a hash. Or, you can list with
<literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
sequences only. Or, the condition of <literal>&lt;#if
...&gt;</literal> must be a boolean. And so on.</para>
<note>
<para>A little terminology... Saying "a boolean" or "a boolean
value" or "a value of type boolean" are all the same.</para>
</note>
<para xml:id="topic.multitype"><indexterm>
<primary>Multi-typed value</primary>
</indexterm>A value can have multiple types at the same time,
although it's rarely utilized. For example in the data-model below
<literal>mouse</literal> is both a string and a hash:</para>
<programlisting role="dataModel">(root)
|
+- mouse = "Yerri"
|
+- age = 12
|
+- color = "brown"</programlisting>
<para>If you merge this template with the above data-model:</para>
<programlisting role="template">${mouse} &lt;#-- uses mouse as a string --&gt;
${mouse.age} &lt;#-- uses mouse as a hash --&gt;
${mouse.color} &lt;#-- uses mouse as a hash --&gt;</programlisting>
<para>the output will be:</para>
<programlisting role="output">Yerri
12
brown</programlisting>
</section>
<section>
<title>The data-model is a hash</title>
<para>Looking at the various data-model examples you may already
realized: the thing marked as "(root)" is just a value of type hash.
When you write something like <literal>user</literal>, that means
that you want the "user" variable stored in the root hash. Like if
you were writing <literal>root.user</literal>, except that there is
no variable called "root" so that wouldn't work.</para>
<para>Some may get confused by the fact that our example data-model,
that is, the root hash, contains further hashes and sequences
(<literal>lotteryNumbers</literal> and <literal>cargo</literal>).
There is nothing special in that. A hash contains other variables,
and those variables have a value, which can be a string, a number,
etc., and of course it can be a hash or sequence as well. Because,
as it was explained earlier, a sequence or a hash is just a value,
like a string or a number is.</para>
</section>
</section>
<section xml:id="dgui_datamodel_types">
<title>The types</title>
<para>The suppored types are:</para>
<itemizedlist spacing="compact">
<listitem>
<para><link linkend="dgui_datamodel_scalar"
os="">Scalars:</link></para>
<itemizedlist spacing="compact">
<listitem>
<para>String</para>
</listitem>
<listitem>
<para>Number</para>
</listitem>
<listitem>
<para>Boolean</para>
</listitem>
<listitem>
<para>Date-like (date, time, or date-time)</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link
linkend="dgui_datamodel_container">Containers:</link></para>
<itemizedlist spacing="compact">
<listitem>
<para>Hash</para>
</listitem>
<listitem>
<para>Sequence</para>
</listitem>
<listitem>
<para>Collection</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Subroutines:</para>
<itemizedlist spacing="compact">
<listitem>
<para><link linkend="dgui_datamodel_method">Methods and
functions</link></para>
</listitem>
<listitem>
<para><link linkend="dgui_datamodel_userdefdir">User-defined
directives</link></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Miscellaneous/seldom used:</para>
<itemizedlist spacing="compact">
<listitem>
<para><link linkend="dgui_datamodel_node">Node</link></para>
</listitem>
<listitem>
<para><link linkend="dgui_datamodel_markupoutput">Markup
output</link></para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<section xml:id="dgui_datamodel_scalar">
<title>Scalars</title>
<anchor xml:id="topic.designer.scalarVariable"/>
<para>These are the basic, simple kind of values. They can
be:</para>
<itemizedlist>
<listitem>
<para><indexterm>
<primary>string</primary>
<secondary>the FTL value type</secondary>
</indexterm>String: It is simple text, e.g., the name of a
product.</para>
<para>If you want to give a string value directly in the
template, rather than use a variable that comes from the data
model, you write the text between quotation marks, e.g.,
<literal>"green mouse"</literal> or <literal>'green
mouse'</literal>. (More details regarding the syntax can be
found <link linkend="dgui_template_exp_direct_string"
xml:lang="">later</link>.)</para>
</listitem>
<listitem>
<para><indexterm>
<primary>number</primary>
<secondary>the FTL value type</secondary>
</indexterm>Number: For example the price of a product.
<phrase role="forProgrammers">Whole numbers and non-whole
numbers are not distinguished; there is only a single number
type. So for example 3/2 will be always 1.5, and never 1. Just
like if you are using a calculator.</phrase></para>
<para>If you want to give a numerical value directly in the
template, then you write for example: <literal>150</literal> or
<literal>-90.05</literal> or <literal>0.001</literal>. (More
details regarding the syntax can be found <link
linkend="dgui_template_exp_direct_number"
xml:lang="">later</link>.)</para>
</listitem>
<listitem>
<para><indexterm>
<primary>boolean</primary>
<secondary>the FTL value type</secondary>
</indexterm>Boolean: A boolean value represents a logical true
or false (yes or no). For example, if a the visitor has been
logged in or not. Typically you use booleans as the condition of
the <literal>if</literal> directive, like <literal>&lt;#if
loggedIn
&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal> or
<literal>&lt;#if price ==
0&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>; in
the last case the result of the <literal>price == 0</literal>
part is a boolean value.</para>
<para>In the templates you can directly specify a boolean with
the reserved words <literal>true</literal> and
<literal>false</literal>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>date</primary>
<secondary>the FTL value type</secondary>
</indexterm><indexterm>
<primary>time</primary>
<secondary>the FTL value type</secondary>
</indexterm><indexterm>
<primary>date-time</primary>
<secondary>the FTL value type</secondary>
</indexterm>Date: A date-like value stores date/time related
data. It has three variations:</para>
<itemizedlist>
<listitem>
<para>Date: Like April 4, 2003. Day precision, no time of
day part.</para>
</listitem>
<listitem>
<para>Time: Like 10:19:18 PM. Millisecond precision, no date
part.</para>
</listitem>
<listitem>
<para>Date-time (sometimes called "time stamp") as April 4,
2003 10:19:18 PM. Both date and time, with millisecond
precision.</para>
</listitem>
</itemizedlist>
<para>Unfortunately, because of the limitations of the Java
platform, FreeMarker sometimes can't decide which parts of the
date are in use (i.e., if it is date-time, a date or a time).
The solution for this problem is an advanced topic that will be
discussed <link
linkend="ref_builtin_date_datetype">later</link>.</para>
<para>It is possible to define date-like values directly in
templates, but this is an advanced topic that will be explained
<link linkend="ref_builtin_string_date">later</link>.</para>
</listitem>
</itemizedlist>
<para>Bear in mind that FreeMarker distinguishes strings from
numbers, booleans and date-like values. For example, while the
string <literal>"150"</literal> looks like the number
<literal>150</literal>, 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.</para>
</section>
<section xml:id="dgui_datamodel_container">
<title>Containers</title>
<remark>Re-explanation of hashes and sequences from a more
''professional'' viewpoint as earlier, and some meditation about
them.</remark>
<para>These are the values whose purpose is to contain other
variables; they are just containers. The contained variables are
often referred as <emphasis>sub variables</emphasis>. The container
types are:</para>
<itemizedlist>
<listitem>
<para><indexterm>
<primary>hash</primary>
<secondary>the FTL value type</secondary>
</indexterm>Hash: Associates a unique lookup name with each of
its sub variables. The name is an unrestricted string. A hash
<emphasis>doesn't define an ordering</emphasis> for the sub
variables in it. That is, there is no such thing as the first
subvariable, and the second subvariable, etc.; the variables are
just accessed by name.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>sequence</primary>
<secondary>the FTL value type</secondary>
</indexterm>Sequence: Associates an integer number with each
of its sub variables. The first subvariable is associated with
0, the second with 1, the third to 2, and so on; the sub
variables are ordered. These numbers are often called the
<emphasis>indexes</emphasis> of the sub variables. Sequences are
usually dense, i.e., all indexes up to the index of the last
subvariable have an associated subvariable, but it's not
strictly necessary. The type of the subvariable values need not
be the same.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>collection</primary>
<secondary>the FTL value type</secondary>
</indexterm>Collection: A collection, from the viewpoint of
the template author, is a restricted sequence. You cannot access
its size or retrieve its sub variables by index, but they can be
still listed with the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link>. Furthermore, very often they can only be
listed once. (If you are a Java programmer,
<quote>iterable</quote> would be a more fitting name than
collection.)</para>
</listitem>
</itemizedlist>
<para>Note that since <link linkend="topic.multitype">a value can
have multiple types</link>, 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.</para>
<para>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.</para>
<para>The data-model itself (or better said the root of it) is a
hash.</para>
<para>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 <literal>+</literal>;
see that in the <link linkend="exp_cheatsheet">chapter about
expressions</link>, and please note the performance
consequences.)</para>
</section>
<section>
<title>Subroutines</title>
<section xml:id="dgui_datamodel_method">
<title>Methods and functions</title>
<anchor xml:id="topic.designer.methodVariable"/>
<indexterm>
<primary>method</primary>
<secondary>the FTL value type</secondary>
</indexterm>
<para>A value that is a method or a function is used to calculate
another value, influenced by the parameters you give to it.</para>
<para><phrase role="forProgrammers">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.</phrase></para>
<para>Suppose that programmers have put the method variable
<literal>avg</literal> 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 <literal>avg</literal>, then you get
the value 4.</para>
<para>The usage of methods will be explained <link
linkend="dgui_template_exp_methodcall">later</link>, but perhaps
this example helps to understand what methods are:</para>
<programlisting role="template">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)}</programlisting>
<para>this will output:</para>
<programlisting role="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</programlisting>
<para>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 (<phrase
role="forProgrammers">as they reflect the methods of Java
objects</phrase>), and functions are defined in templates (with
the <link
linkend="ref.directive.function"><literal>function</literal>
directive</link> -- an advanced topic), but both can be used on
the same way.</para>
</section>
<section xml:id="dgui_datamodel_userdefdir">
<title>User-defined directives</title>
<indexterm>
<primary>macro</primary>
<secondary>the FTL value type</secondary>
</indexterm>
<indexterm>
<primary>directive</primary>
<secondary>the FTL value type</secondary>
</indexterm>
<indexterm>
<primary>user-defined directive</primary>
<secondary>the FTL value type</secondary>
</indexterm>
<para>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
<link linkend="dgui_misc_userdefdir">later</link> in its own
chapter.</para>
<para><phrase role="forProgrammers">For programmer types:
user-defined directives (such as macros), are first-class values
too, just like functions/methods are.</phrase></para>
<para>Just to get an idea about user-defined directives (so just
ignore this if you won't understand), assume we have a variable,
<literal>box</literal>, 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 <literal>box</literal> variable could be
used in the template like this (for example):</para>
<programlisting role="template">&lt;@<emphasis>box</emphasis> title="Attention!"&gt;
Too much copy-pasting may leads to
maintenance headaches.
&lt;/@<emphasis>box</emphasis>&gt;</programlisting>
</section>
<section>
<title>Function/method versus user-defined directive</title>
<para>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:</para>
<itemizedlist>
<listitem>
<para>... the purpose of it is generating a piece of the
output that's not just a single value, and typically involves
markup. The template language was designed for printing to the
output directly, piece by piece, as it goes though
<literal>list</literal> loops, <literal>if</literal>-s, etc.
Building up a string value in a variable then returning it is
much less convenient.</para>
</listitem>
<listitem>
<para>... it's the side-effect that is important and not the
return value. For example, a directive whose purpose is to add
an entry to the server log is like that. (In fact you can't
have a return value for a user-defined directive, but some
kind of feedback is still possible by setting non-local
variables.)</para>
</listitem>
<listitem>
<para>... it will do flow control on the caller side (like for
example <literal>list</literal> or <literal>if</literal>
directives do). You just can't do that with a
function/method.</para>
</listitem>
<listitem>
<para>... you are using legacy escaping via the
<literal>escape</literal> directive (instead of <link
linkend="dgui_misc_autoescaping">auto-escaping</link>), and
the result contains markup. When you print the result with
<literal>${<replaceable>...</replaceable>}</literal>, the
markup will be escaped and thus ruined, but if it's printed by
a directive call
(<literal>&lt;@<replaceable>...</replaceable>&gt;</literal>),
it won't be.</para>
</listitem>
</itemizedlist>
<para>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.</para>
</section>
</section>
<section>
<title>Miscellaneous</title>
<section xml:id="dgui_datamodel_node">
<title>Nodes</title>
<indexterm>
<primary>node</primary>
<secondary>the FTL value type</secondary>
</indexterm>
<para>Node variables represent a node in a tree structure, and are
used mostly with <link linkend="xgui">XML processing</link>, which
is an advanced, and specialized topic.</para>
<para>Still, a quick overview <emphasis>for advanced
users</emphasis>: 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 <literal>h1</literal> element in an XHTML document,
then its name could be <literal>"h1"</literal>, it's node type
could be <literal>"element"</literal>, and it's namespace could be
<literal>"http://www.w3.org/1999/xhtml"</literal>. 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 <link
linkend="ref_builtins_node">in a later chapter</link> (that you
don't have to understand at this point).</para>
</section>
<section xml:id="dgui_datamodel_markupoutput">
<title>Markup output</title>
<indexterm>
<primary>markup output</primary>
<secondary>the FTL value type</secondary>
</indexterm>
<para>This type is related to <link
linkend="dgui_misc_autoescaping">auto-escaping mechanism</link>
introduced FreeMarker 2.3.24; you can <link
linkend="dgui_misc_autoescaping_movalues">read about this type
there</link>. 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.</para>
<para>Values of this type are usually produced inside the
templates (like with <link
linkend="ref_builtin_no_esc"><literal>no_esc</literal>
built-in</link> or <link linkend="ref_directive_assign">output
capturing assignments</link>), 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
<literal>${<replaceable>...</replaceable>}</literal>.</para>
</section>
</section>
</section>
</chapter>
<chapter xml:id="dgui_template">
<title>The Template</title>
<indexterm>
<primary>template</primary>
</indexterm>
<note>
<para>It is assumed that you have already read the <xref
linkend="dgui_quickstart"/> and the <xref linkend="dgui_datamodel"/>
chapter.</para>
</note>
<section xml:id="dgui_template_overallstructure">
<title>Overall structure</title>
<para>Templates are in fact programs you write in a language called
<indexterm>
<primary>FTL</primary>
</indexterm><emphasis role="term">FTL</emphasis> (for FreeMarker
Template Language). This is a quite simple programming language
designed for writing templates and nothing else.</para>
<para>A template (= FTL program) is a mix of the following
sections:</para>
<itemizedlist>
<listitem>
<para><emphasis role="term">Text</emphasis><indexterm>
<primary>text</primary>
</indexterm>: Text that will be printed to the output as
is.</para>
</listitem>
<listitem>
<para><emphasis role="term">Interpolation</emphasis><indexterm>
<primary>interpolation</primary>
</indexterm>: These sections will be replaced with a calculated
value in the output. Interpolations are delimited by
<literal>${</literal> and <literal>}</literal> (or with
<literal>#{</literal> and <literal>}</literal>, but that shouldn't
be used anymore; <link
linkend="ref_depr_numerical_interpolation">see more
here</link>).</para>
</listitem>
<listitem>
<para><emphasis role="term">FTL tags</emphasis><indexterm>
<primary>FTL tag</primary>
</indexterm>: FTL tags are a bit similar to HTML tags, but they
are instructions to FreeMarker and will not be printed to the
output.</para>
</listitem>
<listitem>
<para><emphasis role="term">Comments</emphasis><indexterm>
<primary>comment</primary>
</indexterm><indexterm>
<primary>&lt;#--...--&gt;</primary>
</indexterm><indexterm>
<primary>#</primary>
</indexterm>: Comments are similar to HTML comments, but they
are delimited by <literal>&lt;#--</literal> and
<literal>--&gt;</literal>. Comments will be ignored by FreeMarker,
and will not be written to the output.</para>
</listitem>
</itemizedlist>
<para>Let's see a concrete template. I have marked the template's
components with colors: <phrase role="markedText">text</phrase>,
<phrase role="markedInterpolation">interpolation</phrase>, <phrase
role="markedFTLTag">FTL tag</phrase>, <phrase
role="markedComment">comment</phrase>. With the <phrase
role="markedInvisibleText">[BR]</phrase>-s I intend to visualize the
<link linkend="gloss.lineBreak">line breaks</link>.</para>
<programlisting role="template"><phrase role="markedText">&lt;html&gt;<phrase
role="markedInvisibleText">[BR]</phrase>
&lt;head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
  &lt;title&gt;Welcome!&lt;/title&gt;<phrase role="markedInvisibleText">[BR]</phrase>
&lt;/head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
&lt;body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
  <phrase role="markedComment">&lt;#-- Greet the user with his/her name --&gt;</phrase><phrase
role="markedInvisibleText">[BR]</phrase>
  &lt;h1&gt;Welcome <phrase role="markedInterpolation">${user}</phrase>!&lt;/h1&gt;<phrase
role="markedInvisibleText">[BR]</phrase>
  &lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
  &lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
  <phrase role="markedFTLTag">&lt;#list animals as animal&gt;</phrase><phrase
role="markedInvisibleText">[BR]</phrase>
    &lt;li&gt;<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
role="markedInterpolation">${animal.price}</phrase> Euros<phrase
role="markedInvisibleText">[BR]</phrase>
  <phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
role="markedInvisibleText">[BR]</phrase>
  &lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
&lt;/body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
&lt;/html&gt;</phrase></programlisting>
<para>FTL distinguishes upper case and lower case letters. So
<literal>list</literal> is good directive name, while
<literal>List</literal> is not. Similarly <literal>${name}</literal>
is not the same as <literal>${Name}</literal> or
<literal>${NAME}</literal></para>
<para>It is important to realize that <phrase
role="markedInterpolation">interpolations</phrase> can be used in
<phrase role="markedText">text</phrase> (and in string literal
expressions; see <link
linkend="dgui_template_exp_stringop_interpolation">later</link>)
only.</para>
<para>An <phrase role="markedFTLTag">FTL tag</phrase> can't be inside
another <phrase role="markedFTLTag">FTL tag</phrase> nor inside an
<phrase role="markedInterpolation">interpolation</phrase>. For example
this is <emphasis>WRONG</emphasis>: <literal>&lt;#if &lt;#include
'foo'&gt;='bar'&gt;...&lt;/#if&gt;</literal></para>
<para><phrase role="markedComment">Comments</phrase> can be placed
inside <phrase role="markedFTLTag">FTL tags</phrase> and <phrase
role="markedInterpolation">interpolations</phrase>. For
example:</para>
<programlisting role="template"><phrase role="markedText">&lt;h1&gt;Welcome <phrase
role="markedInterpolation">${user <phrase role="markedComment">&lt;#-- The name of user --&gt;</phrase>}</phrase>!&lt;/h1&gt;<phrase
role="markedInvisibleText">[BR]</phrase>
&lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
<phrase role="markedFTLTag">&lt;#list <phrase role="markedComment">&lt;#-- some comment... --&gt;</phrase> animals as <phrase
role="markedComment">&lt;#-- again... --&gt;</phrase> animal&gt;</phrase><phrase
role="markedInvisibleText">[BR]</phrase></phrase>
<replaceable>...</replaceable></programlisting>
<note>
<para>For those of you who have tried the above examples: You may
notice that some of spaces, tabs and line breaks are missing from
the template output, even though we said that <phrase
role="markedText">text</phrase> is printed as is. Don't bother with
it now. This is because the feature called ''white-space stripping''
is turned on, and that automatically removes some superfluous
spaces, tabs and line breaks. This will be explained <link
linkend="dgui_misc_whitespace">later</link>.</para>
</note>
</section>
<section xml:id="dgui_template_directives">
<title>Directives</title>
<indexterm>
<primary>&lt;#...&gt;</primary>
</indexterm>
<indexterm>
<primary>#</primary>
</indexterm>
<anchor xml:id="term.designer.directive"/>
<remark>Note that the Expressions chapter depends on this chapter, and
Interpolations chapter depends on Expressions chapter. Thus Directives
must be the first chapter after Basics.</remark>
<para><indexterm>
<primary>directive</primary>
</indexterm>You use FTL tags to call <emphasis
role="term">directives</emphasis>. In the example you have called the
<literal>list</literal> directive. Syntactically you have done it with
two tags: <literal>&lt;#list animals as animal&gt;</literal> and
<literal>&lt;/#list&gt;</literal>.</para>
<para><indexterm>
<primary>FTL tag</primary>
</indexterm>There are two kind of FTL tags:</para>
<itemizedlist>
<listitem>
<para>Start-tag:
<literal>&lt;#<replaceable>directivename</replaceable>
<replaceable>parameters</replaceable>&gt;</literal></para>
</listitem>
<listitem>
<para>End-tag:
<literal>&lt;/#<replaceable>directivename</replaceable>&gt;</literal></para>
</listitem>
</itemizedlist>
<para>This is similar to HTML or XML syntax, except that the tag name
starts with <literal>#</literal>. If the directive doesn't have nested
content (content between the start-tag and the end-tag), you must use
the start-tag with no end-tag. For example you write <literal>&lt;#if
<replaceable>something</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>,
but just <literal>&lt;#include
<replaceable>something</replaceable>&gt;</literal> as FreeMarker knows
that the <literal>include</literal> directive can't have nested
content.</para>
<para>The format of the
<literal><replaceable>parameters</replaceable></literal> depends on
the
<literal><replaceable>directivename</replaceable></literal>.</para>
<para>In fact there are two types of directives: <link
linkend="gloss.predefinedDirective">predefined directives</link> and
<link linkend="gloss.userDefinedDirective">user-defined
directives</link>. For user-defined directives you use
<literal>@</literal> instead of <literal>#</literal>, for example
<literal>&lt;@mydirective
<replaceable>parameters</replaceable>&gt;<replaceable>...</replaceable>&lt;/@mydirective&gt;</literal>.
Further difference is that if the directive has no nested content, you
must use a tag like <literal>&lt;@mydirective
<replaceable>parameters</replaceable> /&gt;</literal>, similarly as in
XML (e.g. <literal>&lt;img <replaceable>...</replaceable>
/&gt;</literal>). But user-defined directives is an advanced topic
that will be discussed <link
linkend="dgui_misc_userdefdir">later</link>.</para>
<para>FTL tags, like HTML tags, must be properly nested. So the code
below is wrong, as the <literal>if</literal> directive is both inside
and outside of the nested content of the <literal>list</literal>
directive:</para>
<programlisting role="template">&lt;ul&gt;
<emphasis>&lt;#list animals as animal&gt;</emphasis>
&lt;li&gt;${animal.name} for ${animal.price} Euros
<emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>
(except for you)
<emphasis>&lt;/#list&gt;</emphasis> &lt;#-- WRONG! The "if" has to be closed first. --&gt;
<emphasis>&lt;/#if&gt;</emphasis>
&lt;/ul&gt;</programlisting>
<para>Note that FreeMarker doesn't care about the nesting of HTML
tags, only about the nesting of FTL tags. It just sees HTML as flat
text, it doesn't interpret it in any way.</para>
<para>If you try to use a non-existing directive (e.g., you mistype
the directive name), FreeMarker will decline to use the template and
produce an error message.</para>
<para>FreeMarker ignores superfluous <link
linkend="gloss.whiteSpace">white-space</link> inside FTL tags. So you
can write this:</para>
<programlisting role="template"><phrase role="markedText"><phrase
role="markedFTLTag">&lt;#list<phrase role="markedInvisibleText">[BR]</phrase>
  animals       as<phrase role="markedInvisibleText">[BR]</phrase>
     animal<phrase role="markedInvisibleText">[BR]</phrase>
&gt;</phrase><phrase role="markedInvisibleText">[BR]</phrase>
<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
role="markedInterpolation">${animal.price}</phrase> Euros<phrase
role="markedInvisibleText">[BR]</phrase>
<phrase role="markedFTLTag">&lt;/#list    &gt;</phrase></phrase></programlisting>
<para>You may not, however, insert white-space between the
<literal>&lt;</literal> or <literal>&lt;/</literal> and the directive
name.</para>
<para>The complete list and description of all directives can be found
in the <xref linkend="ref_directives"/> (but I recommend that you look
at the chapter about expressions first).</para>
<note>
<para>FreeMarker can be configured to use <literal>[</literal> and
<literal>]</literal> instead of <literal>&lt;</literal> and
<literal>&gt;</literal> in the FTL tags and FTL comments, like
<literal>[#if user == "Big
Joe"]<replaceable>...</replaceable>[/#if]</literal>. For more
information read: <xref
linkend="dgui_misc_alternativesyntax"/>.</para>
</note>
<note>
<para>FreeMarker can be configured so that it understands predefined
directives without <literal>#</literal> (like <literal>&lt;if user
== "Big
Joe"&gt;<replaceable>...</replaceable>&lt;/if&gt;</literal>).
However we don't recommend the usage of this mode. For more
information read: <xref linkend="ref_depr_oldsyntax"/></para>
</note>
</section>
<section xml:id="dgui_template_exp">
<title>Expressions</title>
<para><indexterm>
<primary>expression</primary>
</indexterm>When you supply values for interpolations or directive
parameters you can use variables or more complex expressions. For
example, if x is the number 8 and y is 5, the value of <literal>(x +
y)/2</literal> resolves to the numerical value 6.5.</para>
<para>Before we go into details, let's see some concrete
examples:</para>
<itemizedlist>
<listitem>
<para>When you supply value for interpolations: The usage of
interpolations is
<literal>${<replaceable>expression</replaceable>}</literal> where
expression gives the value you want to insert into the output as
text. So <literal>${(5 + 8)/2}</literal> prints <quote>6.5</quote>
to the output (or possibly <quote>6,5</quote> if the language of
your output is not US English).</para>
</listitem>
<listitem>
<para>When you supply a value for the directive parameter: You
have already seen the <literal>if</literal> directive in the
Getting Started section. The syntax of this directive is:
<literal>&lt;#if
<replaceable>expression</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>.
The expression here must evaluate to a boolean value. For example
in <literal>&lt;#if 2 &lt; 3&gt;</literal> the <literal>2 &lt;
3</literal> (2 is less than 3) is an expression which evaluates to
<literal>true</literal>.</para>
</listitem>
</itemizedlist>
<section xml:id="exp_cheatsheet">
<title>Quick overview (cheat sheet)</title>
<para>This is a reminder for those of you who already know
FreeMarker or are just experienced programmers:</para>
<itemizedlist spacing="compact">
<listitem>
<para><link linkend="dgui_template_exp_direct">Specify values
directly</link></para>
<itemizedlist spacing="compact">
<listitem>
<para><link
linkend="dgui_template_exp_direct_string">Strings</link>:
<literal>"Foo"</literal> or <literal>'Foo'</literal> or
<literal>"It's \"quoted\""</literal> or <literal>'It\'s
"quoted"'</literal> or
<literal>r"C:\raw\string"</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_direct_number">Numbers</link>:
<literal>123.45</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_direct_boolean">Booleans</link>:
<literal>true</literal>, <literal>false</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_direct_seuqence">Sequences</link>:
<literal>["foo", "bar", 123.45]</literal>; Ranges:
<literal>0..9</literal>, <literal>0..&lt;10</literal> (or
<literal>0..!10</literal>), <literal>0..</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_direct_hash">Hashes</link>:
<literal>{"name":"green mouse",
"price":150}</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_var">Retrieving
variables</link></para>
<itemizedlist spacing="compact">
<listitem>
<para><link
linkend="dgui_template_exp_var_toplevel">Top-level
variables</link>: <literal>user</literal></para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_var_hash">Retrieving
data from a hash</link>: <literal>user.name</literal>,
<literal>user["name"]</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_var_sequence">Retrieving data
from a sequence</link>:
<literal>products[5]</literal></para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_var_special">Special
variable</link>: <literal>.main</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_stringop">String
operations</link></para>
<itemizedlist spacing="compact">
<listitem>
<para><link
linkend="dgui_template_exp_stringop_interpolation">Interpolation
and concatenation</link>:
<literal>"Hello ${user}!"</literal> (or <literal>"Hello
" + user + "!"</literal>)</para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_get_character">Getting a
character</link>: <literal>name[0]</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_stringop_slice">String
slice:</link> Inclusive end: <literal>name[0..4]</literal>,
Exclusive end: <literal>name[0..&lt;5]</literal>,
Length-based (lenient): <literal>name[0..*5]</literal>,
Remove starting: <literal>name[5..]</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_sequenceop">Sequence
operations</link></para>
<itemizedlist spacing="compact">
<listitem>
<para><link
linkend="dgui_template_exp_sequenceop_cat">Concatenation</link>:
<literal>users + ["guest"]</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_seqenceop_slice">Sequence
slice</link>: Inclusive end:
<literal>products[20..29]</literal>, Exclusive end:
<literal>products[20..&lt;30]</literal>, Length-based
(lenient): <literal>products[20..*10]</literal>, Remove
starting: <literal>products[20..]</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_hashop">Hash
operations</link></para>
<itemizedlist spacing="compact">
<listitem>
<para><link
linkend="dgui_template_exp_hashop_cat">Concatenation</link>:
<literal>passwords + { "joe": "secret42" }</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_arit">Arithmetical
calculations</link>: <literal>(x * 1.5 + 10) / 2 - y %
100</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_comparison">Comparison</link>:
<literal>x == y</literal>, <literal>x != y</literal>,
<literal>x &lt; y</literal>, <literal>x &gt; y</literal>,
<literal>x &gt;= y</literal>, <literal>x &lt;= y</literal>,
<literal>x lt y</literal>, <literal>x lte y</literal>,
<literal>x gt y</literal>, <literal>x gte y</literal>,
...etc.</para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_logicalop">Logical
operations</link>: <literal>!registered &amp;&amp; (firstVisit
|| fromEurope)</literal></para>
</listitem>
<listitem>
<para><link
linkend="dgui_template_exp_builtin">Built-ins</link>:
<literal>name?upper_case</literal>,
<literal>path?ensure_starts_with('/')</literal></para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_methodcall">Method
call</link>: <literal>repeat("What", 3)</literal></para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_missing">Missing value
handler operators</link>:</para>
<itemizedlist spacing="compact">
<listitem>
<para><link
linkend="dgui_template_exp_missing_default">Default
value</link>: <literal>name!"unknown"</literal> or
<literal>(user.name)!"unknown"</literal> or
<literal>name!</literal> or
<literal>(user.name)!</literal></para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_missing_test">Missing
value test</link>: <literal>name??</literal> or
<literal>(user.name)??</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_assignment">Assignment
operators</link>: <literal>=</literal>, <literal>+=</literal>,
<literal>-=</literal>, <literal>*=</literal>,
<literal>/=</literal>, <literal>%=</literal>,
<literal>++</literal>, <literal>--</literal></para>
</listitem>
<listitem>
<para><link linkend="dgui_template_exp_lambda">Local
lambdas</link>: <literal>x -&gt; x + 1</literal>, <literal>(x,
y) -&gt; x + y</literal></para>
</listitem>
</itemizedlist>
<para>See also: <link
linkend="dgui_template_exp_precedence">Operator
precedence</link></para>
</section>
<section xml:id="dgui_template_exp_direct">
<title>Specify values directly</title>
<indexterm>
<primary>literal</primary>
</indexterm>
<indexterm>
<primary>constant</primary>
</indexterm>
<para>Often you want to specify a value directly and not as a result
of some calculations.</para>
<section xml:id="dgui_template_exp_direct_string">
<title>Strings</title>
<indexterm>
<primary>string</primary>
<secondary>literal</secondary>
</indexterm>
<para>To specify a string value directly you give the text in
quotation marks, e.g.: <literal>"some text"</literal> or in
apostrophe-quote, e.g. <literal>'some text'</literal>. The two
forms are equivalent. If the text itself contains the character
used for the quoting (either <literal>"</literal> or
<literal>'</literal>) or backslashes, you have to precede them
with a backslash; this is called escaping. You can type any other
character, including <link linkend="gloss.lineBreak">line
breaks</link>, in the text directly. Example:</para>
<programlisting role="template">${"It's \"quoted\" and
this is a backslash: \\"}
${'It\'s "quoted" and
this is a backslash: \\'}</programlisting>
<para>will print:</para>
<programlisting role="output">It's "quoted" and
this is a backslash: \
It's "quoted" and
this is a backslash: \</programlisting>
<note>
<para>Of course, you could simply type the above text into the
template, without using
<literal>${<replaceable>...</replaceable>}</literal>. But we do
it here just for the sake of example, to demonstrate
expressions.</para>
</note>
<anchor xml:id="topic.escapeSequence"/>
<indexterm>
<primary>escape sequences</primary>
</indexterm>
<para>This is the list of all supported escape sequences. All
other usage of backlash in string literals is an error and any
attempt to use the template will fail.</para>
<informaltable border="1">
<thead>
<tr>
<th>Escape sequence</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>\"</literal></td>
<td>Quotation mark (u0022)</td>
</tr>
<tr>
<td><literal>\'</literal></td>
<td>Apostrophe (a.k.a. apostrophe-quote) (u0027)</td>
</tr>
<tr>
<td><literal>\{</literal></td>
<td>Opening curly brace: <literal>{</literal></td>
</tr>
<tr>
<td><literal>\=</literal></td>
<td>Equals character: <literal>=</literal> (Supported since
FreeMarker 2.3.28.)</td>
</tr>
<tr>
<td><literal>\\</literal></td>
<td>Back slash (u005C)</td>
</tr>
<tr>
<td><literal>\n</literal></td>
<td>Line feed (u000A)</td>
</tr>
<tr>
<td><literal>\r</literal></td>
<td>Carriage return (u000D)</td>
</tr>
<tr>
<td><literal>\t</literal></td>
<td>Horizontal tabulation (a.k.a. tab) (u0009)</td>
</tr>
<tr>
<td><literal>\b</literal></td>
<td>Backspace (u0008)</td>
</tr>
<tr>
<td><literal>\f</literal></td>
<td>Form feed (u000C)</td>
</tr>
<tr>
<td><literal>\l</literal></td>
<td>Less-than sign: <literal>&lt;</literal></td>
</tr>
<tr>
<td><literal>\g</literal></td>
<td>Greater-than sign: <literal>&gt;</literal></td>
</tr>
<tr>
<td><literal>\a</literal></td>
<td>Ampersand: <literal>&amp;</literal></td>
</tr>
<tr>
<td><literal>\x<replaceable>Code</replaceable></literal></td>
<td>Character given with its hexadecimal <link
linkend="gloss.unicode">Unicode</link> code (<link
linkend="gloss.UCS">UCS</link> code)</td>
</tr>
</tbody>
</informaltable>
<para>The <literal><replaceable>Code</replaceable></literal> after
the <literal>\x</literal> is 1 to 4 hexadecimal digits. For
example this all put a copyright sign into the string:
<literal>"\xA9 1999-2001"</literal>,
<literal>"\x0A9 1999-2001"</literal>,
<literal>"\x00A9 1999-2001"</literal>. When the character directly
after the last hexadecimal digit can be interpreted as hexadecimal
digit, you must use all 4 digits or else FreeMarker will
misunderstand you.</para>
<para>Note that the character sequence <literal>${</literal> and
<literal>#{</literal> (and rarely <literal>[=</literal> instead,
depending on <link linkend="dgui_misc_alternativesyntax">the
configured syntax</link>) has special meaning. They are used to
insert the value of expressions (typically: the value of
variables, as in <literal>"Hello ${user}!"</literal>). This will
be explained <link
linkend="dgui_template_exp_stringop_interpolation">later</link>.
If you want to print <literal>${</literal> or
<literal>#{</literal> (or <literal>[=</literal>), you should
either use raw string literals as explained below, or escape the
<literal>{</literal> like in <literal>"foo $\{bar}"</literal> (or
the <literal>=</literal> like in <literal>"foo
[\=bar]"</literal>).</para>
<indexterm>
<primary>raw string literal</primary>
</indexterm>
<para>A special kind of string literals is the raw string
literals. In raw string literals, backslash and
<literal>${</literal> have no special meaning, they are considered
as plain characters. To indicate that a string literal is a raw
string literal, you have to put an <literal>r</literal> directly
before the opening quotation mark or apostrophe-quote.
Example:</para>
<programlisting role="template">${r"${foo}"}
${r"C:\foo\bar"}</programlisting>
<para>will print:</para>
<programlisting role="output">${foo}
C:\foo\bar</programlisting>
</section>
<section xml:id="dgui_template_exp_direct_number">
<title>Numbers</title>
<indexterm>
<primary>number</primary>
<secondary>literal</secondary>
</indexterm>
<para>To specify a numerical value directly you type the number
without quotation marks. You have to use the dot as your decimal
separator and must not use any grouping separator symbols. You can
use <literal>-</literal> or <literal>+</literal> to indicate the
sign (<literal>+</literal> is redundant). Scientific notation is
not yet supported (so <literal>1E3</literal> is wrong). Also, you
cannot omit the 0 before the decimal separator (so
<literal>.5</literal> is wrong).</para>
<para>Examples of valid number literals: <literal>0.08</literal>,
<literal>-5.013</literal>, <literal>8</literal>,
<literal>008</literal>, <literal>11</literal>,
<literal>+11</literal></para>
<para>Note that numerical literals like <literal>08</literal>,
<literal>+8</literal>, <literal>8.00</literal> and
<literal>8</literal> are totally equivalent as they all symbolize
the number eight. Thus, <literal>${08}</literal>,
<literal>${+8}</literal>, <literal>${8.00}</literal> and
<literal>${8}</literal> will all print exactly same.</para>
</section>
<section xml:id="dgui_template_exp_direct_boolean">
<title>Booleans</title>
<indexterm>
<primary>boolean</primary>
<secondary>literal</secondary>
</indexterm>
<indexterm>
<primary>literal</primary>
<secondary>boolean</secondary>
</indexterm>
<para>To specify a boolean value you write <literal>true</literal>
or <literal>false</literal>. Don't use quotation marks.</para>
</section>
<section xml:id="dgui_template_exp_direct_seuqence">
<title>Sequences</title>
<indexterm>
<primary>sequence</primary>
<secondary>literal</secondary>
</indexterm>
<indexterm>
<primary>numerical sequence</primary>
</indexterm>
<indexterm>
<primary>numerical range expression</primary>
</indexterm>
<indexterm>
<primary>range expression</primary>
</indexterm>
<para>To specify a literal sequence, you list the <link
linkend="topic.dataModel.subVar">sub variables</link> separated by
commas, and put the whole list into square brackets. For
example:</para>
<programlisting role="template">&lt;#list <emphasis>["foo", "bar", "baz"]</emphasis> as x&gt;
${x}
&lt;/#list&gt;</programlisting>
<para>will print:</para>
<programlisting role="output">foo
bar
baz
</programlisting>
<para>The items in the list are expressions, so you can do this
for example: <literal>[2 + 2, [1, 2, 3, 4], "foo"]</literal>. Here
the first subvariable will be the number 4, the second will be
another sequence, and the third subvariable will be the string
<quote>foo</quote>.</para>
</section>
<section xml:id="dgui_template_exp_direct_ranges">
<title>Ranges</title>
<para>Ranges are just sequences, but they are created by
specifying what range of whole numbers they contain, instead of
specifying their items one by one. For example,
<literal>0..&lt;m</literal>, assuming the <literal>m</literal>
variable stores 5, will give a sequence that contains <literal>[0,
1, 2, 3, 4]</literal>. Ranges are primarily used for iterating
over a range of numbers with <literal>&lt;#list
<replaceable>...</replaceable>&gt;</literal> and for <link
linkend="dgui_template_exp_seqenceop_slice">slicing
sequences</link> and <link
linkend="dgui_template_exp_stringop_slice">slicing
strings</link>.</para>
<para>The generic forms of range expressions are (where
<literal><replaceable>start</replaceable></literal> and
<literal><replaceable>end</replaceable></literal> can be any
expression that evaluates to a number):</para>
<itemizedlist>
<listitem>
<para><literal><replaceable>start</replaceable>..<replaceable>end</replaceable></literal>:
Range with inclusive end. For example, <literal>1..4</literal>
gives <literal>[1, 2, 3, 4]</literal>, and
<literal>4..1</literal> gives <literal>[4, 3, 2, 1]</literal>.
Beware, ranges with inclusive end never give an empty
sequence, so <literal>0..length-1</literal> is
<emphasis>WRONG</emphasis>, because when length is
<literal>0</literal> it gives <literal>[0,
-1]</literal>.</para>
</listitem>
<listitem>
<para><literal><replaceable>start</replaceable>..&lt;<replaceable>end</replaceable></literal>
or
<literal><replaceable>start</replaceable>..!<replaceable>end</replaceable></literal>:
Range with exclusive end. For example,
<literal>1..&lt;4</literal> gives <literal>[1, 2,
3]</literal>, <literal>4..&lt;1</literal> gives <literal>[4,
3, 2]</literal>, and <literal>1..&lt;1</literal> gives
<literal>[]</literal>. Note the last example; the result can
be an empty sequence. There's no difference between
<literal>..&lt;</literal> and <literal>..!</literal>; the last
form is used in applications where using the
<literal>&lt;</literal> character causes problems (for HTML
editors and such).</para>
</listitem>
<listitem>
<para><literal><replaceable>start</replaceable>..*<replaceable>length</replaceable></literal>:
Length limited range. For example, <literal>10..*4</literal>
gives <literal>[10, 11, 12, 13]</literal>,
<literal>10..*-4</literal> gives <literal>[10, 9, 8,
7]</literal>, and <literal>10..*0</literal> gives
<literal>[]</literal>. When these kind of ranges are used for
slicing, the slice will end without error if the end of the
sliced sequence or string is reached before the specified
range length was reached; see <link
linkend="dgui_template_exp_seqenceop_slice">slicing
sequences</link> for more.</para>
<note>
<para>Length limited ranges were introduced in FreeMarker
2.3.21.</para>
</note>
</listitem>
<listitem>
<para><literal><replaceable>start</replaceable>..</literal>:
Right-unbounded range. This are like length limited ranges
with infinite length. For example <literal>1..</literal> gives
<literal>[1, 2, 3, 4, 5, 6, ... ]</literal>, up to infinity.
Be careful when processing (like listing) such ranges, as
processing all items of it it would take forever or until the
application runs out of memory and crashes. Just like with
length limited ranges, when these kind of ranges are used for
slicing, the slice will end when the end of the sliced
sequence or string is reached.</para>
<warning>
<para>Right-unbounded ranges before FreeMarker 2.3.21 were
only used for slicing, and behaved like an empty sequence
for other purposes. To activate the new behavior, it's not
enough to use FreeMarker 2.3.21, the programmer also have to
set the <literal>incompatible_improvements</literal>
configuration setting to at least 2.3.21.</para>
</warning>
</listitem>
</itemizedlist>
<para>Further notes on ranges:</para>
<itemizedlist>
<listitem>
<para>Range expressions themselves don't have square brackets,
for example, you write <literal>&lt;#assign myRange =
0..&lt;x</literal>, NOT <literal>&lt;#assign myRange =
[0..&lt;x]&gt;</literal>. The last would create a sequence
that contains an item that's a range. The square brackets are
part of the slicing syntax, like
<literal><replaceable>seq</replaceable>[<replaceable>myRange</replaceable>]</literal>.</para>
</listitem>
<listitem>
<para>You can write arithmetical expression on the sides of
the <literal>..</literal> without parenthesis, like <literal>n
+ 1 ..&lt; m / 2 - 1</literal>.</para>
</listitem>
<listitem>
<para><literal>..</literal>, <literal>..&lt;</literal>,
<literal>..!</literal> and <literal>..*</literal> are
operators, so you can't have space inside them. Like
<literal>n .. &lt;m</literal> is WRONG, but <literal>n ..&lt;
m</literal> is good.</para>
</listitem>
<listitem>
<para>The reported size of right-unbounded ranges is
2147483647 (or 0 if
<literal>incompatible_improvements</literal> is less than
2.3.21) due to a technical limitation (32 bits). However, when
listing them, their actual size is infinite.</para>
</listitem>
<listitem>
<para>Ranges don't really store the numbers they consist of,
thus for example <literal>0..1</literal> and
<literal>0..100000000</literal> is equally fast to create and
takes the same amount of memory.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="dgui_template_exp_direct_hash">
<title>Hashes</title>
<indexterm>
<primary>hash</primary>
<secondary>literal</secondary>
</indexterm>
<indexterm>
<primary>literal</primary>
<secondary>hash</secondary>
</indexterm>
<para>To specify a hash in a template, you list the key/value
pairs separated by commas, and put the list into curly brackets.
The key and value within a key/value pair are separated with a
colon. Here is an example: <literal>{ "name": "green mouse",
"price": 150 }</literal>. Note that both the names and the values
are expressions. The keys must be strings. The values can be if
any type.</para>
</section>
</section>
<section xml:id="dgui_template_exp_var">
<title>Retrieving variables</title>
<section xml:id="dgui_template_exp_var_toplevel">
<title>Top-level variables</title>
<indexterm>
<primary>subvariable</primary>
<secondary>accessing</secondary>
</indexterm>
<para>To access a top-level variable, you simply use the variable
name. For example, the expression <literal>user</literal> will
evaluate to the value of variable stored with name
<quote>user</quote> in the root. So this will print what you store
there:</para>
<programlisting role="template">${user}</programlisting>
<para>If there is no such top-level variable, then an error will
result when FreeMarker tries to evaluate the expression, and it
aborts template processing (unless programmers has configured
FreeMarker differently).</para>
<para>In this kind of expression, the variable name can only
contain letters (including non-Latin letters), digits (including
non-Latin digits), underline (<literal>_</literal>), dollar
(<literal>$</literal>), at sign (<literal>@</literal>).
Furthermore, the first character can't be an ASCII digit
(<literal>0</literal>-<literal>9</literal>). Starting from
FreeMarker 2.3.22, the variable name can also contain minus
(<literal>-</literal>), dot (<literal>.</literal>), and colon
(<literal>:</literal>) at any position, but these must be escaped
with a preceding backslash (<literal>\</literal>), otherwise they
are interpreted as operators. For example, to read the variable
whose name is <quote>data-id</quote>, the expression is
<literal>data\-id</literal>, as <literal>data-id</literal> would
be interpreted as <quote>data minus id</quote>. (Note that these
escapes only work in identifiers, not in string literals.)</para>
</section>
<section xml:id="dgui_template_exp_var_hash">
<title>Retrieving data from a hash</title>
<indexterm>
<primary>subvariable</primary>
<secondary>accessing</secondary>
</indexterm>
<indexterm>
<primary>hash</primary>
<secondary>accessing subvariable</secondary>
</indexterm>
<para>If we already have a hash as a result of an expression, then
we can get its subvariable with a dot and the name of the
subvariable. Assume that we have this data-model:</para>
<programlisting role="dataModel">(root)
|
+- book
| |
| +- title = "Breeding green mouses"
| |
| +- author
| |
| +- name = "Julia Smith"
| |
| +- info = "Biologist, 1923-1985, Canada"
|
+- test = "title"</programlisting>
<para>Now we can read the <literal>title</literal> with
<literal>book.title</literal>, since the book expression will
return a hash (as explained in the last chapter). Applying this
logic further, we can read the name of the author with this
expression: <literal>book.author.name</literal>.</para>
<para>There is an alternative syntax if we want to specify the
subvariable name with an expression:
<literal>book["title"]</literal>. In the square brackets you can
give any expression as long as it evaluates to a string. So with
this data-model you can also read the title with
<literal>book[test]</literal>. More examples; these are all
equivalent: <literal>book.author.name</literal>,
<literal>book["author"].name</literal>,
<literal>book.author["name"]</literal>,
<literal>book["author"]["name"]</literal>.</para>
<para>When you use the dot syntax, the same restrictions apply
regarding the variable name as with top-level variables (name can
contain only letters, digits, <literal>_</literal>,
<literal>$</literal>, <literal>@</literal> but can't start with
<literal>0</literal>-<literal>9</literal>, also starting from
2.3.22 you can also use <literal>\-</literal>,
<literal>\.</literal> and <literal>\:</literal>). There are no
such restrictions when you use the square bracket syntax, since
the name is the result of an arbitrary expression. (Note, that to
help the FreeMarker XML support, if the subvariable name is
<literal>*</literal> (asterisk) or <literal>**</literal>, then you
do not have to use square bracket syntax.)</para>
<para>As with the top-level variables, trying to access a
non-existent subvariable causes an error and aborts the processing
of the template (unless programmers has configured FreeMarker
differently).</para>
</section>
<section xml:id="dgui_template_exp_var_sequence">
<title>Retrieving data from a sequence</title>
<indexterm>
<primary>subvariable</primary>
<secondary>accessing</secondary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>accessing subvariable</secondary>
</indexterm>
<para>This is the same as for hashes, but you can use the square
bracket syntax only, and the expression in the brackets must
evaluate to a number, not a string. For example to get the name of
the first animal of the <link
linkend="example.stdDataModel">example data-model</link> (remember
that the number of the first item is 0, not 1):
<literal>animals[0].name</literal></para>
</section>
<section xml:id="dgui_template_exp_var_special">
<title>Special variables</title>
<indexterm>
<primary>special variables</primary>
</indexterm>
<para>Special variables are variables defined by the FreeMarker
engine itself. To access them, you use the
<literal>.<replaceable>variable_name</replaceable></literal>
syntax.</para>
<para>Normally you don't need to use special variables. They are
for expert users. The complete list of special variables can be
found in the <link linkend="ref_specvar">reference</link>.</para>
</section>
</section>
<section xml:id="dgui_template_exp_stringop">
<title>String operations</title>
<indexterm>
<primary>string</primary>
<secondary>operations</secondary>
</indexterm>
<section xml:id="dgui_template_exp_stringop_interpolation">
<title>Interpolation and concatenation</title>
<indexterm>
<primary>interpolation</primary>
</indexterm>
<indexterm>
<primary>concatenate strings</primary>
</indexterm>
<indexterm>
<primary>joining strings</primary>
</indexterm>
<indexterm>
<primary>string</primary>
<secondary>concatenate</secondary>
</indexterm>
<indexterm>
<primary>string</primary>
<secondary>interpolation</secondary>
</indexterm>
<indexterm>
<primary>adding strings</primary>
</indexterm>
<para>If you want to insert the value of an expression into a
string, you can use
<literal>${<replaceable>...</replaceable>}</literal> (and the
deprecated <literal>#{<replaceable>...</replaceable>}</literal>)
in string literals.
<literal>${<replaceable>...</replaceable>}</literal> in string
literals <link linkend="dgui_template_valueinsertion">behaves
similarly as in <phrase role="markedText">text</phrase>
sections</link> (so it goes through the same <emphasis>locale
sensitive</emphasis> number and date/time formatting).</para>
<note>
<para>It's possible to configure FreeMarker's interpolation
syntax to use
<literal>[=<replaceable>...</replaceable>]</literal> instead;
<link linkend="dgui_misc_alternativesyntax_interpolation">see
here</link>.</para>
</note>
<para>Example (assume that user is <quote>Big Joe</quote>):</para>
<programlisting role="template">&lt;#assign s = "Hello ${user}!"&gt;
${s} &lt;#-- Just to see what the value of s is --&gt;
</programlisting>
<para>This will print:</para>
<programlisting role="output">Hello Big Joe!</programlisting>
<warning>
<para>A frequent mistake of users is the usage of interpolations
in places where they needn't/shouldn't/can't be used.
Interpolations work <emphasis>only</emphasis> in <link
linkend="dgui_template_overallstructure"><phrase
role="markedText">text</phrase> sections</link> (e.g.
<literal>&lt;h1&gt;Hello ${name}!&lt;/h1&gt;</literal>) and in
string literals (e.g. <literal>&lt;#include
"/footer/${company}.html"&gt;</literal>). A typical
<emphasis>WRONG</emphasis> usage is <literal>&lt;#if
${big}&gt;...&lt;/#if&gt;</literal>, which will cause a
syntactical error. You should simply write <literal>&lt;#if
big&gt;...&lt;/#if&gt;</literal>. Also, <literal>&lt;#if
"${big}"&gt;...&lt;/#if&gt;</literal> is
<emphasis>WRONG</emphasis>, since it converts the parameter
value to string and the <literal>if</literal> directive wants a
boolean value, so it will cause a runtime error.</para>
</warning>
<para
xml:id="dgui_template_exp_stringop_concatenation">Alternatively,
you can use the <literal>+</literal> operator to achieve similar
result:</para>
<programlisting role="template">&lt;#assign s = "Hello " + user + "!"&gt;</programlisting>
<para>This gives the same result as the earlier example with the
<literal>${<replaceable>...</replaceable>}</literal>.</para>
<warning>
<para>Because <literal>+</literal> follows similar rules as
<literal>${<replaceable>...</replaceable>}</literal>, the
appended string is influenced by the <literal>locale</literal>,
<literal>number_format</literal>,
<literal>date_format</literal>, <literal>time_format</literal>,
<literal>datetime_format</literal> and
<literal>boolean_format</literal>, etc. settings, and thus the
result targets humans and isn't in generally machine parseable.
This mostly leads to problems with numbers, as many locales use
grouping (thousands separators) by default, and so
<literal>"someUrl?id=" + id</literal> becomes to something like
<literal>"someUrl?id=1 234"</literal>. To prevent this, use the
<literal>?c</literal> (for Computer audience) built-in, like in
<literal>"someUrl?id=" + id?c</literal> or
<literal>"someUrl?id=${id?c}"</literal>, which will evaluate to
something like <literal>"someUrl?id=1234"</literal>, regardless
of locale and format settings.</para>
</warning>
<para>As when <literal>${<replaceable>...</replaceable>}</literal>
is used inside string <emphasis>expressions</emphasis> it's just a
shorthand of using the <literal>+</literal> operator, <link
linkend="dgui_misc_autoescaping">auto-escaping</link> is not
applied on it.</para>
</section>
<section xml:id="dgui_template_exp_get_character">
<title>Getting a character</title>
<indexterm>
<primary>charAt</primary>
</indexterm>
<indexterm>
<primary>get character</primary>
</indexterm>
<para>You can get a single character of a string at a given index
similarly as you can <link
linkend="dgui_template_exp_var_sequence">read the subvariable of a
sequence</link>, e.g. <literal>user[0]</literal>. The result will
be a string whose length is 1; FTL doesn't have a separate
character type. As with sequence sub variables, the index must be
a number that is at least 0 and less than the length of the
string, or else an error will abort the template
processing.</para>