Skip to content

Improve repeat count XForm output #435

@MartijnR

Description

@MartijnR

I think there are 2 is an issue with how pyxform transforms repeat_count values:

1.It places a new count node as sibling of the repeat. This means that any relevant condition on an ancestor of that repeat clears the repeat_count values and removes all repeats. This is not always desirable for implementations that want to keep irrelevant values stored in the model.

  1. The output is more verbose than necessary for simple ${node} references or static numbers.

See example below with the 3 different types of repeat_count values we support. I propose to change the output of all 3 the first and the third.

type name label repeat_count
integer count Enter count  
begin repeat rep1 Repeat with user entered count ${count}
text text1 Enter text  
end repeat      
begin repeat rep2 Repeat with calculated count ${count} + 2
text text2 Enter text  
end repeat      
begin repeat rep3 Repeat with fixed count 4
text text3 Enter text  
end repeat      

Google Sheets

current output (relevant parts):

        <model odk:xforms-version="1.0.0">
            <instance>
                <data id="repeat-count-cases">
                    <count/>
                    <group>
                        <rep1_count/>
                        <rep1 jr:template="">
                            ...
                        </rep1>
                        <rep1>
                            ...
                        </rep1>
                        <rep2_count/>
                        <rep2 jr:template="">
                            ...
                        </rep2>
                        <rep2>
                            ...
                        </rep2>
                        <rep3_count/>
                        <rep3 jr:template="">
                            ...
                        </rep3>
                        <rep3>
                            ...
                        </rep3>
                    </group>
                    ...
                </data>
            </instance>
            <bind nodeset="/data/count" type="int"/>
            <bind calculate=" /data/count " nodeset="/data/group/rep1_count" readonly="true()" type="string"/>
            <bind calculate=" /data/count  + 2" nodeset="/data/group/rep2_count" readonly="true()" type="string"/>
            <bind calculate="4" nodeset="/data/group/rep3_count" readonly="true()" type="string"/>
            ...
        </model>
    </h:head>
    <h:body>
        <input ref="/data/count">
            <label>Enter count</label>
        </input>
        <group ref="/data/group">
            <group ref="/data/group/rep1">
                <label>Repeat with user entered count</label>
                <repeat jr:count=" /data/group/rep1_count " nodeset="/data/group/rep1">
                    ...
                </repeat>
            </group>
            <group ref="/data/group/rep2">
                <label>Repeat with calculated count</label>
                <repeat jr:count=" /data/group/rep2_count " nodeset="/data/group/rep2">
                    ...
                </repeat>
            </group>
            <group ref="/data/group/rep3">
                <label>Repeat with fixed count</label>
                <repeat jr:count=" /data/group/rep3_count " nodeset="/data/group/rep3">
                    ...
                </repeat>
            </group>
        </group>
    </h:body>

A cleaner, and less problematic, output would be:

<model odk:xforms-version="1.0.0">
            <instance>
                <data id="repeat-count-cases">
                    <count/>
                    <group>
                        <rep1 jr:template=""><!-- NOTE: see body and bind, no additional node or calculation has to be created by pyxform for this case-->
                            ...
                        </rep1>
                        <rep1>
                            ....
                        </rep1>
                        <rep2_count/>
                        <rep2 jr:template=""><!-- NOTE: unchanged -->
                            ....
                        </rep2>
                        <rep2>
                           ...
                        </rep2>
                    
                        <rep3 jr:template=""><!-- NOTE: see body and bind, no additional node or calculation has to be created by pyxform for this case-->
                           ....
                        </rep3>
                        <rep3>
                           ...
                        </rep3>
                           ...
                      </group>
                </data>
            </instance>
            ....

            <bind calculate=" /data/count  + 2" nodeset="/data/group/rep2_count" readonly="true()" type="string"/>
            
             ....
        </model>
    </h:head>
    <h:body>
        <input ref="/data/count">
            <label>Enter count</label>
        </input>
        ....
            <repeat jr:count=" /data/count " nodeset="/data/rep1">
                 .....
            </repeat>
       .....
            <repeat jr:count=" /data/group/rep2_count " nodeset="/data/rep2">
                 .....
            </repeat>
        ....
            <repeat jr:count="4" nodeset="/data/rep3">
                .....
            </repeat>
    </h:body>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions