ODK XForms spec proposal: create and update Entities from repeats

See Create Entities from repeats for the user-facing functionality and proposed XLSForm spec.

The concept

We propose adding a well-known meta block to repeats that can include an inner entity block. This would match the top-level meta/entity block described in the Entities spec.

With this addition, saveto attributes could be declared within a repeat if that repeat has a corresponding meta/entity block.

See below for an example of a form that creates one Entity for each instance of the tree repeat that matches the create condition. Entity updates could also be specified in the meta/entity block for a repeat using the update attribute and other attributes specified by the spec.

<?xml version="1.0"?>
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:entities="http://www.opendatakit.org/xforms/entities" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa" xmlns:odk="http://www.opendatakit.org/xforms" xmlns:orx="http://openrosa.org/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <h:head>
   <h:title>Register many trees</h:title>
   <model odk:xforms-version="1.0.0" entities:entities-version="2025.1.0">
     <instance>
       <data id="trees_registration" version="2025040701">
         <tree>
           <location />
           <species />
           <meta>
             <entity dataset="trees" create_if="" id="">
               <label />
             </entity>
           </meta>
         </tree>
        
         <meta>
           <instanceID/>
         </meta>
       </data>
     </instance>
     <bind nodeset="/data/tree/location" type="geopoint" entities:saveto="geometry" />
     <bind nodeset="/data/tree/species" type="string" entities:saveto="species" />


     <bind nodeset="/data/tree/meta/entity/@id" type="string"/>
     <setvalue event="odk-instance-first-load odk-new-repeat" ref="/data/tree/meta/entity/@id" value="uuid()"/>


     <bind nodeset="/data/tree/meta/entity/@create_if" type="string" calculate="starts-with(../../../species, 'B')" />
    
     <bind nodeset="/data/tree/meta/entity/label" calculate="../../../species"  type="string"/>


     <bind jr:preload="uid" nodeset="/data/meta/instanceID" readonly="true()" type="string"/>
   </model>
 </h:head>
 <body>
   <group ref="/data/tree">
     <label>Tree</label>
     <repeat nodeset="/data/tree">
       <input ref="/data/tree/location">
           <label>Tree location</label>
       </input>
       <input ref="/data/tree/species">
           <label>Tree species</label>
       </input>
     </repeat>
   </group>
 </body>
</h:html>