Other, Please Specify in XLSForm: ODK and Kobo
To add "Other, please specify" in XLSForm, add an Other choice with a code such as -96, then a text question right after the select with ${cooking_fuel} = '-96' in its relevant column (or selected(${water_sources}, '-96') for a select_multiple). The box appears only when Other is picked, and ODK, KoboToolbox and SurveyCTO all read it the same way. Every example below compiles with pyxform and ODK Validate, the check ODK Central runs when you upload a form.
How do I add Other, please specify to a select_one question?
Two rows on the survey sheet and one extra choice. This asks for the household's main cooking fuel, a standard energy and health question:
| type | name | label | relevant | required |
|---|---|---|---|---|
| select_one fuel | cooking_fuel | What is the main fuel the household uses for cooking? | yes | |
| text | cooking_fuel_other | Please specify the other cooking fuel. | ${cooking_fuel} = '-96' | yes |
| list_name | name | label |
|---|---|---|
| fuel | 1 | Electricity |
| fuel | 2 | LPG or natural gas |
| fuel | 3 | Kerosene |
| fuel | 4 | Charcoal |
| fuel | 5 | Wood |
| fuel | 6 | Animal dung or crop waste |
| fuel | -96 | Other (specify) |
Three habits keep this pattern clean across a whole questionnaire:
- One code for Other everywhere.
-96for Other,-98for Refused and-99for Don't know are common in household surveys. A negative code never clashes with a real answer and is easy to filter out in Stata or R. - Name the box after the question.
cooking_fuel_othersits next tocooking_fuelin the exported data, so nobody has to guess which question it belongs to. - Make it required. The
relevantcondition already hides it when Other was not picked, and a hidden question is never required. Sorequired=yesonly applies when the box is on screen.
The value in the condition is the choice name ('-96'), in quotes, not the label "Other (specify)".
How do I add Other, please specify to a select_multiple question?
Use selected() instead of =. A select_multiple answer is saved as every ticked name separated by spaces, such as 1 -96, so ${water_sources} = '-96' is only true when Other is the only option ticked:
| type | name | label | relevant | required |
|---|---|---|---|---|
| select_multiple water_source | water_sources | Which water sources does the household use for drinking? | yes | |
| text | water_sources_other | Please specify the other water source. | selected(${water_sources}, '-96') | yes |
| list_name | name | label |
|---|---|---|
| water_source | 1 | Piped water |
| water_source | 2 | Protected well |
| water_source | 3 | Unprotected well |
| water_source | 4 | Surface water (river or pond) |
| water_source | -96 | Other (specify) |
A "specify other" thread on the ODK forum with over 15,000 views describes exactly this: the box worked when Other was ticked alone and vanished as soon as a second source was ticked too. The select_multiple skip logic guide explains selected() in more detail.
selected() needs the code in quotes. selected(${water_sources}, -96) fails ODK Validate with "The second parameter to the selected() function must be in quotes (like '1')."
Should I use the or_other shortcut?
XLSForm has a shortcut: write or_other after the list name and pyxform adds an "Other" choice and a "Specify other" text question for you:
| type | name | label |
|---|---|---|
| select_one toilet or_other | toilet_type | What kind of toilet facility do members of the household usually use? |
| list_name | name | label |
|---|---|---|
| toilet | 1 | Flush to piped sewer |
| toilet | 2 | Pit latrine with slab |
| toilet | 3 | Pit latrine without slab |
| toilet | 4 | No facility (open defecation) |
It works, but the XLSForm specification itself recommends the explicit pattern above. The shortcut has limits you only find out about later:
- The Other choice is named
other, not a numeric code, so it breaks a numeric coding scheme. - The added label is English only. "Specify other" cannot be changed, and a form with translations gets the warning "This form uses or_other and translations, which is not recommended."
- No choice filter. A select with
or_otherand achoice_filterfails with "Choice filter not supported with or_other." - A fixed question name. The text question is always
<name>_other, so a form that also has its owntoilet_type_otherrow fails as a duplicate name.
For a multilingual form (see adding languages to an ODK form) or a cascading list, write the two rows yourself.
How do I stop one-letter or "other" answers in the specify box?
Enumerators under time pressure type x, . or the word "other". Add a constraint with string-length(), where . means "this answer":
| type | name | label | relevant | required | constraint | constraint_message |
|---|---|---|---|---|---|---|
| select_one occupation | main_occupation | What is the main occupation of the household head? | yes | |||
| text | main_occupation_other | Please specify the other occupation. | ${main_occupation} = '-96' | yes | string-length(.) >= 3 and . != 'other' and . != 'Other' | Write the occupation in at least 3 letters (not 'other'). |
| list_name | name | label |
|---|---|---|
| occupation | 1 | Own farm (crops or livestock) |
| occupation | 2 | Daily wage labour |
| occupation | 3 | Salaried job |
| occupation | 4 | Own business or trade |
| occupation | -96 | Other (specify) |
More text checks are in the XLSForm constraint examples.
How do I show the specified answer later in the form?
Work out the wording in a calculate, then use it in later labels. jr:choice-name() returns the label of the picked choice, and if() swaps in the typed text when Other was picked:
| type | name | label | relevant | calculation |
|---|---|---|---|---|
| select_one crop | main_crop | What is the main crop the household grew this season? | ||
| text | main_crop_other | Please specify the other crop. | ${main_crop} = '-96' | |
| calculate | main_crop_label | if(${main_crop} = '-96', ${main_crop_other}, jr:choice-name(${main_crop}, '${main_crop}')) | ||
| decimal | main_crop_harvest_kg | How many kilograms of ${main_crop_label} did the household harvest? |
| list_name | name | label |
|---|---|---|
| crop | 1 | Rice |
| crop | 2 | Maize |
| crop | 3 | Wheat |
| crop | 4 | Potato |
| crop | -96 | Other (specify) |
A respondent who picked Other and typed "sorghum" now sees "How many kilograms of sorghum did the household harvest?" instead of "How many kilograms of Other (specify)...".
Can the specify box be on the same screen as the question?
Yes. Put both rows in a group with the field-list appearance. ODK Collect and Enketo (KoboToolbox web forms) show the box the moment Other is ticked, without moving to a new screen:
| type | name | label | relevant | required | appearance |
|---|---|---|---|---|---|
| begin_group | info_source_screen | Information sources | field-list | ||
| select_multiple info_source | info_sources | Where did the household get information about the vaccination campaign? | yes | ||
| text | info_sources_other | Please specify the other source. | selected(${info_sources}, '-96') | yes | |
| end_group | info_source_screen |
| list_name | name | label |
|---|---|---|
| info_source | 1 | Health worker |
| info_source | 2 | Radio or TV |
| info_source | 3 | Mosque or church announcement |
| info_source | 4 | Neighbour or relative |
| info_source | -96 | Other (specify) |
If the box does not appear on one screen, check the relevant value first: on a select_multiple it must use selected().
Common Other, please specify mistakes
These are the messages pyxform and ODK Validate return, which is what you see when ODK Central, KoboToolbox or the XLSForm converter rejects a form:
| You wrote | Write instead | Error you will see |
|---|---|---|
${q} = '-96' on select_multiple | selected(${q}, '-96') | No error, but the box is missing when two options are ticked |
${q} = 'Other' (the label) | ${q} = '-96' (the name) | No error, but the box never appears |
selected(${q}, -96) | selected(${q}, '-96') | The second parameter to the selected() function must be in quotes (like '1'). |
${q_typo} = '-96' | The exact question name | Reference variables must contain a name from the 'survey' sheet. Could not find the name 'q_typo'. |
or_other with a choice_filter | Your own Other choice and text row | Choice filter not supported with or_other. |
or_other plus your own q_other row | One or the other, not both | Questions, groups, and repeats must be unique within their nearest parent group or repeat |
The first two rows are the costly ones: the form compiles, and the specify box is silently missing for part of the sample. For other messages, see common XLSForm errors, or paste your form into the free XLSForm validator.
Does this work the same in ODK, KoboToolbox and SurveyCTO?
Yes. The pattern is plain skip logic, so it moves between the three platforms unchanged. What differs is where you type it:
| Platform | Where the condition goes |
|---|---|
| ODK (XLSForm) | relevant column of the text row |
| KoboToolbox Formbuilder | Add a Text question, open its settings and set its Skip Logic to the Other choice of the select question |
| KoboToolbox (XLSForm upload) | Same as ODK |
| SurveyCTO | Column named relevance instead of relevant; the expression is the same |
selected(), string-length() and if() are standard ODK XPath functions, so the conditions and constraints on this page read the same on all three.
Why Other answers deserve a plan before fieldwork
"Other" is where a questionnaire learns what it missed. If 15% of households specify "solar cooker" or "rainwater tank", that is a choice the list should have had. Plan for it: one code for Other in every list, a specify box named after its question, and a recoding step after the pilot that turns frequent Other answers into real choices before the main survey starts.
You can describe it instead: "add Other, please specify to every select question". LooprAI adds the Other choice with code -96, writes the specify rows with the right relevant for select_one and select_multiple, and compiles the form with pyxform before anything is saved.
Next: skip logic in XLSForm →
Frequently Asked Questions
How do I add Other, please specify in XLSForm?
Add an Other choice with a code such as -96 to the list, then a text question right after the select with ${question} = '-96' in its relevant column. The text box appears only when Other is picked. Set required to yes so it cannot be left empty.
Why does my Other specify box not appear on a select_multiple question?
The condition uses = instead of selected(). A select_multiple answer stores every ticked code separated by spaces, so ${q} = '-96' is false once a second option is ticked. Write selected(${q}, '-96') in the relevant column instead.
What is or_other in XLSForm?
or_other is a shortcut written after the list name, as in select_one toilet or_other. pyxform adds an Other choice named other and a Specify other text question. It cannot be used with choice_filter, its label is English only, and the XLSForm spec recommends writing the rows yourself.
What code should I use for Other in XLSForm choices?
Use one numeric code for Other in every list, such as -96, with -98 for Refused and -99 for Don't know. Negative codes never clash with real answers and are easy to filter in analysis. Avoid or_other if you want numeric codes, since it names the choice other.
Can I show the Other text in a later question label?
Yes. Add a calculate such as if(${crop} = '-96', ${crop_other}, jr:choice-name(${crop}, '${crop}')) and use ${crop_label} in later labels. The respondent then sees the crop they typed instead of the words Other (specify).
Does Other, please specify work the same in KoboToolbox and SurveyCTO?
Yes. It is ordinary skip logic. KoboToolbox reads the same relevant column, or you set it in the Formbuilder's Skip Logic. SurveyCTO uses the same expression in a column named relevance. selected() and string-length() behave the same on all three.
No Credit Card Required
Build the form first. Add hosting when you need it.
Start free with LooprAI, then deploy a managed ODK Central server or run DataSnap checks when your project is ready.
Automation handles the mechanical work.
Researchers decide what the evidence means.