Functions can be used to validate syntax, calculate values, transform data, and control workflow. 

Much of the content below is borrowed and adapted under the Creative Commons license from Get ODK. Note: OpenClinica does not support every function listed on the Get ODK website. Review the full list of functions that have been validated and tested in OpenClinica in the OpenClinica Validated Functions Index.

General functions
Functions for repeating data structures
Date and time functions
Math functions and number handling
String functions
Calculations


General Functions

Description:Evaluates expression, if the expression is true it returns or executes the then statement, if the expression evaluates to false it returns/executes the else statement.
Syntax:if(expression, then, else)
Example:if(${ae_death} = ‘yes’, ‘SAE’, if(${ae_hospital} = 'yes', 'SAE', if(...))) 

This nested if statement will eventually cascade through the entire SAE criteria list to see if any were answered 'Yes', and if so it will return 'SAE', if not then it will move to the next criteria and so-on. The last statement should return 'false' or similar negative value.

Description:Returns the value defined by 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.

Syntax:once(expression)
Example:once(today())
When used in a calculation, returns the current date on form load. If an expression is in a calculation, constraint, or required condition, it is evaluated when the item becomes relevant and the item is not empty. Typically used in calculations.Could also be used in relevant conditions or constraints, but in these cases its usually more clear to use as if() statement. For example:

Instead of using once(), you could also if(. !='', today(), .). If it's not empty, do expression. Otherwise, leave unchanged.

 

Description:Checks whether string2 appears in string1, where string1 is a space-separated list of values. Either or both could be item references instead of hard-coded string literals.
Syntax:selected(string1, string2)
Example:selected(${diagnoses}, 'cancer')
Returns true if “cancer” was selected from a set of diagnoses. Otherwise, returns false.

not(selected(., 'c') or selected(., 'd'))
Returns true if the user did not choose c or d from the current item.

Note: Can be used as a shortcut for writing many or clauses. For example, selected('a b c d e', .) is a shortcut for ". = 'a' or . = 'b' or ' = 'c' or . = 'd' or . = 'e'." This could be useful in if() statements, relevant logic, etc.

Description:Returns the number of choices selected in a multiple choice question.
Syntax:count-selected(select_multiple_item_name)
Example:count-selected(${days_sick})
Returns the number of days the subject was sick (e.g. from a set of choices ${days_sick} such as Mon, Tue, Wed, etc.).  Taking a space separated string and telling you how many of a given value exist. Can also be used to count the total number of selection choices in a space separated lists. If you concatenate strings together with a space, or join repeating data with a space, in a calculate item, this function would return the total number of items in that string.


Functions for Repeating Data Structures

Description:Returns the largest member of nodeset.

Only works on sets of numbers. Empty values (that is, variables referencing unanswered questions) are actually empty strings, and will not be automatically converted to zero (0). Learn more about Null Values in Form Logic.

Syntax:max(nodeset)
Example:In the below example, the calculation max(${child_age}) would return the largest age of all the ages in the repeating item group.

If you wanted to see if one of the children was, say 5 years old, you could use the join or concatenate function to produce a string of all the responses, then use this string as the argument for the selected function.

typenamelabelcalculation
begin_repeatchild_questionsQuestions about child 
textchild_nameChild's name 
integerchild_ageChild's age 
end_repeat   
calculateage_of_oldest_child max(${child_age})

Description:Returns the smallest member of nodeset. 

Only works on sets of numbers. Empty values (that is, variables referencing unanswered questions) are actually empty strings, and will not be automatically converted to zero (0). Learn more about Null Values in Form Logic.

Syntax:min(nodeset)
Example:In the below example, the calculation min(${child_age}) would return the lowest age of all the ages in the repeating item group.
typenamelabelcalculation
begin_repeatchild_questionsQuestions about child 
textchild_nameChild's name 
integerchild_ageChild's age 
end_repeat   
calculateage_of_youngest_child min(${child_age})

