Skip to main content

More on the realise function

This topic shows you how to use the realise function to generate sentences from different kinds of data.

Contents

Realise a JSON array

This example uses the following two JSON arrays:

{"people":[
    { "name":"John", "location":"London"},
    { "name":"Anna", "location":"New York" },
    { "name":"Peter", "location":"New York"}
],
 "cars":{ 
        "NYcars":{"make":"Ford", "number":4, "location":"New York" },
        "Londoncars":{"make":"Volvo", "number":2, "location":"London" }  
}}

and the following lex rule with “Abode” as the value for classes:

<S id="LexRule1" classes="Abode">
    <Subj word="{{msg.name}}"/>
    <VP word="live"/>        
    <Obj word="{{msg.location}}" preposition="in"/>
</S>

The following ATL script generates sentences from the lex rule:

[[realise((WholeJSON.people,'Abode'))]]

The result is:

John lives in London, Anna lives in New York. Peter lives in New York.

Each element in the JSON array is input in turn to the lex rule with classes="Abode" and a sentence is generated. Three sentences are generated because there are three objects in the JSON array.

Realise a filtered JSON array

This example uses the same data and lex rule used for Realise a JSON array above.

To generate from a subset of the JSON array, nest the filter function the ATL as follows:

[[realise((filter(WholeJSON.people, p -> p.location == 'London'),'Abode'))]]

This selects only those elements in WholeJSON.people with value ‘London’ for the location key.

The generated output is:

John lives in London.

This time only one sentence is generated because the filter blocks the data for the two objects with "location":"New York".

Realise a JSON object

This example uses the following JSON data:

{"people":[
    { "name":"John", "location":"London"},
    { "name":"Anna", "location":"New York" },
    { "name":"Peter", "location":"New York"}
],
 "cars":{ 
        "NYcars":{"make":"Ford", "number":4, "location":"New York" },
        "Londoncars":{"make":"Volvo", "number":2, "location":"London" }  
}}

and the following lex rule:

<S id="LexRule2" classes="Car">
    <Subj>
        <Spec word="the"/>
        <N word="{{msg.location}}"/>
        <N word="office"/>
    </Subj>
    <VP word="have"/>        
    <Obj>
        <Number int="{{msg.number}}"/>
        <N word="{{msg.make}}"/>
    </Obj>
</S>

To generate from a JSON object that is not an array, nest the values function in the ATL as follows:

[[realise((values(WholeJSON.cars),'Car'))]]

The above ATL uses the values function in realise to transform the JSON object WholeJSON.cars into a list of two objects. It uses a lex rule with classes="Car" to generate a sentence from each item in the list.

The generated output is:

The New York office has 4 Fords. The London office has 2 Volvos.

The JSON object is converted into a list and each item in the list is generated with the classes="Car" lex rule.

Realise a JSON array with mapping

This example uses the following JSON data:

{"people":[
    { "name":"John", "location":"London"},
    { "name":"Anna", "location":"New York" },
    { "name":"Peter", "location":"New York"}
],
 "cars":{ 
        "NYcars":{"make":"Ford", "number":4, "location":"New York" },
        "Londoncars":{"make":"Volvo", "number":2, "location":"London" }  
}}

and the following lex rule:

<S id="LexRule1" classes="Abode">
    <Subj word="{{msg.name}}"/>
    <VP word="live"/>        
    <Obj word="{{msg.location}}" preposition="in"/>
</S>

To generate from a JSON array with mapping, nest the map function in the ATL as follows:

[[realise((map(WholeJSON.people, f -> lower(f)),'Abode'))]]

The above ATL uses the map function to apply the lower function to each item in WholeJSON.people to transform it into lowercase. Then realise generates text from a lex rule with classes="Abode".

The generated output is:

John lives in london. Anna lives in new york. Peter lives in new york.

The city names in the output have been converted to lowercase. Notice that the sentences still begin with a capital because they are generated with a Sentence lex rule.

Realise a sorted JSON object

This example uses the following JSON data:

{"people":[
    { "name":"John", "location":"London"},
    { "name":"Anna", "location":"New York" },
    { "name":"Peter", "location":"New York"}
],
 "cars":{ 
        "NYcars":{"make":"Ford", "number":4, "location":"New York" },
        "Londoncars":{"make":"Volvo", "number":2, "location":"London" }  
}}

and the following lex rule:

<S id="LexRule2" classes="Car">
    <Subj>
        <Spec word="the"/>
        <N word="{{msg.location}}"/>
        <N word="office"/>
    </Subj>
    <VP word="have"/>        
    <Obj>
        <Number int="{{msg.number}}"/>
        <N word="{{msg.make}}"/>
    </Obj>
