Expressions

Relevance, constraints and calculates all compute a new value using answers from other questions.

Syntax

Syntax:
operator usage example notes
this current prompt’s answer . . < 5 Constraint In a constraint, Dot (.) refers to the value in the current question.In this case it must be less than 5
not not(expression) not(selected(${qname}, ‘c’)) Relevant A question is relevant as long as ‘c’ is not selected in question qname
and and selected(., ‘c’) and selected(., ‘d’) Constraint Both ‘c’ and ‘d’ need to be selected in the current question
or or selected(., ‘c’) or selected(., ‘d’) Constraint Either ‘c’ or ‘d’ needs to be selected for the current question
greater than > . > 10.51 Constraint Current question must be greater than 10.51. Can also be combined with equals to make “greater than or equal” >=
less than < . < 10.51 Constraint Current question must be less than 10.51. Can also be combined with equals to make “less than or equal” <=
selected selected(xpath/to/node, value) selected(${qname}, ‘n’) Relevant Checks if answer in selected prompt is selected Note xpath to node can be specified using ${} syntax with the question name
count-selected count-selected(${multiple_choice_q}) count-selected( . ) < 4 Constraint The number of options selected in this question must be less than 4.
selected-at selected-at(${multiple_choice_q}, index) selected-at(${trips}, 0) The first selected item will be at index 0, the second at index 1 etc
regular expression regex(value, expression) regex(., ‘[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}’) Constraint This regex checks for a valid email address
equal to . = . = number(‘10’) Constraint Current answer must be equal to 10
Conditional (if)

if(condition, a, b)

If the condition is true use “a” otherwise use “b”

if(${count} < 10, ${count}, 10) Calculate If the count is less than 10 then use it.Perhaps as the number of times a repeat group is to be asked.Otherwise use the value 10.Hence this sets a cap on the value.

Date Functions

Date Functions:
operator usage example
date formatted as text

format-date(${question}, format)

Refer to the following section for a list of the date formats

format-date(${dob}, ‘%Y %n %d’)

“2011 2 26”

Convert a date, or a time or a date and time to a decimal number

decimal-date-time(${question})

Useful as part of a date calculation.Every additional day adds one to the number

Every additional hour adds 1/24 to the number

Not available in web forms

Constraint decimal-date-time( . )> (decimal-date-time(${dob}) + 10.0416666)

The entered date time must be more than 10 days and one hour after the date of birth.

Convert a date to a decimal number

decimal-date-time(${question})

Useful as part of a date calculation.Every additional day adds one to the number

Not available in web forms

Constraint decimal-date( . )> (decimal-date(${dob}) + 10)

The entered date must be more than 10 days after the date of birth.

Convert a time to a decimal number

decimal-time(${question})

Useful as part of a date calculation.Every additional hour adds 1/24 to the number

Not available in web forms

Constraint decimal-time( . )>decimal-time(${time_of_birth}) + 10 div 24

The entered time must be more than 10 hours after the date of birth.

Convert a decimal number to a date

date-time(${question})

Convert a calculated date back into date format.

Relevant date-time(decimal-date-time(${dob})+10)

The date is equal to the date of birth plus 10 days.

Get todays date today()  
Convert text to date date(‘some text)’ constraint=”. >= date(‘2011-11-12’)”

Date Formats

  1. %Y : 4 digit year
  2. %y : 2 digit year
  3. %m : numeric month padded with 0
  4. %n : numeric month
  5. %b : short text month (English)
  6. %d : day of month
  7. %H : hour, 24 hour clock padded with 0
  8. %h : hour, 24 hour clock
  9. %M : minute padded with 0
  10. %S : second padded with 0
  11. %3 : milliseconds padded with 0
  12. %a : short text day (English)

Text Functions

Text Functions:
Function usage example
Concatenate Text concat(text1, text2, text3 etc)

concat(${name}, ${address}, ${city})

This joins the answers to the name, address and city question. Use it with a “calculate” question

Join Text join(separator, text1, text2, text3 etc) This is the same as concatenate text except it adds the “separator” text between each of the items of text you are joining

join(‘;’,’Details’,${name}, ${age})

If the value of name was “John Smith” and the value of age was “26” then this would set the value of a calculate question to: Details;John Smith;26

Convert to number number(${num-plots})  
Convert to integer int(${num-plots})  
Convert to text string(${num-plots})  
Get the label for a choice in a select one question jr:choice-name(${question name}, ‘${choice name}’).

jr:choice-name(${transport_type}, ‘${transport_type}’)

Note the quotes around the second parameter

substring-before

substring-before(a, b)

Returns everything in “a” before the text in “b”

substring-before(‘xx-yy’, ‘-‘) returns ‘xx’

substring-before(${q}, ‘ ‘) where ${q} has the value “Tom Smith”, this will return “Tom”

Available with fieldTask 5.90

aubstring-after

substring-after(a, b)

Returns everything in “a” after the text in “b”

substring-after(‘xx-yy’, ‘-‘) returns ‘yy’

substring-after(${q}, ‘ ‘) where ${q} has the value “Tom Smith”, this will return “Smith”

Available with fieldTask 5.90

translate

translate(text, abc, XYZ)