Description:Returns the sum of the members of nodeset. Can be used to tally responses to a repeated select question.
Syntax:sum(nodeset)
Example:The below example uses this function to tally the number of meal preference.
typenamelabelcalculation
begin_repeatguest_detailsGuest details 
textguest_nameGuest name 
select_one meal_optionsmeal_preferenceMeal preference 
calculatechkn if(${meal_preference} = 'chicken', 1, 0 )
calculatefsh if(${meal_preference} = 'fish', 1, 0 )
calculateveg if(${meal_preference} = 'vegetarian', 1, 0 )
end_repeat   
calculatechkn_count sum(${chkn})
calculatefsh_count sum(${fsh})
calculateveg_count sum(${veg})

Description:Returns the sum of the members of nodeset. Can be used to tally responses to a repeated select question.
Syntax:count(nodeset)
Example:The below example asks the user for the number of family members, then uses the count function to ensure follow-up questions are asked once per each family member.
typenamelabelrepeat_countcalculation
noteperson_list_notePlease list the names of the people in your household.  
begin_repeatpersonMember of household  
textnameName  
end_repeat    
begin_repeatperson_detailsDetailscount(${person}) 
calculatecurrent_name  indexed-repeat(${name}, ${person}, position(..))
datemember_bdayBirthday of ${current_name}  
end_repeat    

Description:Returns the number of non-empty members of nodeset.
Syntax:count-non-empty(nodeset)
Example:count-non-empty(${bp_sys})
Returns the number of times systolic blood pressure was blank, where ${bp_sys} captures systolic blood pressure inside a repeating group.

If a user adds a repeating group occurrence but does not put data into any of its fields, the count() function would increase by 1, but the count-non-empty() function would not increase.

Description:Returns a particular iteration of a repeating value. 
Syntax:indexed-repeat(item_name, repeating_group_name, iteration)

item_name is the variable you want to retrieve
repeating_group is the name of the repeating group containing the item_name
iteration is the repetition number for the item_name

Example:indexed-repeat(${bp_diastolic}, ${bp_rg}, ${bp_number})

When used as a calculation, returns the diastolic pressure from a specific repeat instance, where:

  • ${bp_diastolic} is the value by the diastolic pressure captured across one or more repetitions
  • ${bp_rg} is the name of the repeating group that collects multiple blood pressure values
  • ${bp_number} is an integer indicating which repetition of the blood pressure to return

Description:Returns an integer equal to the position of the current node within the node defined by xpath. The first entry has a position of 1, second entry 2, and so on. 

Most often this is used in the form position(..) to identify the current iteration within a repeating group.

Syntax:position(xpath)
Example:position(..)
When used as a calculation inside a repeating group, will return the current repeat iteration. Could be used to assign a number for each repetition. In the example below, the first repeating group captures the names of each household member. The second repeating group asks for the birthdate for each household member entered in the first group. This shows how position() can be used with indexed-repeat().
typenamelabelrepeat_countcalculation
begin_repeat  
calculatemed_num  position(..)
textnamePlease enter the name of medication # ${med_num)  
end_repeat    

 


String functions

Description: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.

Syntax:concat(arg1, arg2, arg3...)
Example:concat(${yyyy},'-',${mm},'-',${dd})
Combines year, month, and day (each captured separately) into a single item formatted YYYY-MM-DD.

concat(${temp},' ⁰C')
Combines temperature value with units label (e.g. to display "37 ⁰C").

Description:Converts arg to a string.
Syntax:string(arg)
string references the item for which you wish to count characters

Description:Returns True if the string is an exact and complete match for the expression. Regular expressions provide a standardized way of validating the syntax of data entered.
Syntax:regex(string, expression)

string is the value you want to which you want to apply the regular expression
expression is the regular expression

Example:regex(., '([01][0-9]|2[0-3]):[0-5][0-9]') and string-length(.) = 5
When used as a constraint, ensures the user enters time in 24-hour format (HH:MM)

regex(., '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}')
When used as a constraint, ensures the user enters an email address in the format xxxx@xxxx.xxxxLearn more about how to construct regular expressions.

