Template syntax
This guide will cover the essentials of the templating language.
It provides special instructions how to merge your data into the resulting output.
The same template syntax can be used in Google Docs, LibreOffice, MS Word and HTML documents or in plain text.
You can also use the template syntax in all Ultradox input fields that have a blue or green background. This allows you to populate form fields from your date and more.
When using the template language in documents the formatting capabilities that your word processor offers will be preserved.
The formatting capabilities of Ultradox allows you to merge text, images, maps, tables or lists into your documents using data from any data source.
We have open sourced the core template engine on github. If you are a Java developer feel free to use it in your own projects.
Variables
With variables you can merge data into the resulting document.
Variables may represent just a single word, a longer text, a date, a number, an image or even a list of values.
Let's say you want to create a personalized letter. Your static document may contain the greeting:
Hello Daniel!
Now you want to replace the name Daniel with a variable to be able to generate personalized letters for different contacts. Replacing the name with a variable is easy, just type
Hello ${name}!
Ultradox is very picky!
Variable names must not contain any special characters or spaces!
Keep your variable names simple and use lowercase or camelCase letters e.g. givenName
, phoneNumber
or email
The variable name may contain underscores (e.g. given_name
), but we'd recommend not to use them.
Mare sure to start the merge tag with ${
and end it with }
. Don't mix up the curly braces with square brackets or alike and do not add any spaces.
Default values
If you are creating personalized letters that you want to send out to a bunch of your contacts, you may have a number of contacts where you only know the email address but not the name.
You can specify a default value that will be printed if the variable is not available. Simply specify this default value in round brackets just after the variable name:
Hello ${name(customer)}!
If the name variable is not set, you will find this in your document:
Hello customer!
Playground
If you remove the name from the data, the default value will be displayed instead.
Hello ${name(customer)}!
{ "name" : "Daniel" }
Formatting
Ultradox comes with a number of renderers that will help you to format dates, numbers and strings and other data in the various ways.
To use a renderer simply enter the name of the renderer and optionally the renderer-specific format after the variable name:
${
variable;renderer(format)}
The syntax of the format
varies depending on the the renderer, but in most cases you just specify a number of options separated by a semicolon.
Let's see a few examples to see how this works:
Break text into multiple lines
If you want to wrap text into multiple lines, you can specify the wrap option in the text
renderer.
If the variable address
contains a text that looks like this:
1600 Amphitheatre Parkway,Mountain View,CA 94043
You can break the parts into different lines like using the wrap
option with ,
as delimiter:
${contact.address;string(wrap=,)}
This will break the address into multiple lines:
1600 Amphitheatre Parkway
Mountain View
CA 94043
Playground
Adjust the address and the delimiter to change the resulting output.
Hey ${name}, We will send your order to: ${address;string(wrap=,)}
{ "name" : "Larry", "address" : "1600 Amphitheatre Parkway,Mountain View,CA 94043" }
Dealing with long text
If your variable may contain very long text you can limit the length of the text using the max
parameter.
Let's say you have a variable called description containing long text like this:
This may become a very long text, a very very long text, it contains the description of an item
You can cut off the text after 20 characters by using the max
parameter:
${description;string(max=20)}
This will print:
This may become a ve
To indicate that text has been cut off you can specify the ellipsis
option:
${description;string(max=20;ellipsis=...)}
The specified characters get appended after the shortened text, so now you will get:
This may become a ve...
Convert text to upper- or lowercase
Use the string
renderer if you want to print out variables in uppercase or lowercase letters only:
${name;string(uppercase)} - ${name;string(lowercase)}
If the name is Daniel
this will print
DANIEL - daniel
Combining options
Of course you can combine all of the explained options.
Let's recap the long text example to see how this works. The variable description contains this longer text:
This may become a very long text, a very very long text, it contains the description of an item
You can now combine the different options like this:
$
{description;string(uppercase;wrap=, ;max=50;ellipsis=...)}
This will print out the description variable like this:
THIS MAY BECOME A VERY LONG TEXT
A VERY VERY LONG...
Note that in our example a new line will only be created whenever a comma is followed by a space
Check out the renderer reference for a full description of the formatting capabilities of the string
renderer.
Playground
Adjust the parameters of the string
renderers to see how it affects the result.
Hey ${name}, We will send your order to: ${address;string(wrap=,)} ${description;string(uppercase;wrap=, ;max=50;ellipsis=...)}
{ "name" : "Larry", "address" : "1600 Amphitheatre Parkway,Mountain View,CA 94043", "description" : "This may become a very long text, a very very long text, it contains the description of an item" }
Dynamic parameters
Let's say you are generating an HTML email or website and want to render a URL as a link. You can use the link
renderer for that and use the text option to specify the clickable text that should be displayed in the generated document:
${myurl;link(text=Click me)}
If the text that you want to display should be taken from a variable instead of typing it right into the template, you can use dynamic parameters in the renderer options:
${myurl;link(text=$mytext)}
In this example the text that will be displayed in your document will be taken from the variable mytext
and the target link will still be taken from the myurl
variable.
Playground
Change the myurl
and mytext
variables in the Data
tab to modify the output of the link
renderer.
<h1>Visit us at</h1> <h2>${myurl;link(text=$mytext;target=_blank)}</h2>
{ "myurl" : "https://cloud.withgoogle.com/next18/sf/", "mytext" : "Google Next" }
Conditions
Conditions are a powerful feature to create sophisticated documents. You can for example assemble documents by including paragraphs depending on conditions.
The easiest condition is to check if a variable is set and has a value that is not false
.
Let us add some text to our document only if the contact is male:
${if male}Guess what? You are male!${end}
The text between the ${
if ...}
and the ${
end}
tag will only be printed if the male variable is present and is not false
.
If you want to add some text if the condition is not met, you can use the ${
else}
tag:
Dear ${if male}Mr.${else}Mrs.${end} ${familyName}
It may look a little bit complicated, but if you have a closer look you should get what it means:
If the contact is male, it will generate Dear Mr.
Smith
if the contact is not male, it will generate Dear Mrs. Smith
instead.
You can check if a variable is set, no matter if it is a simple variable holding just a single value or if is a list variable. If you for example want to print a text or table only if a loaded sheet contains any rows, just use the same syntax:
${if sheet1}The worksheet sheet1 contains at least one row${end}
Ultradox allows you to compare your variables to a fixed value.
Let's say you have a variable called country
and you want to print different text snippets based on the value of the country variable, you can use an if
statement like this one:
${if country="DE"}You are from Germany${end}
${if country="US"}You are from the United States${end}
${if !country[a]="DE"}You are not from Germany${end}
Use the not operator !
to print a snippet if the variable does not match your string
Playground
${if country="DE"}You are from Germany${end} ${if country="US"}You are from the United States${end} ${if !country="DE"}You are not from Germany${end}
{ "country" : "DE" }
Conditions and formatting
You can use all formatting capabilities to create advanced conditions.
Let's say you have a variable called email
with the value [email protected]
and you just want to compare the domain name you can leverage the string renderer to do so:
${
if email;string(fromAfterFirst
=@)="gmail.com"}You are using GMail
${
end}
In this example the string renderer will give you the the part of the email after the @
character.
Please be very careful with the syntax when combining conditions and formatting.
When formatting your variables you will find a number of options that will return either true
or false
. This makes them work in if
-statements.
If you for example want to check if the variable age
contains a number greater than 21
you can use this statement:
${if age;number(gt=21)}You are of legal age${end}
If you have a variable name
with value Oliver Angermann
and want to check if the last name starts with an A
, you could combine the formatting options like this:
${if name;string(fromAfterLast= ;startsWith=A)}Last word starts with character A${end}
If you have a variable releaseDate
with value 2018/04/03
and want to check if it is in the next year you can combine the output pattern yyyy
to only compare the year part with the addYear
and equals
options:
${if appointment;date(op=YYYY;addYear=-1;equals=$now)}Release is next year!${end}
Nested conditions
By nesting conditions you can emulate AND
and OR
operators.
Let try to solve this problem: You are running your business in the EU and want to create an invoice for a European customer, so you have to add VAT only if the customer is a private customer.
You can use reverse charge if the customer is a company identified by a valid VAT number.
Let's assume you have integrated Ultradox into your own shopping site and have provided the variables vatId
and euCustomer
:
${if euCustomer} You are a European customer. ${if vatId} Verified VAT ID is ${vatId}, you are liable for the tax (“Reverse charge”). ${else} % VAT for private customers included. ${end} ${else} You are from outside the EU. ${end}
{ "euCustomer" : true, "vatId" : "DE1234567890", "vatRate" : 21 }
Lists
Variables may contain a list of named values.
If you for example are loading a Google Sheet you will find a variables containing the values for each column.
Simple variables and list variables can be distinguished either by the tiny icon after the variable name: A single line indicates that this is a simple variable with just a single value, three lines indicate that this variable represents a list of values.
You can also identify list variables by a pair of brackets after the variable name, e.g. you will find variables like contacts[].givenName
and contacts[].photo
when loading multiple contacts.
If you want to print the title of the first contact, you can write ${contacts[0].title}
, to print the title of the third contacts, use a statement like this: ${contacts[2].title}
To access the last contact in the list, you can write ${contacts[last].title}
. This feature may come in handy if you for example want to access the last row of a worksheet.
${contacts.length}
will print the number of contacts loaded.
Number of contacts: ${contacts.length} Name of first contact: ${contacts[0].name} Name of second contact: ${contacts[1].name} Name of last contact: ${contacts[last].name}
{ "contacts" : [ { "name" : "Daniel" }, { "name" : "Olli" }, { "name" : "Esther" }, { "name" : "Alex" } ] }
Loops
Ultradox also allows you to iterate over the values by using the foreach
keyword.
Let's assume we have a list of contacts with the fields name
and email
.
The first argument in the foreach
statement is the variable that contains the list, in our example it is the variable contacts
holding the list of contacts.
The second argument in the foreach statement is the iterator which will help us to access the fields of each contact in the loop.
In the example we will pick contact
as name for the iterator, but you can pick an arbitrary name instead - just make sure that you are using this name when accessing the fields.
<ul> ${foreach contacts contact} <li>${contact.name} - ${contact.email}</li> ${end} </ul>
{ "contacts" : [ { "name" : "Daniel", "email" : "[email protected]" }, { "name" : "Olli", "email" : "[email protected]" }, { "name" : "Esther", "email" : "[email protected]" }, { "name" : "Alex", "email" : "[email protected]" } ] }
You can use conditions in loops and you can even nest loops you are dealing with a list of lists.
What if we want to print out all email addresses in a single line, separated with a comma? If we use an approach like this:
${foreach contacts contact}${contact.name}, ${end}
we end up with this result:
Daniel, Olli, Esther, Alex,
This looks good, except that we also have a comma at the end of the list.
How can we avoid this?
Loops with separators
Ultradox provides a special feature that allows you to create loops with a separator like this:
${foreach contacts contact , }${contact.name}${end}
So you can enter a delimiter in the foreach construct. You can use a single or multiple characters as a delimiter.
In our case we use a comma followed by a blank. The result looks like this:
Daniel, Olli, Esther, Alex
This is exactly what we needed!
Wrap values
You specify characters that will be prepended or appended when rendering a variable:
${<h1>,title,</h1>}
If the variable title
would contain Hello World
this would generate:
<h1>Hello World</h1>
This is great if you are generating HTML documents, but may be useful in other cases as well.
Let's say you want to print
Hi!
for users with no given name set, but
Hi Daniel!
for users with a given name available.
If you simply use the statement Hi ${if name}!
and your name is empty, you will end up with Hi !
which contains an unwanted space character. If you remove the space, you'd get HiDaniel!
if the name is set - which is even worse.
You could solve the problem by using a condition:
Hi${if name} ${name}${else}${end}!
This expression would check if the name is set and only add a space if the name is present.
This is quite a long statement just to get rid of the space character and can be simplified by just using the following shortcut:
Hi${ ,name,}!
Putting it all together
If you are familiar with templating languages and cannot wait to see some code, here we go with a fully featured HTML template and some data that you may have retrieved using a webhook
<!-- Wrap name in bold tags and provide default value --> <p>Hello ${,name(dear customer),}!</p> <!-- Format the current date in short form --> <p>We have received your order at ${date;datetime(op=short)}.</p> <!-- Print all authors separated by comma --> <p>You have ordered books from ${foreach authors author , }${author.name}${end}.</p> <!-- Print section for each author... --> ${foreach authors author} <p><b>${author.name}</b></p> <table> <tr><th width="200" style="text-align:left">Title</th><th>Published</th></tr> <!-- ... and display all books by this author --> ${foreach author.books book} <tr><td width="200">${book.title}</td><td style="text-align:left">${book.published}</td></tr> ${end} </table> ${end}
{ "name" : "Daniel", "date" : "2018-02-25T13:15", "authors" : [ { "name" : "Arnon Grunberg", "books" : [ { "title" : "Mit Haut und Haaren", "published" : "2012" }, { "title" : "Tirza", "published" : "2006" } ] }, { "name" : "Fjodor Michailowitsch Dostojewski", "books" : [ { "title" : "Schuld und Sühne", "published" : "1864" }, { "title" : "Die Brüder Karamasow", "published" : "1877" } ] } ] }
Learn more
The following guides will cover the aspects of the templating language.
[a]Just spent 2 hours of my time because putting something in "quotations" does not give any output. The correct example should be:
Questions and Feedback
If you have any comments on this page, feel free to add suggestions right to the Google document that we are using to create this site.
If you are not yet member of the Ultradox community on Google+, please join now to get updates from our end or to provide feedback, bug reports or discuss with other users.
Last Updated: 1/22/23