Loop over pre-established list

Hi,

I'm using XLSForm with ODK Collect and ona.io. I'm building a new form. I have to loop 3 time over the same question , but I'd like to present a different word each time :

I have a "begin repeat/end repeat" with a repeat_count column set to 3. I put my 3 word in a list, in the "choices" worksheet. I'm trying to calculate a field for each loop. I tried selected-at(my-list, postion(..)-1) But it doesn't seem to work properly :-(. Do you have any advice ? Maybe with pulldata, but I don't want CSV.

Hi @Remi_Desgrange! what do you mean it doesn't seem to work properly? Perhaps you can attach a very small test XLSForm that we could look at?

Sure ! Here is a quick exemple. Basically, when I iterate over the loop I would like to say "position A" then "position B" Then "position C" instead of "position 1" then "position 2", etc...(position in repeat I get from position(..))
test-form.xlsx (10.7 KB)

I am not clear your problem but you can rename position serial using a calculation which is like that if the position is 1 then convert it into Position A.

See this example test-form.xlsx (16.2 KB)

If you want to repeat a group based on the multiple selections and want to view the label of the selection then you can see this example

multiple_selected_item_repeat.xlsx (14.7 KB)

Thank, I have let say 5 value, it will start to look like a big if/else statement. So there is no way to loop over predefined array ?

Bonjour @Remi_Desgrange. Your intuition to use a choice list is just right but the XLSForm converter isn't actually including the list in your form because it doesn't see it being used. Additionally, selected-at can only be used to pick a string out of a space-separated string, not to pick an item in a list.

This form shows a possible approach to what you're trying to do. I'd like to hear from others whether they can come up with a simpler way.

I had to use some of my knowledge of the underlying XForms spec and XPath to get this working. I'll explain it a bit below for those interested but I think it should be possible to pattern match on the structure without a full understanding of the details.

The placeholder question with a choice filter tricks the XLSForm converter into actually adding your list to the form. The choice filter is important because it's what makes the XLSForm converter output an instance for the list rather than putting the choices inline. There's an issue to make it easier to add a list used for value lookups (as opposed to being used in selects) at https://github.com/XLSForm/pyxform/issues/176.

jr:itext(instance('masques_list')/root/item[position()=current()/../numero_masque]/itextId) is the other interesting bit. Understanding it really requires looking at the underlying form XML. You'll see that your list becomes an instance called masques_list with a single root and several items. The expression position()=current()/../numero_masque identifies the item that matches the repeat iteration that we're currently on. I had to create the numero_masque calculate because inside the [], the context is that expression (NOT the node) and it looks like position(current()/..) is not supported. Once we have the desired item, we can grab the ID of the label string defined (itextId) and then look up the string with jr:itext. This should work with multiple languages defined in the form.

Again, I'm interested in simpler alternatives. One slight concern I have and that I'll try to look into more deeply soon is that I would have expected this to be affected by the bug described at Fixing current() context in choice filter but it seems not to be. Just realized that bug only affects predicates used in defining itemsets so this use of current() should be fine.

3 Likes