Description:Returns the substring of string beginning at the index start and extending to (but not including) index end (or to the termination of string, if end is not provided).
Syntax:substr(string, start, end)
string references the data item you wish to parse
start is the index number of the beginning character you want to include
end is the index number of the first character after start that you do NOT want to include

Members of string are zero-indexed, so the first character of the string has index value of 0, the second character an index value of 1, etc.

Example:substr(${date}, 0, 4)
Returns just the 4-digit year from a date field which has a format such as YYYY-MM-DD.

 

Description:Returns the substring of string before the first occurrence of the target substring.

If the target is not found, or string begins with the target substring, then this will return an empty string.

Syntax:substring-before(string, target)
string references the data item you wish to parse
target is the stopping point (up to which the system will return the partial string)
Example:substr-before(${kit_num}, ‘-’)
If the value of ${kit_num} is "123-ABC-XYZ", the function would return 123. Returns the string value before the first occurrence of the target.

Description:Returns the substring of string after the first occurrence of the target substring. If the target is not found this will return an empty string.
Syntax:substring-after(string, target)
string references the data item you wish to parse
target is the starting point, beyond which you want the system will return the remaining string
Example:substr-after(${kit_num}, ‘-’)
If the value of ${kit_num} is "112-ABC-XYZ", the function would return ABC-XYZ. Returns the string value after the first occurrence of the target. To return just XYZ, you could run this function two times, nested together. 

Description: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 a constraint expression.

Syntax:string-length(string)
string references the item for which you wish to count characters
Example:substr(., string-length(.) - 4, string-length(.)) = ".pdf" or substr(., string-length(.) - 4, string-length(.)) = ".PDF"

Ensures only PDF files are uploaded when used as a constraint on a file field.

The substing function first gets the last 4 characters of the file name. Then it checks to see if the PDF file extension is all lowercase or uppercase.

 

Description:Returns a copy of a string where every occurrence of a specified character is replaced by a new character.
Syntax:translate(string, fromchars, tochars)

string is the item you want to translate
fromchars are the characters, if found within the string, you want to translate
tochars are the characters you want to translate to

If fromchars is longer than tochars then every occurrence of a character in fromchars that does not have a corresponding character in tochars will be removed from the string.

Example:translate(substr(., string-length(.) - 4, string-length(.)), 'pdf', 'PDF') = '.PDF'

When used as a constraint on a file field, ensures the files with a PDF extension are uploaded, regardless of the case in which the file extension is written.

The substing function first gets the last 4 characters of the file name. Then it checks to see if the PDF file extension is all lowercase or uppercase.

