Proposal: customize name and label 'columns' in selects from external data in XLSForm

When creating select options from external (and internal) data in XLSForm, the "name" and "label" data columns are hardcoded in the XForm output (and therefore required in the data), when using:

  • select_one_from_file filename.csv & select_one_from filename.xml
  • select_multiple_from_file filename.csv & select_multiple_from filename.xml
  • (are there others?)

This means that you'd normally have to modify the data file to rename columns (or XML nodes), which is not great.

This is purely a pyxform/xlsform restriction because Collect, Enketo, iXForms etc are perfectly capable to deal with other names.

How about adding something outrageous (but very nice) support for:

select_multiple_from_file hh-data.csv using hh_number as value and hh_name as label (where either one or two column/node names can be changed)

What do you think? Implementation considerations/problems in pyxform would be very valid arguments, of course.

Sorry I didn't respond to this earlier. Agreed this is important to do.

How about using the parameters column in XLSForm? We added it for question types that need any kind of specialized data. That would mean introducing value and label parameters for those types, both of which are optional. There's no possible validation because the external files wouldn't be available to pyxform. So whatever values are provided would just be passed on to the XML.

1 Like

Yes, using parameters would be perfect to override value and label. Thanks!

type parameters name label
select_multiple_from_file hh-data.csv value=hh_number, label=hh_name a Select
1 Like

Issue was created here:

1 Like

Thanks, @martijnr! I've been having a Briefcase-related conversation with a user that overlaps with this and which led me to an enketo-transformer issue and a Kobo forum post. He's @Freeedim in those places and I'm hoping we can unify the various threads and make progress.

He rightfully points out that it's important to be able to specify labels in multiple languages so columns for the underlying value and a single label aren't enough.

I don't find the jr:itext multi language machinery very compatible with external secondary instances because it expects all the translations to be in the form definition. This defeats the purpose of pushing data to external files. Unless I'm missing something, I think we might need to consider extensions to the specs for jr:itext and external secondary instances to fully support using external secondary instances as sources of select choices.

search() provides multi-lingual support by:

  • having the user define column names in the choices sheet (for example, country in the name column, country_name in the label column, nom_pays in the label::French (fr) column, etc.)
  • using a static choice list with a single item in the form definition where the values for label and name define the columns to query in the external CSV
  • using a jr:itext call for the ref attribute of the label if the form is multilingual (for example, jr:itext('/data/produce/name:label') in external-csv-search-language.xml (2.0 KB) )
  • having a text item with a value that represents the corresponding label column in the CSV for each language in the itext block. (For example, the text block for /data/multi_produce/name:label in the form above has the value label::French in French).

@martijnr am I forgetting a straightforward mechanism for specifying multiple language labels in an external secondary instance? This is a big thing that has kept us from moving on from search().

1 Like

Good point. Would be nice to figure that out too. Thanks!

Yes, indeed.

Nothing defined afaik, but actually Enketo does support an undocumented, rogue :flushed: and forgotten method that relies on using ::nl postfixes to CSV columns or lang="nl" attributes in XML nodes. I wonder if that less flexible solution would be acceptable, as it's a very lightweight solution and I like it.

It would be exposed by a (new) translation function call. Enketo chose the function name translate1 and it could be used in the above proposal like this:

type parameters name label
select_multiple_from_file hh-data.csv value=hh_number, label=translate(hh_name) a Select

resulting in the XForm output:

<itemset nodeset="instance('hh-data')/root/item">
       <value ref="hh_number" />
       <label ref="translate(hh_name)" />

That new XPath function would return from its node-set parameter the first XML node (including transformed CSV to XML) with a lang attribute that matches the current language.

1 Very bad name because there is an XPath 1.0 function with that name that does something entirely different. We could use something like current-lang instead.