Search code examples
freemarker

Assigning empty string if XML node doesn't exist in Freemarker


I have an XML document passed as root to a Freemarker template. I want some values from this XML to be assigned to variables as a string and later concatenate/print them out.

<#assign MyVar = root.child1.child2.child3.mynode>

The issue here is that even when a path doesn't exist MyVar gets assigned with a sequence+hash which cannot be printed out or converted to string. This variable although returns false for ?has_content, it needs an extra step for these checks and I have this same issue with many variables and across template files and modules.

The only solution I have been able to find was

<#assign MyVar = root.child1.child2.child3.mynode>
<#assign MyVar = MyVar ?has_content?then(MyVar , "")>

I am looking for something like the Default Value Operator which also checks for nulls like ?has_content.

Does Freemarker provide any simpler one line function to check if a variable has no content and assign it with a default?


Solution

  • In short:

    <#assign myVar = root.child1.child2.child3.mynode[0]!''>
    

    Or just <#assign myVar = root.child1.child2.child3.mynode[0]!> if the implicit multi-typed default value doesn't cause problems (like when you just print it with ${}).

    Why: XML queries (just like XPath queries) always return a sequence of matching nodes. There are maybe 0 such nodes (or 1, or multiple). An empty sequence is not a "missing value" according the template language. It's an inconvenient mismatch with the XML data-model. But while the sequence always exists, its 1st element ([0]) doesn't, so you can use all the missing value handler operators with it as usual.