translate(${input_item}, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') 
Would translate any lowercase letter into an uppercase letter for the string input_item.

OpenClinica reads in cross form data from a select_multiple item as a comma separated list. However, if you want to treat this as a select_multiple value on the form you read it into, it must be treated as a space separated list. For example, the following expression would convert these values into a space separated string upon reading it into the form:

translate(instance('clinicaldata')/ODM/ClinicalData/SubjectData/StudyEventData[@StudyEventOID='Event OID Here']/FormData[@FormOID='Form OID Here']/ItemGroupData[@OpenClinica:ItemGroupName='Item Group Name Here']/ItemData[@OpenClinica:ItemName='Item Name Here']/@Value, ',', ' ') 


Math functions and number handling

Description:
Syntax:not(expression)
Example:

Description:Truncates the fractional portion of a decimal number to return an integer.
Syntax:int(number)
Example:int(${age)

If ${age} = 24.6, would return the value 24.

Description:Converts arg to number value.

If arg is a string of digits, returns the number value.

If arg is True, returns 1. If arg is False, returns 0.

If arg cannot be converted, returns NaN (not a number).

Syntax:number(arg)
Example:number(${year})

if ${year} = "1995", then number(${year}) would return 1995

Description:Rounds a decimal number to some number of decimal places.
Syntax:round(number, # places)
Example:round(${pi}, 4)

If ${pi} = “3.14159”, then round(${pi}, 4) would return 3.1416

Description:Returns a random number between 0.0 (inclusive) and 1.0 (exclusive).
Syntax:random()
Example:once(round(random()*3+1,0))

The above expression would return and integer of either 1, 2, or 3, and could thus be used to randomly assign participants to one of three groups.

The following logic could then be used to map the output of the above function to one of the three groups:

if(${rndm} = 1,'A', if(${rndm} = 2,'B', 'C'))

 

 

 


Date and Time

Description:Returns the current date without a time component.
Syntax:today()
Example:The expression . <= today() could be used in a constraint to ensure the date entered is not a future date.

Description:Returns the current date and time with the timezone.
Syntax:now()
Example:For example, this can be used to set the current date and time as default.

Description:Converts time to a number representing a fractional day.
Syntax:decimal-time(time)
Example:For example,

decimal-time(12:00)

noon is 0.5 and 6:00 PM is 0.75.

Description:Returns date as a string formatted as defined by format.
Syntax:format-date(date, format)
Example:format-date(${date},‘%d-%b-%Y’)

If ${date} = 2028-11-06 would return 06-Nov-2028

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.

%Y4-digit year
%y2-digit year
%m0-padded month
%nnumeric month
%bshort text month (Jan, Feb, Mar…)
%d0-padded day of month
%eday of month
%ashort text day (Sun, Mon, Tue…).

Description:Returns dateTime as a string formatted as defined by format.
Syntax:format-date-time(dateTime, format)
Example:

 

The identifiers list in format-date() are available, plus the following:

%H0-padded hour (24-hr time)
%hhour (24-hr time)
%M0-padded minute
%S0-padded second
%30-padded millisecond ticks.

Calculations

Description:Raises number to a power
Syntax:pow(number, power)
Example:pow(2,3) 

Returns the value 8.

Description:Returns the natural log of number.
Syntax:log(number)
Example:log(30) 

Returns 3.4011973816621555, the natural log of 30.

Description:Returns the base-10 log of number.
Syntax:log10(number)
Example:log10(30) 

Returns 1.4771212547196624, the base-10 log of 30.

Description:Returns the absolute value of number.
Syntax:abs(number)
Example:abs(-5.23) 

Returns 5.23.

Description:Returns the absolute value of number.
Syntax:abs(number)
Example:abs(-5.23) 

Returns 5.23.

2.2.5.1 OpenClinica Validated Functions Index

All OpenClinica Validated Functions

String Functions
string(* arg)
concat(string arg*|node-set arg*)
join(string separator, node-set nodes*)
substr(string value, number start, number end?)
substring-before(string, string)
substring-after(string, string)
translate(string, string, string)
string-length(string arg)
normalize-space(string arg?)
contains(string haystack, string needle)
starts-with(string haystack, string needle)
ends-with(string haystack, string needle)
uuid(number?)
pulldata(string instance_id, string desired_element, string query_element, string query)

Boolean Functions
if(boolean condition, string then, string else)
coalesce(string arg1, string arg2)
once(string calc)
true()
false()
boolean(* arg)
boolean-from-string(string arg)
not(boolean arg)
regex(string value, string expression)

Number Functions
number(* arg)
random()
int(number arg)
sum(node-set arg)
max(node-set arg*)
min(node-set arg*)
round(number arg, number decimals?)
pow(number value, number power)
log(number arg)
log10(number arg)
abs(number arg)
sin(number arg)
cos(number arg)
tan(number arg)
asin(number arg)
acos(number arg)
atan(number arg)
atan2(number arg, number arg)
sqrt(number arg)
exp(number arg)
exp10(number arg)
pi()

Node-set Functions
count(node-set arg)
count-non-empty(node-set arg)
position(node arg?)
instance(string id)
current()
randomize(node-set arg, number seed)

Date and Time Functions
today()
now()
format-date(date value, string format)
format-date-time(dateTime value, string format)
date(* value)
decimal-date-time(dateTime value)
decimal-time(time value)

Select Functions
selected(string list, string value)
selected-at(string list, number index)
count-selected(node node)
jr:choice-name(node node, string value)

Repeat Functions
indexed-repeat(node-set arg, node-set repeat, number index)

 

Note: The asterisk (*) in these functions indicates that it can take arguments of multiple types (string, number, date, etc.).