javarosa icon indicating copy to clipboard operation
javarosa copied to clipboard

Validate reports invalid self-reference for indexed-repeat()

Open tiritea opened this issue 5 years ago • 2 comments

Software versions

javaRosa as it exists in Validate as it exists in XSLForm Online v1.3.1

Problem description

using indexed-repeat() inside a repeat group to accumulate results, by referencing 'previous' repeat results; eg

if(position(..)=1, ${foo}, concat(indexed-repeat(., ${repeat}, position(..)-1))

fails DAG check because detects reference to self (.), even though not in fact self-referencing because actually referencing result from previous iteration.

Steps to reproduce the problem

run form with repeat group that uses an accumulator in this manner. Form cannot run because DAG check incorrectly detects as self-reference cycle

Expected behavior

no error

Other information

no way to determine this is not in fact a self-reference except by dynamically evaluating the expression, to see that the resulting XML element is actually different (ie position(..)-1))

tiritea avatar May 24 '19 03:05 tiritea

As I understand it, you are trying to accumulate results across repeats. The form here demonstrates how I would do that. The important expression is join(" ", /data/my-repeat[position(..) <= position(current()/..)]/foo).

I find indexed-repeat more complicated to reason about than raw XPath queries so I try to avoid it.

I'm also not exactly clear on what you're trying to concatenate. Are you accumulating results into a node that is also a question?

lognaturel avatar Jul 11 '19 00:07 lognaturel

In the provided example, yes I was trying to accumulate results, which you correctly point out can probably be accommodated with a join(...) instead. However there are still cases when you want to reference previous iterations, eg prefilling values from the previous iteration (see https://forum.opendatakit.org/t/previous-response-pre-loaded-for-the-same-question-from-a-previous-iteration-of-a-repeat/20706/4)

The issue is that indexed-repeat() is the documented function for referencing specific values in a repeat group, and therefore - as defined - should work equally well within and outside a repeat group. I believe it probably can, but validate is 'interfering' by throwing a bogus cyclic dependency check, essentially based on the (false) premise in this case that a specified element node name is always unique, whereas it is not when it comes to repeat groups. Note that Enketo does not throw a cyclic dependency error here.

tiritea avatar Jul 11 '19 01:07 tiritea