SurveyLoopr
Tips & Tricks
9 min read

XLSForm None of the Above in select_multiple

Mehrab Ali
Mehrab AliPublished October 27, 2026

To make "None of the above" exclusive in an XLSForm select_multiple question, set the constraint to not(selected(., '0')) or count-selected(.) = 1, where 0 is the name of the None choice. It reads: either None is not ticked, or it is the only thing ticked. ODK, KoboToolbox and SurveyCTO all evaluate it the same way, and every example on this page compiles with pyxform and ODK Validate.

Download example form (.xlsx)All four examples in one XLSForm, one group each. Tested with pyxform and ODK Validate; free to reuse under CC BY 4.0.Download

What is the constraint for an exclusive None option?

A select_multiple answer is a space-separated list of the choice names that were ticked, such as 1 4. The constraint runs when the enumerator tries to move on, and it checks that list. In a constraint, . means "this question's answer".

typenamelabelhintrequiredconstraintconstraint_message
select_multiple shockshocksWhich of these shocks did the household face in the last 12 months?Select all that apply, or choose None.yesnot(selected(., '0')) or count-selected(.) = 1None cannot be combined with another answer.
surveychoicessettings
list_namenamelabel
shock1Drought or flood
shock2Crop pest or disease
shock3Death of livestock
shock4Job loss or illness of the main earner
shock5Sharp rise in food prices
shock0None of the above
surveychoicessettings

Two functions do the work:

  • selected(., '0') is true when the choice named 0 is among the ticked options.
  • count-selected(.) is the number of options ticked.

The form blocks the swipe only when None is ticked and something else is too. Ticking only None passes, and ticking several real options without None passes.

How do I make both None and Don't know exclusive?

Surveys often carry two exclusive answers: "None" and "Don't know". Neither may be combined with a real answer. Test for either one, then require a single selection:

typenamelabelrequiredconstraintconstraint_message
select_multiple symptomsymptomsWhich symptoms does the child have today?yescount-selected(.) = 1 or not(selected(., '0') or selected(., '-99'))None and Don't know must be the only answer, or choose real symptoms.
surveychoicessettings
list_namenamelabel
symptom1Fever
symptom2Cough
symptom3Diarrhoea
symptom4Vomiting
symptom5Skin rash
symptom0None of these
symptom-99Don't know
surveychoicessettings

This still allows "None" alone and "Don't know" alone, but not "None" with "Don't know", because that would mean two ticks. The same pattern extends to a third exclusive option such as Refused: add or selected(., '-98') inside the not(...).

How do I limit selections to a maximum and keep None exclusive?

This is a frequent forum question: allow up to 3 answers, but only 1 when None is chosen. Join the two rules with and:

typenamelabelhintrequiredconstraintconstraint_message
select_multiple cropcropsWhich crops did the household grow this season?Choose up to 3 crops.yescount-selected(.) <= 3 and (count-selected(.) = 1 or not(selected(., '0')))Choose up to 3 crops, or only 'Did not grow any crops'.
surveychoicessettings
list_namenamelabel
crop1Maize
crop2Rice
crop3Beans
crop4Cassava
crop5Groundnut
crop6Vegetables
crop0Did not grow any crops
surveychoicessettings

One constraint message covers both failures, so write it to name both rules. If you only need the maximum, count-selected(.) <= 3 on its own is enough. More validation patterns are in the XLSForm constraint examples.

Why add a None option instead of letting people skip?

If the question is optional and an enumerator leaves it empty, you cannot tell "the household had no shocks" from "the enumerator forgot". An explicit None option removes the doubt: every completed interview has a real answer. So pair the None choice with required set to yes, as every example above does.

Do not let the empty answer stand in for None, and do not drop required to "make it easier". The analysis then splits into three groups (some, none, missing) instead of two.

How do I use the None answer in later questions?

Treat None as a normal choice in later rules. Ask a follow-up only when the household reported at least one shock, and count shocks without counting None itself:

