---
category: [Administration & Integrations, Platform and Product Extensions, Platform and Product Extensions/Integration, Administration & Integrations/Custom Integrations & Apps, Platform and Product Extensions/Workday Extend]
keyword: [Extend, Orchestration Builder, Orchestrate, Orchestration]
nav: wcp_docs
parent_url: /wcp_docs/
title: >- 
  Concept: Text Templates
layout: subsection
---

Orchestration Builder's <b>Create Text Template</b> component enables you to create text documents that take advantage of powerful templating functionality. You can create these types of documents:

-   application/json
-   application/octet-stream
-   application/x-www-form-urlencoded
-   application/xml
-   text/csv
-   text/html
-   text/plain
-   text/xml


You insert templating expressions in your text document between curly braces. Example: suppose that your orchestration has an upstream <b>Create Values</b> step named `assign` that creates a StringType value `name` with the value "John". You can embed it in a text document using the `data()` function, like so:

```
Hello {{data.assign.name}}
```

The expression's output is:

```
Hello John
```

<b>Note:</b> If you need to include "{{" as text, you must escape it using a backslash, like so: `\{{`.

The template runtime is fully streaming, so you can embed multiple large documents into a template without impacting efficiency.

The <b>Create Text Template</b> component enables these templating features:

-   Conditional inclusion
-   Looping
-   Aliasing
-   With statement shorthand
-   Data statement shorthand
-   User-defined functions
-   Template naming
-   Commenting


<b>Conditional Inclusion</b>

You can add text and expressions on a conditional basis using the `if` statement.

Begin the expression with `{{#if` <i>boolean expression</i> `}}` and end it with `{{/if}}`.

Example: consider this expression:

```
Greetings{{#if data.assign.customer}} valued customer{{/if}}, {{data.assign.message}}
```

When `data.assign.customer` == `true`, the output is:

```
Greetings valued customer, please find attached our latest catalog.
```

When `data.assign.customer` == `false`, the output is:

```
Greetings, please find attached our latest catalog.
```

<b>Looping</b>

You can include collections of data using the `each` statement. The collection must be an expression that yields an iterator.

<b>Note:</b> XML iterators return elements, not strings.

Begin the expression with `{{#each` <i>iterator expression</i> `}}` and end it with `{{/each}}`. You can reference the loop items using the `this` keyword. Alternatively, you can name the loop items using the `as` keyword and this syntax:

```
{{#each some_iterator_expression as loop_variable}}
{{item.loop_variable}}
{{/each}}
```

Example: suppose that your orchestration has an upstream step named `assign`, which produces this JSON output, named `response`:

```
{
"workers": [
{
 "name": "John",
 "age": 38
},
{
 "name": "Susan",
 "age": 47
},
{
 "name": "Claudio",
 "age": 24
}
]
}
```

Consider this expression, which uses the `this` keyword:

```
{{#each data.assign.response.iterator("$.workers[*]")}}
Worker: {{this.stringAtJsonPath("$.name")}}
{{/each}}
```

This expression names the iterator items using the `as` keyword:

```
{{#each data.assign.response.iterator("$.workers[*] as worker")}}
Worker: {{item.worker.stringAtJsonPath("$.name")}}
{{/each}}
```

In both cases, the output is:

```
Worker: John
Worker: Susan
Worker: Claudio
```

You can iterate over nested loop blocks to produce more complex documents. Example: suppose that your orchestration has an upstream step named `assign`, which produces this JSON output, named `response`:

```
{
"PayGroup": [
{
 "Employee": {
   "Employee_ID": "1234"
 }
},
{
 "Employee": {
   "Employee_ID": "6789"
 }
}
]
}
```

This expression contains nested loops that fetch the `Employee_ID` from the JSON output:

```
{{#each data.assign.response.iterator("$.PayGroup[*] as payGroup")}}
{{#each item.payGroup.iterator("$.Employee as employee")}}
{{item.employee.stringAtJsonPath("$.Employee_ID")}}
{{/each}}
{{/each}}
```

The output is:

```
1234
6789
```

<b>Aliasing</b>

