VTL uses special characters, such as $
and #
, to do its
work, so some added care should be taken where using these characters in your templates. This section deals with escaping these characters.
Currency
There is no problem writing "I bought a 4 lb. sack of potatoes at the farmer's market for only $2.50!" As mentioned, a VTL identifier always begins with an upper- or lower-case letter, so $2.50 would not be mistaken for a reference.
Escaping Valid VTL
Cases may arise where you do not want to have a reference rendered by Velocity. Escaping
special characters is the best way to output VTL's
special characters in these situations, and this can be done using the backslash
(\
) character when those special characters are part
of a valid VTL reference
.
#set( $email = "foo" )
$email
If Velocity encounters a reference in your VTL template to $email
,
it will search the Context for a corresponding value. Here the output will be
foo
, because $email
is defined. If
$email
is not defined, the output will be
$email
.
Suppose that $email
is defined (for example, if it has the value
foo
), and that you want to output $email
. There are a few ways of doing this, but the simplest is to use the escape character. Here is a demonstration:
## The following line defines $email in this template:
#set( $email = "foo" )
$email
\$email
This renders as:
foo
$email
If, for some reason, you need a backslash before either line above, you can do the following:
## The following line defines $email in this template:
#set( $email = "foo" )
\\$email
\\\$email
This renders as:
\foo
\$email
\
character bind to the $
from the left. The
bind-from-left rule causes \\\$email
to render as
\$email
. Compare these examples to those in which
$email
is not defined. $email
\$email
\\$email
\\\$email
renders as
$email
\$email
\\$email
\\\$email
$foo
the value
gibbous
. #set( $foo = "gibbous" )
$moon = $foo
The output will be: $moon = gibbous
-- where $moon
is output as a literal because it is undefined and gibbous
is
output in place of $foo
.
Escaping Invalid VTL
Sometimes Velocity has trouble parsing your template when it encounters an "invalid
reference" that you never intended to be a reference at all. Escaping
special characters is, again, the best way to handle
these situations. In these situations, the backslash will likely fail you. Instead
of simply trying to escape the problematic $ or #, you should probably just replace
this:
${my:invalid:non:reference}
with something like this:
#set( $D = '$' )
${D}{my:invalid:non:reference}
You can, of course, put your $ or # string directly into the context from your java code (for
example, context.put
("D
","$
");)
to avoid the extra #set() directive in your templates. Or, if you are using
VelocityTools , you can just use the EscapeTool like this:
${esc.d}{my:invalid:non:reference}
Escaping of both valid and invalid VTL directives is handled in much the same manner; this is described in more detail in the Directives section.
Escaping VTL Directives
VTL directives can be escaped with the backslash character ("\") in a manner similar to valid VTL references.
## #include( "a.txt" ) renders as <contents of a.txt>
#include( "a.txt" )
## \#include( "a.txt" ) renders as #include( "a.txt" )
\#include( "a.txt" )
## \\#include ( "a.txt" ) renders as \<contents of a.txt>
\\#include ( "a.txt" )
Extra care should be taken when escaping VTL directives that contain multiple script elements in a single directive (such as in an if-else-end statements). Here is a typical VTL if-statement:
#if( $jazz )
Vyacheslav Ganelin
#end
If $jazz
is true, the output is:
Vyacheslav Ganelin
If $jazz
is false, there is no output. Escaping script elements
alters the output. Consider the following case:
\#if( $jazz )
Vyacheslav Ganelin
\#end
This causes the directives to be escaped, but the rendering of $jazz
proceeds as normal. So, if $jazz
is true, the output is:
#if( true )
Vyacheslav Ganelin
#end
Suppose backslashes precede script elements that are legitimately escaped:
\\#if( $jazz )
Vyacheslav Ganelin
//#end
Error! Hyperlink reference not valid.
In this case, if $jazz
is true, the output is:
\ Vyacheslav Ganelin
\
To understand this, note that the #if( arg )
, when ended by a
newline (return), will omit the newline from the output. Therefore, the body of the
#if()
block follows the first "\", rendered from the "\\"
preceding the #if()
. The last \ is on a different line than the
text because there is a newline after "Ganelin", so the final \\, preceding the
#end
is part of the body of the block.
If $jazz
is false, the output is:
\
\\\#if( $jazz )
Vyacheslave Ganelin
\\#end
Here the #if
is escaped, but there is an #end
remaining; having too many endings will cause a parsing error.