diff --git a/pyxform/constants.py b/pyxform/constants.py index 19c5c84a..6ab670eb 100644 --- a/pyxform/constants.py +++ b/pyxform/constants.py @@ -101,6 +101,10 @@ # The ODK XForms version that generated forms comply to CURRENT_XFORMS_VERSION = "1.0.0" +# The ODK entities spec version that generated forms comply to +CURRENT_ENTITIES_VERSION = "2022.1.0" +ENTITY_RELATED = "false" + DEPRECATED_DEVICE_ID_METADATA_FIELDS = ["subscriberid", "simserial"] AUDIO_QUALITY_VOICE_ONLY = "voice-only" diff --git a/pyxform/survey.py b/pyxform/survey.py index bee37241..bbbf26a6 100644 --- a/pyxform/survey.py +++ b/pyxform/survey.py @@ -173,6 +173,7 @@ class Survey(Section): "style": str, "attribute": dict, "namespaces": str, + constants.ENTITY_RELATED: str, } ) # yapf: disable @@ -204,7 +205,9 @@ def _validate_uniqueness_of_section_names(self): def get_nsmap(self): """Add additional namespaces""" - namespaces = getattr(self, constants.NAMESPACES, None) + namespaces = getattr(self, constants.NAMESPACES, "") + if getattr(self, constants.ENTITY_RELATED, "false") == "true": + namespaces += " entities=http://www.opendatakit.org/xforms/entities" if namespaces and isinstance(namespaces, str): nslist = [ @@ -550,6 +553,8 @@ def xml_model(self): self._add_empty_translations() model_kwargs = {"odk:xforms-version": constants.CURRENT_XFORMS_VERSION} + if getattr(self, constants.ENTITY_RELATED, "false") == "true": + model_kwargs["entities:entities-version"] = constants.CURRENT_ENTITIES_VERSION model_children = [] if self._translations: diff --git a/pyxform/xls2json.py b/pyxform/xls2json.py index cfb4eac2..5953b833 100644 --- a/pyxform/xls2json.py +++ b/pyxform/xls2json.py @@ -1429,6 +1429,7 @@ def workbook_to_json( entity_declaration = get_entity_declaration(workbook_dict) if len(entity_declaration) > 0: + json_dict[constants.ENTITY_RELATED] = "true" meta_children.append(entity_declaration) if len(meta_children) > 0: diff --git a/tests/test_entities.py b/tests/test_entities.py index 97f991cd..4d5e49a9 100644 --- a/tests/test_entities.py +++ b/tests/test_entities.py @@ -150,3 +150,53 @@ def test_entity_label__required(self): errored=True, error__contains=["The entities sheet is missing the required label column."], ) + + def test_dataset_in_entities_sheet__adds_entities_namespace(self): + self.assertPyxformXform( + name="data", + md=""" + | survey | | | | + | | type | name | label | + | | text | a | A | + | entities | | | | + | | dataset | label | | + | | trees | a | | + """, + xml__contains=["xmlns:entities=\"http://www.opendatakit.org/xforms/entities\""], + ) + + def test_entities_namespace__omitted_if_no_entities_sheet(self): + self.assertPyxformXform( + name="data", + md=""" + | survey | | | | + | | type | name | label | + | | text | a | A | + """, + xml__excludes=["xmlns:entities=\"http://www.opendatakit.org/xforms/entities\""], + ) + + def test_dataset_in_entities_sheet__adds_entities_version(self): + self.assertPyxformXform( + name="data", + md=""" + | survey | | | | + | | type | name | label | + | | text | a | A | + | entities | | | | + | | dataset | label | | + | | trees | a | | + """, + xml__xpath_match=['/h:html/h:head/x:model[@entities:entities-version = "2022.1.0"]'] + ) + + def test_entities_version__omitted_if_no_entities_sheet(self): + self.assertPyxformXform( + name="data", + md=""" + | survey | | | | + | | type | name | label | + | | text | a | A | + """, + xml__excludes=["entities:entities-version = \"2022.1.0\""], + ) \ No newline at end of file