Rather than type a long expression in full every time you want to use it, you can assign it an alias and use that instead. The expression is only evaluated once, no matter how many times the alias is used.

Begin the expression with `{{#alias` <i>name</i> `}}` and end it with `{{/alias}}`. Add the expression that you want to alias as the body.

Refer to the alias using `"alias.name"`. You can apply any instance function that's valid for the aliased expression.

Example: in this expression, the `data` statement is given the alias `json`:

```
{{#alias json}} {{data.assign.response}} {{/alias}}
<comment> {{alias.json.stringAtJsonPath("$.workers[2].name")}} is here. </comment>
```

The output is:

```
<comment> Claudio is here. </comment>
```

<b>With Statement Shorthand</b>

You can use the `with` statement to refer multiple times to the same expression or alias.

Begin the with expression with `{{#with` <i>expression or alias</i> `}}` and end it with `{{/with}}`. Reference the `with` value using the `this` keyword. The `this` keyword always refers to the nearest in-scope `with` value or `each` item.

Example: suppose that your orchestration has an upstream step named `assign`, which produces JSON output named `response`, as described in the <b>Looping</b> section above.

Another upstream step produces this output, which has the alias `details`:

```
{
"address": "Manhattan, New York",
"phone": "0838459756"
}
```

These expressions use the `with` statement to join the `response` output with the `details` output:

```
{{#with data.assign.response}}
<name> {{this.stringAtJsonPath("$.name")}} </name>
<age> {{this.numberAtJsonPath("$.age")}} </age>
{{#with alias.details}}
<address> {{this.stringAtJsonPath("$.address")}} </address>
<phone> {{this.stringAtJsonPath("$.phone")}} </phone>
{{/with}}
{{/with}}
```

The output is:

```
<name> John </name>
<age> 38 </age>

<address> Manhattan, New York </address>
<phone> 0838459756 </phone>

<name> Susan </name>
<age> 47 </age>

<address> Manhattan, New York </address>
<phone> 0838459756 </phone>

<name> Claudio </name>
<age> 24 </age>

<address> Manhattan, New York </address>
<phone> 0838459756 </phone>
```

<b>Data Statement Shorthand</b>

You can shorten a statement in the format `data("inputId", "outputName")` to the less verbose ``data.inputId.outputName`.`

Example: these expressions are identical:

```
<name> {{data.assign.response.stringAtJsonPath("$.workers[0].name")}} </name>

<name> {{data("assign", "response").stringAtJsonPath("$.workers[0].name")}} </name>
```

<b>User-defined Functions</b>

You can define your own functions and invoke them from expressions. Your functions can take zero to many arguments. You must declare functions above the expressions that use them.

Begin your function construct with `{{#function` <i>name(argument: Type, ...)</i> `}}` and end it with `{{/function}}`. The body of the construct is `{{` <i>expression</i> `}}`. You can only include 1 expression in the body. Like expressions, user-defined functions return a value. They don't write anything into the template.

To declare a function with zero arguments use empty parentheses.

To invoke a function, use the syntax `function.functionName(arguments)`.

To invoke a function with zero arguments, use the syntax `function.functionName()`.

Example: 2 functions are defined and invoked here:

```
{{#function myIterator(key: String) }}
{{data.assign.response.iterator(key)}}
{{/function}}

{{#function isThirty(age: Number) }}
{{age > 30}}
{{/function}}

{{#each function.myIterator("$.workers[*]")}}
{{#if function.isThirty(this.numberAtJsonPath("$.age"))}}{{this.stringAtJsonPath("$.name")}} is more than 30 years old.{{/if}}
{{/each}}
```

The output is:

```
John is more than 30 years old.
Susan is more than 30 years old.
```

<b>Template Naming</b>

You can define named templates inside a template and invoke them just like user-defined functions. The difference is that named templates write their output into the template.

Named templates can use all the same features as other templates, including defining and calling other named templates. Named templates can read the contents of their parent template, but can't see inside sibling named templates or child named templates. They can invoke sibling named templates.

You can't invoke a named template from a user-defined function or specify one as an expression of an alias definition. Use the `data` function to provide named template parameter values, where the inputId is the name of the named template.

