0

Context:

Inside a XWiki site, I heavily use velocity templates to have specific representation of objects. In a particular template, I need to be able to have one indirection level to allow special processing for some fields. I managed to put the formula in a variable and evaluate it at render time.

My current (simplified) code is:

#set($special = { 'field1': 'F1: $pageDoc.display("field1") - F2: $pageDoc.display("field2")',
                  'field2': '' }
...
#foreach($field in $fields):
  #if($special.contains($field))
    #if("$special[$field]" != "")
      <p>#evaluate($special[$field])</p>
    #end
  #else
    <p>$pageDoc.display($field)</p>
  #end
#end

In fact this example code displays a list of fields one at a line, while some of them (special fields) are displayed 2 in a row ($pageDoc.display($field) is a XWiki idiom to display a get the displayable value from an object contained in page)

Problem:

For a different rendering engine, I now need to pass the lines to the engine:

$engine.addLine($pageDoc.display($field))

But $engine.addLine(#evaluate($special[$field])) cannot work, because #evaluate directly outputs its evaluation and does not return anything.

Question

Is there a way in velocity to store the result of #evaluate in a variable?

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252

1 Answers1

1

In velocity, #evaluate only executes its content. All side effects, mainly outputs are observed, but nothing can be returned.

The (first part of) the trick is to have #evaluate to evaluate a #set, like (beware this one is incorrect):

#evaluate(#set($resul = $special[$field]))
$engine.addLine($resul)

The problem if that special characters are to be escaped in the evaluated strings, because the first part shall not be evaluate, while the second shall, and that velocity has rather weird escape rules: # and $ shall be escaped with \, while ' and " shall be doubled...

With that second part, it just gives:

#evaluate("\#set(\$resul= ""$special[$field]"")")
$engine.addLine($resul)
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252