typenamelabelrequiredrelevantconstraintconstraint_messagechoice_filtercalculation
select_multiple shockshocksWhich of these shocks did the household face in the last 12 months?yesnot(selected(., '0')) or count-selected(.) = 1None cannot be combined with another answer.
select_one shockworst_shockWhich shock hurt the household most?yesnot(selected(${shocks}, '0'))name != '0'
calculateshock_countif(selected(${shocks}, '0'), 0, count-selected(${shocks}))
noteshow_countShocks reported: ${shock_count}
surveychoicessettings
list_namenamelabel
shock1Drought or flood
shock2Crop pest or disease
shock3Death of livestock
shock4Job loss or illness of the main earner
shock5Sharp rise in food prices
shock0None of the above
surveychoicessettings

worst_shock is skipped when None is ticked, and its choice_filter of name != '0' removes None from the list it shows. Because the earlier constraint guarantees None is alone, shock_count is either 0 or the number of real shocks. Skip logic on a select_multiple question covers the relevant side in more depth.

Warning:

The mistake that compiles is comparing with = or !=. On a select_multiple question, . != '0' is also true for 0 1, because the whole string 0 1 is not equal to 0. The constraint then blocks nothing and no error appears. Always use selected() and count-selected().

Common mistakes and the errors you will see

The messages below come from ODK Validate, which ODK Central, KoboToolbox and the XLSForm converter run when a form is uploaded:

You wroteWrite insteadError you will see
selected(., '0') && count-selected(.) = 1selected(., '0') and count-selected(.) = 1Couldn't understand the expression starting at this point
not selected(., '0') or count-selected(.) = 1not(selected(., '0')) or count-selected(.) = 1Couldn't understand the expression starting at this point
count-selected(.) <= 3 AND not(...)count-selected(.) <= 3 and not(...)Couldn't understand the expression starting at this point
count-selected(.) =< 3count-selected(.) <= 3Bad node
. != '0' on a select_multiplenot(selected(., '0'))No error, but nothing is blocked

and, or and not() are XPath words: lowercase, with not written as a function. For other messages, see common XLSForm errors, or paste the form into the free XLSForm validator.

Does this work the same in ODK, KoboToolbox and SurveyCTO?

Yes. selected() and count-selected() are standard XPath functions in all three, so the constraint text is identical. Only the place you type it differs:

PlatformWhere the constraint goes
ODK (XLSForm)constraint column, with the sentence in constraint_message
KoboToolbox (XLSForm upload)Same as ODK
KoboToolbox FormbuilderThe question's Validation criteria setting
SurveyCTOconstraint column of the form definition

A form that follows this page moves between the three platforms with its logic intact.

Where exclusive options pay off in the field

An enumerator who has just heard "none of those" can still tick a real option by accident, and the dataset then says a household had no shocks and a drought. That contradiction takes hours to find in Stata or R and cannot be fixed after the interview. The constraint stops it while the respondent is still in the room.

Tip:

Describe the rule in plain language: "None of the above must be the only answer, and allow at most 3 other options." LooprAI writes the constraint and the message, then compiles the form with pyxform before saving, so a missing parenthesis never reaches your enumerators.

Build my first form free

Next: XLSForm constraint examples →

Frequently Asked Questions

How do I stop None from being selected with other options in XLSForm?

Add a constraint to the select_multiple question: not(selected(., '0')) or count-selected(.) = 1, where 0 is the name of the None choice. The form then refuses to move on when None is ticked together with any other option.

How do I limit a select_multiple question to 3 answers in XLSForm?

Use count-selected(.) <= 3 in the constraint column and write a constraint message such as 'Choose no more than 3.' To keep None exclusive as well, join both rules with and and wrap the None test in parentheses.

How do I make both None and Don't know exclusive?

Use count-selected(.) = 1 or not(selected(., '0') or selected(., '-99')). It passes when only one option is ticked, or when neither exclusive option is ticked. Add another or selected(...) inside not() for a third option such as Refused.

Why does my None constraint not block anything?

You probably compared with = or != instead of selected(). A select_multiple answer is a space-separated list, so . != '0' is also true for the answer '0 1'. Switch to selected(., '0') and count-selected(.), which read the list correctly.

Should the None option be required?

Yes. Set required to yes so every completed interview has a real answer. If the question is optional, an empty value could mean no or skipped by mistake, and you cannot tell the two apart during analysis.

Is the None constraint the same in KoboToolbox and SurveyCTO?

Yes. ODK, KoboToolbox and SurveyCTO all support selected() and count-selected(), so the same constraint text works in each. In XLSForm and SurveyCTO it goes in the constraint column; in Kobo's Formbuilder use the question's Validation criteria.

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.