Form Operators and Functions¶
Expressions in calculations, constraints, and relevants can contain operators and functions.
Operators¶
Math operators¶
Explanation |
Example |
|
---|---|---|
+ |
addition |
${salary_income} + ${self_employed_income} |
- |
subtraction |
${income} - ${expenses} |
* |
multiplication |
${bill} * 1.18 |
div |
division |
${percent_int} div 100 |
mod |
modulo (division remainder) |
(${even_number} mod 2) = 0 |
Warning
Math operators only work with numbers.
The addition operator cannot be used to concatenate strings. Use the
concat()
function instead.Empty values (that is, variables referencing unanswered questions) are actually empty strings, and will not be automatically converted to zero (0).
Comparison operators¶
Comparison operators are used to compare values.
The result of a comparison is always True
or False
.
Explanation |
Example |
Notes |
|
---|---|---|---|
= |
equal to |
${enrolled} = 'yes' |
Can compare numbers or strings. |
!= |
not equal to |
${enrolled} != 'yes' |
Can compare numbers or strings. |
> |
greater than |
${age} > 17 |
|
>= |
greater than or equal to |
${age} >= 18 |
|
< |
less than |
${age} < 65 |
|
<= |
less than or equal to |
${age} <= 64 |
Warning
The relational operators (
>
,>=
,<
,<=
) only work with numbers.Empty response values are not automatically converted to zero (0).
Boolean operators¶
Boolean operators combine two True
or False
values
into a single True
or False
value.
Explanation |
Example |
|
---|---|---|
and |
|
${age} > -1 and ${age} < 120 |
or |
|
${age} < 19 or ${age} > 64 |
Path operators¶
Explanation |
Example |
Notes |
|
---|---|---|---|
. |
current question's value |
. >= 18 |
Used in constraints. |
.. |
current question's parent group |
position(..) |
Used with |
Note
Formally, these are not operators but rather XPath references
to the current node (.
) and the parent node (..
).
XPath paths can be used to reference nodes of a form.
Functions¶
Control flow¶
- if(expression, then, else)¶
Returns
then
ifexpression
evaluates toTrue
. Otherwise, returnselse
.
- position(xpath)¶
Returns an integer equal to the 1-indexed position of the current node within the node defined by
xpath
.Most often this is used in the form
position(..)
to identify the current iteration index within a repeat group.XLSForm
type
name
label
repeat_count
calculation
note
person_list_note
Please list the names of the people in your household.
begin_repeat
person
Member of household
text
name
Name
end_repeat
begin_repeat
person_details
Details
count(${person})
calculate
current_name
indexed-repeat(${name}, ${person}, position(..))
date
member_bday
Birthday of ${current_name}
end_repeat
- once(expression)¶
Returns the value
expression
if the question's value is empty. Otherwise, returns the current value of the question.This can be used to ensure that a random number is only generated once, or to store the first value entered for a question in a way that is retrievable even if the response is changed later.
Warning
This function is often misunderstood. Read when expressions are evaluated to learn more.
Accessing response values¶
Note
The response from most question types can be accessed using variables. Functions are needed for accessing responses to multi select questions and questions inside repeat groups.
Select questions¶
- selected(space_delimited_array, string)¶
Returns
True
ifstring
is a member ofspace_delimited_array
, otherwise returnsFalse
.Commonly used to determined if a specific choice was selected in a select question. (This is possible because a reference to a select question returns a space-delimited array of choice names.)
XLSForm
¶ type
name
label
hint
relevant
constraint
select_multiple medical_issues
what_issues
Have you experienced any of the following?
Select all that apply.
select_multiple cancer_types
what_cancer
What type of cancer have you experienced?
Select all that apply.
selected(${what_issues}, 'cancer')
select_multiple diabetes_types
what_diabetes
What type of diabetes do you have?
Select all that apply.
selected(${what_issues}, 'diabetes')
begin_group
blood_pressure
Blood pressure reading
selected(${what_issues}, 'hypertension')
integer
systolic_bp
Systolic
. > 40 and . < 400
integer
diastolic_bp
Diastolic
. >= 20 and . <= 200
end_group
text
other_health
List other issues.
selected(${what_issues}, 'other')
note
after_health_note
This note is after all health questions.
¶ list_name
name
label
medical_issues
cancer
Cancer
medical_issues
diabetes
Diabetes
medical_issues
hypertension
Hypertension
medical_issues
other
Other
cancer_types
lung
Lung cancer
cancer_types
skin
Skin cancer
cancer_types
prostate
Prostate cancer
cancer_types
breast
Breast cancer
cancer_types
other
Other
diabetes_types
type_1
Type 1 (Insulin dependent)
diabetes_types
type_2
Type 2 (Insulin resistant)
- selected-at(space_delimited_array, n)¶
Returns the string at the
n
th position of thespace_delimited_array
. (The array is zero-indexed.) Returns an empty string if the index does not exist.This can be used to get the
name
of a selected choice from a multi-select question. (This is possible because a reference to a select question returns a space-delimited array of choice names.)Note
If used to get a choice name from a select question, this function returns the
name
, not thelabel
, of the selected choice. To get the label in the current language, usejr:choice-name()
.XLSForm
¶ type
name
label
hint
calculation
select_multiple colors
color_prefs
What colors do you like?
Select three.
calculate
color_0
selected-at(${color_prefs}, 0)
calculate
color_1
selected-at(${color_prefs}, 1)
calculate
color_2
selected-at(${color_prefs}, 2)
note
color_note
Selected colors:
${color_0} <br> ${color_1} <br> ${color_2}
¶ list_name
name
label
colors
red
Red
colors
blue
Blue
colors
yellow
Yellow
colors
green
Green
colors
orange
Orange
colors
purple
Purple
- count-selected(multi_select_question)¶
Returns the number of choices selected in
multi_select_question
.XLSForm
¶ type
name
label
hint
constraint
constraint_message
select_multiple colors
color_prefs
What colors do you like?
Select three.
count-selected(.)=3
Select exactly three.
¶ list_name
name
label
colors
red
Red
colors
blue
Blue
colors
yellow
Yellow
colors
green
Green
colors
orange
Orange
colors
purple
Purple
- jr:choice-name(choice_name, 'select_question')¶
Returns the label value, in the active language, associated with the
choice_name
in the list of choices for theselect_question
.Note
You have to wrap the
select_question
reference in quotes.'${question_name}'
XLSForm
¶ type
name
label::English
label::Español
hint::English
hint:Español
calculation
select_multiple colors
color_prefs
What colors do you like?
¿Qué colores te gustan?
Select three.
Seleccione tres.
calculate
color_0
jr:choice-name( selected-at(${color_prefs}, 0), '${color_prefs}')
calculate
color_1
jr:choice-name( selected-at(${color_prefs}, 1), '${color_prefs}')
calculate
color_2
jr:choice-name( selected-at(${color_prefs}, 2), '${color_prefs}')
note
color_note
Selected colors:
Colores seleccionados:
${color_0} <br> ${color_1} <br> ${color_2}
${color_0} <br> ${color_1} <br> ${color_2}
¶ list_name
name
label::English
label::Español
colors
red
Red
Rojo
colors
blue
Blue
Azul
colors
yellow
Yellow
Amarillo
colors
green
Green
Verde
colors
orange
Orange
Anaranjado
colors
purple
Purple
Púrpura
Repeat groups¶
Helpful terms
- nodeset¶
A collection of XML nodes. In XLSForms, this is typically a collection of response values.
Outside a repeat group, referring to a question by name will return a nodeset containing all the responses to that question.
Nodesets can also be created by joining two or more nodes with pipes:
/data/age | /data/name
.
- indexed-repeat(name, group, i[, sub_grp, sub_i[, sub_sub_grp, sub_sub_i]])¶
Returns the response value of question
name
from the repeat-groupgroup
, in iterationi
.Nested repeat groups can be accessed using the
sub
andsub_sub
parameters.XLSForm
type
name
label
repeat_count
calculation
note
person_list_note
Please list the names of the people in your household.
begin_repeat
person
Member of household
text
name
Name
end_repeat
begin_repeat
person_details
Details
count(${person})
calculate
current_name
indexed-repeat(${name}, ${person}, position(..))
date
member_bday
Birthday of ${current_name}
end_repeat
- count(nodeset)¶
Returns the number of items in
nodeset
. This can be used to count the number of repetitions in a repeat group.XLSForm
type
name
label
repeat_count
calculation
note
person_list_note
Please list the names of the people in your household.
begin_repeat
person
Member of household
text
name
Name
end_repeat
begin_repeat
person_details
Details
count(${person})
calculate
current_name
indexed-repeat(${name}, ${person}, position(..))
date
member_bday
Birthday of ${current_name}
end_repeat
- count-non-empty(nodeset)¶
Returns the number of non-empty members of
nodeset
.
- sum(nodeset)¶
Returns the sum of the members of
nodeset
.Can be used to tally responses to a repeated select question.
XLSForm
¶ type
name
label
calculation
begin_repeat
guest_details
Guest details
text
guest_name
Guest name
select_one meal_options
meal_preference
Meal preference
calculate
chkn
if(${meal_preference} = 'chicken', 1, 0 )
calculate
fsh
if(${meal_preference} = 'fish', 1, 0 )
calculate
veg
if(${meal_preference} = 'vegetarian', 1, 0 )
end_repeat
calculate
chkn_count
sum(${chkn})
calculate
fsh_count
sum(${fsh})
calculate
veg_count
sum(${veg})
¶ list_name
name
label
meal_options
chicken
Chicken
meal_options
fish
Fish
meal_options
vegetarian
Vegetarian
- max(nodeset)¶
Returns the largest member of
nodeset
.XLSForm
¶ type
name
label
calculation
begin_repeat
child_questions
Questions about child
text
child_name
Child's name
integer
child_age
Child's age
end_repeat
calculate
age_of_oldest_child
max(${child_age})
- min(nodeset)¶
Returns the smallest member of
nodeset
.XLSForm
¶ type
name
label
calculation
begin_repeat
child_questions
Questions about child
text
child_name
Child's name
integer
child_age
Child's age
end_repeat
calculate
age_of_youngest_child
min(${child_age})
Warning
The min()
and max()
functions
only work sets of numbers.
Empty values
(that is, variables referencing unanswered questions)
are actually empty strings,
and will not be automatically converted to zero (0).
Strings¶
Searching and matching strings¶
- regex(string, expression)¶
Returns
True
ifstring
is an exact and complete match forexpression
.See also
XLSForm
¶ type
name
label
constraint
constraint_message
text
middle_initial
What is your middle initial?
regex(., '\p{L}')
Just the first letter.
- contains(string, substring)¶
Returns
True
if thestring
contains thesubstring
.
- starts-with(string, substring)¶
Returns
True
ifstring
begins withsubstring
.
- ends-with(string, substring)¶
Returns
True
if thestring
ends withsubstring
.
- substr(string, start[, end])¶
Returns the substring of
string
beginning at the indexstart
and extending to (but not including) indexend
(or to the termination ofstring
, ifend
is not provided). Members ofstring
are zero-indexed.
- substring-before(string, target)¶
Returns the substring of
string
before the first occurrence of thetarget
substring. If thetarget
is not found, orstring
begins with thetarget
substring, then this will return an empty string.
- substring-after(string, target)¶
Returns the substring of
string
after the first occurrence of thetarget
substring. If thetarget
is not found this will return an empty string.
- translate(string, fromchars, tochars)¶
Returns a copy of
string
, where every occurrence of a character infromchars
is replaced by the corresponding character intochars
. Iffromchars
is longer thantochars
then every occurrence of a character infromchars
that does not have a corresponding character intochars
will be removed.
- string-length(string)¶
Returns the number of characters in
string
. If no value is passed in, returns the number of characters in the value of the question that this function call is tied to which can be useful in aconstraint
expression.
- normalize-space(string)¶
Returns a string with normalized whitespace by stripping leading and trailing whitespace of
string
and replacing sequences of whitespace characters with a single space. If no value is passed in, normalizes whitespace of the value of the question that this function call is tied to.
Combining strings¶
- concat(arg [, arg [, arg [, arg [...]]]])¶
Concatenates one or more arguments into a single string. If any
arg
is a nodeset, the values within the set are concatenated into a string.
- join(separator, nodeset)¶
Joins the members of
nodeset
, using the stringseparator
.
Converting to and from strings¶
- boolean-from-string(string)¶
Returns
True
ifstring
is "true" or "1". Otherwise,False
.
- string(arg)¶
Converts
arg
to a string.
Encoding and decoding strings¶
- digest(data, algorithm, encoding method (optional))¶
Computes and returns the hash value of the data
string
using the indicated hash algorithmstring
, and encoding this hash value using the optional encodingstring
.Options for the algorithm are
MD5
,SHA-1
,SHA-256
,SHA-384
,SHA-512
.If the third parameter is not specified, the encoding is
base64
. Valid options for the encoding arebase64
andhex
.This function can be useful if, for example, someone wants to build a unique identifier from sensitive data like a national ID number without compromising that data.
- base64-decode(string)¶
Decodes all bytes from the input using the Base64 encoding scheme, assuming that the encoded bytes represent UTF-8 characters. Returns a UTF-8 character string.
- extract-signed(string, public-key)¶
Given a base64-encoded, signed string and public key as inputs, verifies that the first 64 bytes are a valid Ed25519 signature. If the signature is valid, returns the message (non-signature) portion of the contents as a UTF-8 string. If the signature is not valid, returns an empty string.
Math¶
Warning
Math functions (except number()
) only work with number values.
You can use number()
to convert a string of digits to a number,
but it is usually better to get a number value directly.
Empty values (that is, variables referencing unanswered questions) are actually empty strings, and will not be automatically converted to zero (0).
Number handling¶
- round(number, places)¶
Rounds a decimal
number
to some number of decimalplaces
.
- int(number)¶
Truncates the fractional portion of a decimal
number
to return an integer.
- number(arg)¶
Converts
arg
to number value.If
arg
is a string of digits, returns the number value.If
arg
isTrue
, returns 1. Ifarg
isFalse
, returns 0.If
arg
cannot be converted, returnsNaN
(not a number).
Calculation¶
- pow(number, power)¶
Raises a
number
to apower
.
- log(number)¶
Returns the natural log of
number
.
- log10(number)¶
Returns the base-10 log of
number
.
- abs(number)¶
Returns the absolute value of
number
.
- sin(number)¶
Returns the sine of
number
.
- cos(number)¶
Returns the cosine of
number
.
- tan(number)¶
Returns the tangent of
number
.
- asin(number)¶
Returns the arc sine of
number
.
- acos(number)¶
Returns the arc cosine of
number
.
- atan(number)¶
Returns the arctan of
number
.
- atan2(y, x)¶
Returns the multi-valued inverse tangent of
y
,x
.
- sqrt(number)¶
Returns the square root of
number
.
- exp(x)¶
Returns
e^x
.
- exp10(x)¶
Returns
10^x
.
- pi()¶
Returns an approximation of the mathematical constant π.
Date and time¶
- today()¶
Returns the current date without a time component.
- now()¶
Returns the current datetime in ISO 8601 format, including the timezone.
Warning
This function is often misused. Read when expressions are evaluated to learn more.
Converting dates and time¶
- decimal-date-time(dateTime)¶
Converts
dateTime
value to the number of days since January 1, 1970 (the Unix Epoch).This is the inverse of
date()
.
- date(days)¶
Converts an integer representing a number of
days
from January 1, 1970 (the Unix Epoch) to a standard date value.This is the inverse of
decimal-date-time()
.
- decimal-time(time)¶
Converts
time
to a number representing a fractional day. For example, noon is 0.5 and 6:00 PM is 0.75.
Formatting dates and times for display¶
- format-date(date, format)¶
Returns
date
as a string formatted as defined byformat
.The following identifiers are used in the
format
string:%Y
4-digit year
%y
2-digit year
%m
0-padded month
%n
numeric month
%b
short text month (Jan, Feb, Mar…)
%d
0-padded day of month
%e
day of month
%a
short text day (Sun, Mon, Tue…).
Note
Month and day abbreviations are language and locale specific. If form locale can be determined, that locale will be used. Otherwise, the device locale will be used.
- format-date-time(dateTime, format)¶
Returns
dateTime
as a string formatted as defined byformat
.The identifiers list in
format-date()
are available, plus the following:%H
0-padded hour (24-hr time)
%h
hour (24-hr time)
%M
0-padded minute
%S
0-padded second
%3
0-padded millisecond ticks.
Geography¶
- area(nodeset | geoshape)¶
Returns the area, in square meters, of either a
nodeset
of geopoints or ageoshape
value.It takes into account the circumference of the Earth around the Equator but does not take altitude into account.
- distance(nodeset | geoshape | geotrace | geopoint, geopoint [, geopoint [...]])¶
Returns the distance, in meters, of either:
a
nodeset
of geopoints
¶ type
name
label
calculation
begin_repeat
points
geopoint
point
Record a Geopoint
end_repeat
calculate
calculated_distance
distance(${point})
note
display_distance
Calculated distance: ${calculated_distance}
the perimeter of a
geoshape
¶ type
name
label
calculation
geoshape
shape
Record a Geoshape
calculate
calculated_distance
distance(${shape})
note
display_distance
Calculated distance: ${calculated_distance}
the length of a
geotrace
value
¶ type
name
label
calculation
geotrace
trace
Record a Geotrace
calculate
calculated_distance
distance(${trace})
note
display_distance
Calculated distance: ${calculated_distance}
a list of geopoints either specified as strings or references to other fields
¶ type
name
label
calculation
geopoint
point1
Record a Geopoint
geopoint
point2
Record a Geopoint
calculate
dist
distance(${point1}, ${point2})
note
dist_note
Calculated distance: ${dist}
The
distance
function takes into account the circumference of the Earth around the equator but does not take altitude into account. The longer the line segments are, the less accurate the computed distance will be. Additionally, distance calculations closer to the equator are more accurate than ones close to the poles.You can use the
distance
function for things like basic reverse geocoding and basic geofencing. See this sample form for multiple examples.
- geofence(geopoint, geoshape)¶
Returns
True
if the specified point is inside the specified geoshape,False
otherwise.¶ type
name
label
relevant
appearance
geoshape
shape
Specify a shape to use as a fence
geopoint
point
Select a point to see whether it is in the fence
placement-map
note
in_note
Point is inside the fence
geofence(${point}, ${shape})
note
out_note
Point is outside the fence
${point} != '' and not(geofence(${point}, ${shape}))
You can find the above example in this Google Sheet.
The
geofence
function is helpful for things like validating that a data collector is in the expected location when filling out a form. If you don't need to define precise boundaries, you can instead use thedistance()
function to validate that a data collector is within a certain distance of the center of the target location.If you need to validate that data collectors are at an indoor location, keep in mind that location capture is generally inaccurate indoors unless there are cellular and WiFi signals available. You can address this by asking data collector to capture the location of the building front door before entering or by defining a fence that is, for example, 5 to 10 meters outside the real boundaries of the building.
Utility¶
- random()¶
Returns a random number between 0.0 (inclusive) and 1.0 (exclusive).
Warning
This function is often misused. Read when expressions are evaluated to learn more.
- randomize(nodeset[, seed])¶
Returns a shuffled
nodeset
.A shuffle with a numeric
seed
is deterministic and reproducible.The primary use for this function is to randomize the order of choices for a select question. The documentation on select widgets describes how this is done in XLSForm.
randomize()
can only be used in a context where anodeset
is accepted. Note that questions of type calculate cannot reference anodeset
.
- uuid([length])¶
Without argument, returns a random RFC 4122 version 4 compliant UUID.
With an argument it returns a random GUID of specified
length
.
- boolean(arg)¶
Returns
True
ifarg
is:a number other than zero
a non-empty string
a non-empty collection
a comparison or expressions that evaluates to
True
.
Returns
False
ifarg
is:the number 0
an empty string
an empty collection
a comparison or expression that evaluates to
False
.
- not(arg)¶
Returns the opposite of
boolean(arg)
.
- coalesce(arg1, arg2)¶
Returns first non-empty value of the two
arg
s. Returns an empty string if both are empty or non-existent.
- checklist(min, max, response[, response[, response[, ...]]])¶
Returns
True
if the number ofresponse
s that are exactly the string "yes" is betweenmin
andmax
, inclusive.Set
min
ormax
to-1
to make the argument not applicable.
- weighted-checklist(min, max, reponse, weight[, response, weight[, response, weight[, response, weight[, ... ]]])¶
Returns
True
if the sum of theweight
s of eachresponse
that is exactly the string "yes" is betweenmin
andmax
, inclusive.Set
min
ormax
to-1
to make the argument not
- true()¶
Evaluates to
True
.
- false()¶
Evaluates to
False
.