XPath queries for external itemsets.csv (XLSForm)

If I'm using an internal choices list, I can do the following with XLSForm to pull the metadata of the selected city into a text field elsewhere:

survey tab:

type name label choice_filter calculation
text name Name
select_one states or_other state state
select_one cities city city state=${state}
text county county instance('cities')/root/item[name=${city}]/county

choices tab:

list_name name label state county
states texas Texas
states washington Washington
counties king King washington
counties pierce Pierce washington
counties king King texas
counties cameron Cameron texas
cities dumont Dumont texas king
cities finney Finney texas king
cities brownsville brownsville texas cameron
cities harlingen harlingen texas cameron
cities seattle Seattle washington king
cities redmond Redmond washington king
cities tacoma Tacoma washington pierce
cities puyallup Puyallup washington pierce

However, I run into a problem if I change select_one to select_one_external and move my choices to a external_choices tab. I suspect the XPath query isn't recognizing the path as valid...

CSV support in ODK is unfortunately pretty weird at the moment. select_one_external does not allow for XPath querying because it just builds a database with exactly the columns you have in your choices sheet. All it lets you do is use it to build selects.

Do you absolutely need to use an external file? I encourage you to try including your choices internally -- there have been recent speed increases to Collect that may make this a viable path even for large data sets. Also note that you can update a form with just a dataset change and upload it to Aggregate with a version change and keeping existing collected data.

If you really do need an external data file, your best bet will probably be the pulldata function which works with a different and also non-standards-compliant database implementation: http://xlsform.org/#pre-loading-csv-data. It would be helpful to understand why you have that need.

Thanks for the reply!

I'm not actually using ODK Collect, but enketo-transformer and enketo-core in a custom implementation... it looks like most XLSForm things should be cross-compatible though.

I want to make it possible to maintain the list of choices and their metadata independent of the XLSForm, so that I don't need to reprocess the whole XLSForm every time anything changes. Or maintain an independent list that can be used in multiple surveys.

Currently, I'm manually running my XLSForms through pyxform, then enketo-transformer, and loading it up into enketo-core. I'm storing the enketo-transformer output in a database to avoid re-processing.

I'll look into pulldata(), but is there more comprehensive documentation for it? It's unclear exactly what all the arguments are, and where the "fruits.csv" file has to live, or how it's linked? This is especially of interest due to the custom implementation I'm pursuing... should I provide a relative path like the following?

type name label appearance
select_one fruits fruits Select a fruit search(‘./itemsets/fruits.csv')

As an example use case, imagine I wanted to maintain a list of countries, and whether or not they had some arbitrary flag... let's say quarantine, or embargo, or something like that.

Maybe I'd want forms that have a country field to all reference that centralized list. So if a new country pops up, or one changes its name, I only have to change it in one place.

Additionally, the metadata may drive a secondary questions, i.e. if the user selects a country with a quarantine to prompt them for an acknowledgment or something similar.

This way we can update the metadata in a single place once, and have it automatically update the form logic without "recompiling" the XLSForms.

Ah, I guess you reference the CSV files in the media section of enketo-core.

Well, I'll give it a shot and report back. :slight_smile:

1 Like

I just realized I'm making my life difficult by storing the output of enketo-transformer... I should be transforming the xform every time...

The media section is in enketo-transformer, actually... but it doesn't seem like it's doing anything with my CSV...

Anyhow, enketo-core has a external option where you can manually shove in external instances... maybe I can rig up some hack that uses that if all else fails. :thinking: