-
Notifications
You must be signed in to change notification settings - Fork 152
Description
ODK forum discussion · ODK forum discussion of XForms spec
The entities sheet MAY include multiple Entity declaration rows, provided that no two rows reference the same list_name.
Survey sheet save_to prefixes
If the entities sheet has more than one Entity declaration, then each save_to value on the survey sheet MUST be prefixed with a list_name followed by #, where the prefix matches a list_name in the entities sheet.
Example:
households#hhidparticipants#first_name
The string after # is the Entity property name.
See the XForms spec for rules and validation related to save_to.
Entity-level expressions and repeats
Entity-level expressions are expressions on the entities sheet, currently label, create_if, update_if, and entity_id.
If an Entity declaration's associated save_tos are in a repeat, Entity-level expressions MUST be evaluated by clients separately for each repeat instance (so generated XForms references must be relative).
Additionally, each node reference in an Entity-level expression MUST resolve to a single unambiguous node for each repeat instance. A node reference is valid only if
- The referenced node is within the repeat subtree, or
- The referenced node is outside the repeat subtree and is not contained within any repeat that is not an ancestor of the Entity declaration’s repeat.
In other words, the repeat-ancestor chain of the referenced node MUST be a prefix of the repeat-ancestor chain of the Entity declaration container.
If an Entity-level expression violates these constraints, the form is invalid.
Example
entities sheet for a form that creates Entities in the households and participants lists:
| list_name | label |
|---|---|
| households | ${hhid} |
| participants | concat(${first_name}, " ", ${last_name}, "(", ${hhid}, ")") |
survey sheet:
| type | name | label | save_to | calculation |
|---|---|---|---|---|
| text | hhid | Household ID | households#hhid | |
| geopoint | hh_location | Household location | households#geometry | |
| begin_repeat | member | Member | ||
| text | first_name | Member first name | participants#first_name | |
| text | last_name | Member last name | participants#last_name | |
| calculate | member_hh | participants#hhid | ${hhid} | |
| calculate | hh_link | participants#hh | ../meta/entity/@id | |
| end_repeat | member |
This example would result in a top-level Entity declaration to create Entities in the households list and an Entity declaration in the member repeat to create Entities in the participants list.
See #816 for proposed syntax to use instead of ../meta/entity/@id. pyxform will be deciding where to put the entity block so writing relative expressions will be hard.
Notes
This specification does not define automatic relationships between Entities declared in nested containers. Relationships, if required, MUST be expressed as normal entity properties (e.g. saving a parent entity ID into a child entity property).
An Entity property MAY be interpreted as a relationship by configuration.
The restriction that list_name values on the entities sheet must be unique exists to keep XLSForm authoring simple. Future versions of the XLSForm specification may introduce an additional identifier (e.g., entity_name) to allow multiple Entity declarations targeting the same Entity List within a single form. For now, users with this need can either have multiple forms (e.g. Register parent and Register child that both save to the people list) or multiple lists (e.g. parent and child lists).
Pyxform implementation notes
For each list_name declared on the entities sheet, pyxform MUST generate exactly one Entity declaration in the XForm.
pyxform MUST place the declaration at the container level that “covers” all of that list’s save_to fields, without crossing invalid repeat boundaries. Sometimes there will be multiple groups in the hierarchy in which pyxform could put the Entity declaration without violating XForms rules. Pyxform should put it somewhere deterministic (e.g. the highest or lowest possible).
Examples:
- If all
households#... fields are at the root,pyxformgenerates the households Entity declaration at the root. - If all
participants#...fields are inside a repeat/data/member,pyxformgenerates the participants Entity declaration inside that repeat. - If some
participants#...fields are inside a repeat and others are outside that repeat, the form is invalid (because there is no placement that satisfies XForms repeat scoping).
A form is invalid if any of the following are true:
- The entities sheet contains more than one row with the same list_name.
- The entities sheet contains more than one row and a save_to value is missing a list_name# prefix.
- A save_to prefix does not match any list_name declared on the entities sheet.
- For any given list_name, there does not exist a single container placement for that list’s Entity declaration that satisfies:
- the “nearest ancestor with an Entity declaration” association rule, and
- the repeat scoping rules from the XForms specification.