text The text to evaluate. abc The string of characters that will be replaced. XYZ The string of characters used for replacement. The first character inXYZwill replace every occurrence of the first character inabcthat appears intext.

translate(‘My old car’, ‘old’, ‘new’) will return ‘My new car’.

translate(‘My old car’, ‘olda’, ‘newx’) will return ‘My new cxr’.

Available with fieldTask 5.90

The usage was taken from the following site which provides more information: https://developer.mozilla.org/en-US/docs/Web/XPath/Functions/translate

normalize-space normalize-space(text) Removes leading and trailing spaces from text and converts multiple spaces into a single space
Text Length string-length(question)

string-length(.) < 5

Constraint The length of the text entered in the current question must be less than 5 characters

Mathematical

Referring to data inside repeats, also called sub-forms, can be quite complex as you often need to identify which iteration of the sub form you are referring to. These functions can assist.

Math Functions:
operator usage example
Plus   ${a} + ${b}
Minus
${a} - ${b}
Times
${a} * ${b}
Divide div ${a} div ${b}
Modulus Remainder mod 3 mod 2 Results in 1
Raise to the power pow(a,b)

pow(${width}, 3)

Returns ${width} * ${width} * ${width}

Random number

random()

Returns a random number between 0.0 (inclusive) and 1.0 (exclusive)

round((random()* ${number_children} + 0.5), 0)

Generates a random number between 1 and the number of children in the household. This can be used to select a child for further questions.

It can be combined with the position() function to display the name of the child that has been selected.

Round to a number of decimal places

round(a,b)

Rounds the number a to the number of decimals places b

round(${weight_kg}, 2)

round(0.5, 0)is 1

Sum of repeating group sum(nodeset) sum(${weight})
Maximum max(nodeset) Maximum value in a repeating group
Minimum min(nodeset) Minimum value in a repeating group

Repeats

Referring to data inside repeats, also called sub-forms, can be quite complex as you often need to identify which iteration of the sub form you are referring to. These functions can assist.

Repeat Functions:
operator usage example
reference a question inside a repeat group

indexed-repeat(${repeatquestion}, ${repeatgroup}, index)

Index starts from 1

indexed-repeat(${name}, ${geopolygon_a}, 2)

Returns the value for the name question in the second occurrence of the geopolygon_a repeat group.

Index of current repeat group position(..)

indexed-repeat(${name}, ${names}, position(..))

Returns the name from the names repeat group at the same location index as the current repeat group.

Getting the number of repeats count()

count(${repeat_name})

Returns the number of repeats

Online

Online Functions:
Function usage example
lookup This function can be used instead of pulldata in calculations. It takes the same parameters as pulldata. However the csv file is not downloaded. This can be useful when you have very large reference files.

lookup(‘hhdata’,’members’,’hhid_key’,${hhid})

Not available in web forms

lookup_choices This function can be used instead of the search() function. Both this and search() are placed in appearance. It takes the same parameters as search. However the csv file is not downloaded. This can be useful when you have very large reference files.

lookup_choices(‘children’, ‘matches’, ‘class_v’, ${class}, ‘enrolled_v’, ${enrolled})

Not available in web forms

lookup_image_labels

lookup_image_labels(picture)

This has no counterpart in offline mode. It can be used to call AWS Rekognition service to identify objects in a picture. Use in a calculation.

The image must be a jpg file.

To make this useful for your project you would probably want to create your own AI tool to recognise patterns in data and ask the fieldTask development team to add that as a service.

lookup_image_labels(${a_picture})

Not available in web forms

get_media Download a media file from a server. This media file can then be used as the default value for an image, video or audio question. Use in a calculation to set an image as an intial value to a question.

Use a select to identify a base image to be downloaded and then annotated.

1) Select a picture to edit. The value of the select is the URL of the image. 2) In a calculate have: get_media(${image_select_question}, ‘/main/image_show_question’). This will download the selected image 3) Have an image question with appearance of annotate” and a calculation of ${calculate_question_name}.

Because of the way ODK evaluates calculations when the user saves the form using the naive approach above will cause the modified image not to be sent. Refer to the dynamic image examples in the examples for an approach that will work.”

Other

Other Functions:
Function usage example
pulldata pulldata(filename, data column, key column, key value)

pulldata(‘hhdata’,’members’,’hhid_key’,${hhid})

This retrieves a value from the members column in the hhdata.csv file where the hhid_key column has the value selected for the hhid question.

Available in webforms in version 18.05+

coalesce coalesce(value, value)

coalesce(${age}, 0)

Coalesce returns the first non empty value out of the values provided in the parameters.This is useful when doing calculations with numbers as if a value was empty, perhaps because the question was not relevant, then the calculation will not work.

In this example the age value is set to 0 if it is empty.

area

area(${the_geom})

Where the_geom is the name of a geoshape type question

Note the name of the geoshape needs to be “the_geom”.
distance

distance(${the_geom})

Where the_geom is the name of a geoshape or geotrace question

As for area you should name your geometry question “the_geom”. The reason being Smap currently converts all geometry questions to that name to simplify GIS analysis. So if you are referencing a question in an “area” function using a different name then it will not be found.
once once(${age}) The value will only be evaluated once while the form is open. This is useful for setting dynamic default values that you want to get an initial value but after that the value should be set by the user.