3.4 Escaping VTL elements

Most of the time, there is no problem, rendering a Velocity template because the rendering engine is quite smart about finding Velocity Statements and References and distinguishing them from regular text.

## Renders as normal text, because the dollar sign 
## is not followed by a letter.
I bought a 4 lb. sack of potatoes for only $2.50!

## Renders as variable
I bought a 4 lb. sack of potatoes for only $money.

Velocity allows for explicit escaping of References and Directives using the \ (backslash) character. If the character following the \ would start a new directive or reference, then this character is output verbatim. This can lead to some unexpected behaviour, especially with directives.

Example 3.4. VTL escaping examples

\         ## Renders as a single backslash (no # or $ follows)

\\ \# \$  ## Renders as \\ \# \$ (no directive or reference follows)

\#end     ## Renders as #end, backslash escapes an existing directive

Unfortunately, the escaping of VTL elements contains a number of quirks that make them actually hard to use[2]. As you have seen, the behaviour of the \ differs whether a directive or just text follows:

Example 3.5. Escaping VTL references

$a     ## $a is a reference but an unbound on (it has no value)
       ## This renders as $a in the output

\$a    ## Escaping an unbound reference renders it as \$a

#set($a = 10)  ## When a value is assigned to the reference...

$a     ## Now renders as 10

\$a    ## Now renders as $a

Escaping VTL statements works in the same way.

Example 3.6. Escaping VTL statements

\#end    ## Renders as #end
\# end   ## Renders as \# end (note the space)

\#set ($a = 10) ## Renders as #set ($a = 10)

## If $a has been assigned a value:

#set ($a = 10)
\#set ($a = 20) ## Renders as #set (10 = 20)

## The backslash does not escape a whole multiline statement
## This is a syntax error: (#end without a starting statement)
\#if ($a == 10)
#end

Using Velocity Macros, the behaviour of escaping # changes a bit:[3]

Example 3.7. Escaping Macros

#apple    ## Renders as #apple, because it is not a VTL
          ## statement
\#apple   ## Renders as \#apple

#macro(apple)
 Apple
#end

#apple    ## This is now an syntax error (#apple needs now
          ## brackets because it's a macro)

#apple()  ## Renders as Apple (VTL Macro)

\#apple   ## renders as #apple, because it is now a VTL
          ## statement after macro definition.



[2] It is really mind-boggling how we came up with this. It is tied more to the internal workings of the Velocity engine than any user-friendlyness. This is definitely subject to change in future Velocity versions. Until then, please be kind to our mistakes.

[3] ...and you probably thought, the worst part was over...