Begin the named template construct with `{{#template` <i>name(argument: Type, ...)</i> `}}` and end it with `{{/template}}`.

To invoke a named template, use the syntax `template.templateName(arguments)`.

Example:

```
{{#template myNamedTemplate(str: String, max: Number) }}
<welcome> {{data.myNamedTemplate.str}} </welcome>
<stuff> {{data.myNamedTemplate.max}} </stuff>
<more> Time now for {{data.more.stuff}} </more>
{{/template}}

<funstuff> {{template.myNamedTemplate("hello", 3)}}</funstuff>
```

```
<funstuff>
<welcome> Hello. </welcome>
<stuff> 3 </stuff>
<more> Time now for goodbye. </more>
</funstuff>
```

<b>Commenting</b>

To include comments in templates, use the syntax `{{! my comment }}` or `{{!-- my comment --}}`.

Example:

```
{{! This is an example of a user defined function }}
{{#function myStringFunction(str: String, max: Number) }}
{{str.upperCase().lowerCase().abbreviate(max).capitalize()}}
{{/function}}
```

<b>Line Continuation</b>

As you work with the <b>Create Text Template</b> component, you might find that long lines of text become difficult to follow. To improve readability, enter a backslash character (`\`) as the final character in a line and continue the text on the next line. When it encounters a backslash at the end of a line, Orchestration Builder ignores both the backslash and the subsequent line break.

Example:

```
line1,
line2, \
line3
```

This text would be output as follows:

```
line1, line2, line3
```

You can also use continuation characters to add whitespace formatting that Orchestration Builder ignores in the output. When you end a line with 2 backslash characters (`\\`), Orchestration Builder ignores the backslashes, the subsequent line break, and any leading whitespace in the next line.

Example:

```
{\\
"name": "Bob", \\
"age": 42\\
}
```

This text would be output as follows:

```
{"name": "Bob", "age": 42}
```

If you need to use a backslash not for continuation purposes but as the actual last character in a line, use `{{"\\"}}`.

<b>Supported Operators</b>

The <b>Create Text Template</b> component supports these arithmetic, comparison, logical, and unary operators:

<table><thead><tr><th>Type</th><th>Operators</th></tr></thead><tbody><tr><td>Arithmetic</td><td><ul><li>+: add
</li><li>-: subtract
</li><li>*: multiply
</li><li>/: divide
</li><li>%: modulo
</li></ul></td></tr><tr><td>Comparison</td><td><ul><li>==: equal to
</li><li>!=: not equal to
</li><li>>=: more than or equal to
</li><li>>: more than
</li><li><=: less than or equal to
</li><li><: less than
</li></ul></td></tr><tr><td>Logical</td><td><ul><li>&&: logical AND
</li><li>||: logical OR
</li></ul></td></tr><tr><td>Unary</td><td><ul><li>!: unary NOT
</li><li>+: unary plus
</li><li>-: unary minus
</li></ul></td></tr></tbody></table><br/>

<b>Supported Argument Types</b>

Named templates and user-defined functions support these types as arguments:

-   Any
-   PalaPrimitive
-   Boolean
-   Number
-   String
-   Date Local
-   DateTime
-   ZonedDateTime
-   LocalTime
-   ListOfPrimitive
-   StringList
-   NumberList
-   BooleanList
-   DateList
-   LocalDateTimeList
-   ZonedDateTimeList
-   LocalTimeList
-   Iterator
-   DataIterator
-   XmlIterator
-   JsonIterator
-   CsvRowIterator
-   TextIterator
-   StringIterator
-   NumberIterator
-   BooleanIterator
-   DateIterator
-   LocalDateTimeIterator
-   ZonedDateTimeIterator
-   LocalTimeIterator
-   MapOfPrimitive
-   StringMap
-   NumberMap
-   BooleanMap
-   DateMap
-   LocalDateTimeMap
-   ZonedDateTimeMap
-   LocalTimeMap
-   OAuthToken Data
-   Text Headers
-   QueryParams
-   HttpPartInfo
-   HttpParts
-   Json
-   Xml
-   Csv
-   CsvRow
-   MatchedWith
-   JoinResiduals
-   MatchedWithIterator