</S>

To generate from a JSON object that has been sorted, nest both the sort and values functions in the ATL as follows:

[[realise((sort(values(WholeJSON.cars), (p,q) -> (sign(p.number - q.number))),"Car"))]]

The above ATL uses the sort function to sort the data (converted into a list by values) by the number of cars using the lambda expression (p,q) -> (sign(p.number - q.number))). Then realise generates text from a lex rule with classes="Car".

The generated output is:

The London office has 2 Volvos. The New York office has 4 Fords.

Notice that the output sentences are now sorted by increasing numbers of cars.

Realise non-JSON data

You can use lex rules to generate from other kinds of input data (i.e. not just JSON objects). This section shows you how to input strings, lists, integers, ATL objects (lists of key–value pairs), and ATL strings.

When your input data is not in JSON format, there are two ways to handle this in a lex rule:

  1. Input a list of ATL objects instead of JSON data and refer to the keys in the same way as you would for JSON objects, i.e. use msg.name to refer to a key called 'name'. See ATL guide > ATL objects for more information.

  2. Use a special Message property called “data”, i.e. {{msg.data}} and input strings, lists, numbers, etc.

A list of key–value pairs

Let’s use one of the lex rules above that takes JSON input:

<S id="LexRule1" classes="Abode">
    <Subj word="{{msg.name}}"/>
    <VP word="live"/>        
    <Obj word="{{msg.location}}" preposition="in"/>
</S>

You can input an ATL object (a list of key–value pairs) with the same keys as the JSON data and the lex rule will treat the list as though it is a JSON object.

The following expression realises the rule with inputs that are new values for the keys ‘name’ and ‘location’:

[[realise((((name='Bill',location='Washington'),(name='Claire',location='Tampa')),'Abode'))]]

This produces:

Bill lives in Washington. Claire lives in Tampa.

The remaining examples show you how to use the special Message property, {{msg.data}}, with input strings, lists of strings, integers and ATL strings.

A single string

This example illustrates the use of {{msg.data}} in the following lex rule:

<S id="LexRule3" classes="StringInput2">
    <Subj word="{{msg.data}}"/>
    <VP word="be"/>        
    <PP string="on the payroll"/>
</S>

Input a single string to the above lex rule and realise the sentence with the following:

[[realise(('Bill','StringInput2'))]]

Here, the string ‘Bill’ is the input data to a rule with classes=”StringInput2″. The output text is:

Bill is on the payroll.

A list of strings

In this example, we input a list of strings to the same lex rule used for A single string.

[[realise((('Bill','Susan','Anne'),'StringInput2'))]]

The output text is:

Bill, Susan and Anne are on the payroll.

An integer

To input an integer, we need a lex rule that takes an integer input:

<S id="LexRule4" classes="InputNumber">
    <Subj>
        <Number int="{{msg.data}}" isAlpha="true"/>
        <N word="person">
            <Feature name="pluralform" value="people"/>
        </N>
    </Subj>
    <VP word="be"/>
    <PP string="on the payroll"/>
</S>

This rule has a <Number></Number> component that accepts integer input data, int="{{msg.data}}".

Let’s realise the rule with the integer 1 as input:

[[realise((1,'InputNumber'))]]

The result is:

One person is on the payroll.

Realising the rule with the integer 342 as input:

[[realise((342,'InputNumber'))]]

produces:

Three hundred forty-two people are on the payroll.

An ATL string

In this example, we will use the lex rule that takes a string as input data:

<S id="LexRule3" classes="StringInput2">
    <Subj word="{{msg.data}}"/>
    <VP word="be"/>        
    <PP string="on the payroll"/>
</S>

We can input an ATL string as follows:

[[realise(("one [[gender('Bill')]]",'StringInput2'))]]

and the output is:

One male is on the payroll.

Notice that the ATL string is encased in double quotes so that the ATL function [[gender('Bill')]] is evaluated. The result is “one male” which is the input to the lex rule.

Individual list elements

Finally, when you input a list of items, individual members of the list can be accessed with square bracket notation (array notation). So the first element in the list is accessed with msg.data[0], the second with msg.data[1] and so on. Don’t forget that the first element is at position 0 and the entire list is msg.data.

For this example, we'll use a new lex rule that accesses elements of an input list:

<S id="LexRule5" classes="AccessList">
    <Subj word="{{msg.data[0]}}"/>
    <VP word="live"/>        
    <Obj word="{{msg.data[1]}}" preposition="in"/>
</S>

The following expression realises the rule with an input list:

[[realise((('Bill','Washington'),'AccessList'))]]

This produces:

Bill lives in Washington.