Text generators – XML/JSON output

Text generators – XML/JSON output

Compose Enterprise is going through a design update. The illustrations on this page might be of the old design, but the information is up to date. Thank you for your patience during this update!

Norsk

This user guide displays several examples of how you script and process workflow information into text generators. These text generators can be used for any text generating activity, but this guide will purposely demonstrate text generator scripting for XML output files (the same principles hold for JSON and other formats). You will find an overview of the most frequently used methods/operators in Compose scripting in this user “encyclopedia” Properties of Objects available in script contexts.

The first step in using a text generator is to define the input variables. These input variables denote external information we aim to generate into the text file.

Navigate to the Script-section of the Text Generator Builder. You’ll see a free text script window. Here, we can refer to input variables and implement logic for additional processing and formatting.

To reference input variables, we use ${} syntax, and refer to the input variable inside the brackets. The actual value of the input variable will replace the ${} syntax when the file gets generated.

Text Generator Script

<contactInformation> <name>${name}</name> <age>${age}</age> </contactInformation>

Generated Text

<contactInformation> <name>Peter Person</name> <age>58</age> </contactInformation>

The exact usage of input variables inside the script depends on the type. In the above example both name and age are of the type value. The workflow values these input variables will get, is defined in the workflow. Say, for a Text Generation activity, the values are mapped in the Variables menu, accessed through the Input variables button.

The example above displays the mapping between the input variables from the text generator and question answers from the form activity Contact Information. (We’ll get back to the input variable personalForm, which is connected to the full form) Answers submitted by the end user during the workflow session will get assigned to these input variables and appear in the generated file.

Text Generator Scriptlets

In addition to referencing input variables, more advanced logic can be inserted with <% %> notation. You can add Groovy code between the <% %> notation to generate new output, as shown below:

Text Generator Script

<% def isSeniorCitizen(age) { return age > 65 } %> <contactInformation> <name>${name}</name> <age>${age}</age> <% if (isSeniorCitizen(age)) { %> <seniorCitizen>Y</seniorCitizen> <% } %> </contactInformation>

Generated Text

<contactInformation> <name>Mary McLady</name> <age>111</age> <seniorCitizen>Y</seniorCitizen> </contactInformation>

We’ve defined a function, isSeniorCitizen, and invoked it later in the script. As shown above, Groovy code can be interleaved between normal text sections. It should be noted that code placed between <% %> does not contribute to the end output, whilst code placed inside ${} notation does.

Scripting with form answer based input variables

What operations can be performed on the input variables depends solely on the type of input variables. The three types of input variables are data type variable, form answer based and option source variable. When you have a form answer based type input variable, you can reference all question elements in the entire form. The following is an example of a script with the form answer based input variable personalForm:

Text Generator Script

<contactInformation> <name>${personalForm.Q1.answer}</name> <age>${personalForm.Q2.answer}</age> <dateOfBirth>${personalForm.Q3.answer.asString}</dateOfBirth> <communicationMethod>${personalForm.Q4.answer.value}</communicationMethod> <creditCardTypes> <% for (selectedOption in personalForm.Q5.answers) { %> <type>${selectedOption.value}</type> <% } %> </creditCardTypes> </contactInformation>

Generated Text

<contactInformation> <name>Dan Druff</name> <age>29</age> <dateOfBirth>1992-01-01</dateOfBirth> <communicationMethod>1</communicationMethod> <creditCardTypes> <type>1</type> </creditCardTypes> </contactInformation>

When writing the script, it was known that Q1 and Q2 are value input questions, Q3 is also a value input question but with a Date validation, Q4 is a single-select question and Q5 is a multiselect question.

The next example uses a form answer based input variable named signUpForm and goes through all standard questions and prints out the answers. (Standard questions refers to all questions that aren’t inside question groups in the data model)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <form> <%for (aQuestion in signUpForm.questionAnswers.values()) {     if (aQuestion instanceof ValueInputQuestion) {%>         <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${(aQuestion.answer instanceof DateObj) ? aQuestion.answer.asString : aQuestion.answer}</question>     <%} else if (aQuestion instanceof SingleSelectQuestion) {%>         <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${aQuestion.answer.value}</question>     <%} else if (aQuestion instanceof MultiSelectQuestion) {%>         <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${aQuestion.answers.value}</question>     <%}  }%> </form>

Note that file answers are not considered here. It can work on any form, but again, this script will not print content inside question groups in the data model. However, this next example does, and is taking file based answers into account.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <form> <%for (questionGroupList in signUpForm.questionGroupAnswers.values()) {     for (aQuestionGroup in questionGroupList) {%>         <questionGroup id="${aQuestionGroup.groupId}">             <%for (aQuestion in aQuestionGroup.questionAnswerList) {                 if (aQuestion instanceof ValueInputQuestion) {%>                     <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${(aQuestion.answer instanceof DateObj) ? aQuestion.answer.asString : aQuestion.answer}</question>                 <%} else if (aQuestion instanceof SingleSelectQuestion) {%>                     <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${aQuestion.answer?.value}</question>                 <%} else if (aQuestion instanceof MultiSelectQuestion) {%>                     <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${aQuestion.answers.value}</question>                 <%} else if (aQuestion instanceof FileQuestion) {%>                     <question id="${aQuestion.question.id}" text="${aQuestion.question.label.text.xml}">${aQuestion.answer?.fileName}</question>                 <%}             }%>         </questionGroup>     <%   } }%> </form>

It goes through all question groups recursively and prints out the answer values. It can work on any form.

As mentioned earlier, methods inside the ${} notation will affect the generated text. Here is an example of how you can split up a Date object, and also format the answer to your liking:

Text Generator Script

<contactInformation> <name>${name}</name> <age>${age}</age> <dateOfBirth> <year>${dateOfBirth.year}</year> <month>${dateOfBirth.month}</month> <day>${dateOfBirth.day}</day> <text>${dateOfBirth.asString}</text> <formatted>${dateOfBirth.format('DD-MM-YYYY')}</formatted> </dateOfBirth> </contactInformation>

Generated Text

<contactInformation> <name>Dinah Mite</name> <age>39</age> <dateOfBirth> <year>1982</year> <month>5</month> <day>13</day> <text>1982-05-13</text> <formatted>13-05-1982</formatted> </dateOfBirth> </contactInformation>

 

In this case all input variables are connected to value input questions. The name input variable is String validated, age is integer validated and dateOfBirth is Date validated.

Even though all these examples are XML scripts, the same principles and Groovy scriptlets holds up for JSON output files and other formats.