XLSForm / pyxform

A Python package to create XForms for ODK Collect.
BSD 2-Clause "Simplified" License
77 stars 134 forks source link

fix parsing of (multiple) pulldata calls in a (multi-line) expression #547

Closed lindsay-stevens closed 2 years ago

lindsay-stevens commented 2 years ago

Closes #509

Why is this the best possible solution? Were any other approaches considered?

Users may wish to format their large / complex expressions with newlines and still utilise the pulldata() function. It seems most XLSForm documentation and examples show pulldata used on its own in an expression. However the existing test test_external_instance_pulldata_constraint_in_expression shows that pulldata is valid as part of compound expressions. It may be a bit unusual but there seems to be no technical reason why an expression could not use multiple pulldata calls. These changes result in support for multi-line formatted expressions, and multiple pulldata calls in an expression.

Alternatives may be to raise an error if a) multi-line formatting or b) multiple pulldata calls are detected in an expression. However there seems no spec or technical reason to forbid these usages.

What are the regression risks?

It may be that some XForm collectors / tools do not support expressions with line breaks, or multiple pulldata calls. In which case these applications could check for these and reject the form design. The current changes are accepted by ODK Validate so presumably they are OK.

Does this change require updates to documentation? If so, please file an issue here and include the link below.

No, they seem to be consistent with the documentation. The section "How to pull data from CSV" refers to pulldata as a function, so it's reasonable to assume from that that it could be used more than once in an expression.

Before submitting this PR, please make sure you have:

lindsay-stevens commented 2 years ago

Tested a form with multiple pulldata and line-break on ODK Collect v2021.2.3 on Android 10 and it works.

Using the following files, the expected if and pulldata functionality applies:

/sdcard/Android/data/org.odk.collect.android/files/projects/DEMO/forms/test.xml ``` pyxform_autotesttitle 1 1 1 ```

CSV files in /sdcard/Android/data/org.odk.collect.android/files/projects/DEMO/forms/test-media/

my_data_b.csv

aref,metainstanceID
1,a
2,b

my_data_c.csv

aref,metainstanceID
1,g
2,f