diff --git a/cdisc_rules_engine/services/define_xml/define_xml_reader_2_0.py b/cdisc_rules_engine/services/define_xml/define_xml_reader_2_0.py index 080db2721..855473092 100644 --- a/cdisc_rules_engine/services/define_xml/define_xml_reader_2_0.py +++ b/cdisc_rules_engine/services/define_xml/define_xml_reader_2_0.py @@ -27,6 +27,8 @@ def _get_metadata_representation(self, metadata) -> dict: """ Returns metadata as dictionary. """ + has_no_data: str | None = getattr(metadata, "HasNoData", "") + has_no_data = has_no_data or "" return { "define_dataset_name": metadata.Name, "define_dataset_label": str(metadata.Description.TranslatedText[0]), @@ -36,6 +38,7 @@ def _get_metadata_representation(self, metadata) -> dict: "define_dataset_structure": str(metadata.Structure), # v2.0 does not support is_non_standard. Default to blank "define_dataset_is_non_standard": "", + "define_dataset_has_no_data": bool(has_no_data.lower() == "yes"), } def get_extensible_codelist_mappings(self): diff --git a/cdisc_rules_engine/services/define_xml/define_xml_reader_2_1.py b/cdisc_rules_engine/services/define_xml/define_xml_reader_2_1.py index 0e0a86be6..ddeac21df 100644 --- a/cdisc_rules_engine/services/define_xml/define_xml_reader_2_1.py +++ b/cdisc_rules_engine/services/define_xml/define_xml_reader_2_1.py @@ -30,6 +30,8 @@ def _get_metadata_representation(self, metadata) -> dict: """ Returns metadata as dictionary. """ + has_no_data: str | None = getattr(metadata, "HasNoData", "") + has_no_data = has_no_data or "" return { "define_dataset_name": metadata.Name, "define_dataset_label": str(metadata.Description.TranslatedText[0]), @@ -38,6 +40,7 @@ def _get_metadata_representation(self, metadata) -> dict: "define_dataset_class": str(metadata.Class.Name), "define_dataset_structure": str(metadata.Structure), "define_dataset_is_non_standard": str(metadata.IsNonStandard or ""), + "define_dataset_has_no_data": bool(has_no_data.lower() == "yes"), } def get_ct_version(self): diff --git a/tests/unit/test_define_xml_reader.py b/tests/unit/test_define_xml_reader.py index 7a9fbbee7..bf7b16516 100644 --- a/tests/unit/test_define_xml_reader.py +++ b/tests/unit/test_define_xml_reader.py @@ -74,6 +74,7 @@ def test_read_define_xml(): "define_dataset_class", "define_dataset_structure", "define_dataset_is_non_standard", + "define_dataset_has_no_data", ] @@ -110,6 +111,44 @@ def test_extract_domain_metadata(filename): "TSVCDVER", ], "define_dataset_key_sequence": ["STUDYID", "TSPARMCD", "TSVAL", "TSSEQ"], + "define_dataset_has_no_data": False, + } + + +@pytest.mark.parametrize( + "filename", [(test_define_file_path), (test_define_2_0_file_path)] +) +def test_extract_dataset_metadata(filename): + """ + Unit test for DefineXMLReader.extract_dataset_metadata for TS dataset. + """ + with open(filename, "rb") as file: + contents: bytes = file.read() + reader = DefineXMLReaderFactory.from_file_contents(contents) + dataset_metadata: dict = reader.extract_dataset_metadata(dataset_name="TS") + assert dataset_metadata == { + "define_dataset_name": "TS", + "define_dataset_label": "Trial Summary", + "define_dataset_location": "ts.xml", + "define_dataset_domain": "TS", + "define_dataset_class": "TRIAL DESIGN", + "define_dataset_structure": "One record per trial summary parameter value", + "define_dataset_is_non_standard": "", + "define_dataset_variables": [ + "STUDYID", + "DOMAIN", + "TSSEQ", + "TSGRPID", + "TSPARMCD", + "TSPARM", + "TSVAL", + "TSVALNF", + "TSVALCD", + "TSVCDREF", + "TSVCDVER", + ], + "define_dataset_key_sequence": ["STUDYID", "TSPARMCD", "TSVAL", "TSSEQ"], + "define_dataset_has_no_data": False, } @@ -370,3 +409,28 @@ def test_read_dictionary_version(dictionary_type, expected_version): reader = DefineXMLReaderFactory.from_file_contents(contents) version = reader.get_external_dictionary_version(dictionary_type) assert version == expected_version + + +@pytest.mark.parametrize( + "filename,has_no_data", + [ + ( + test_define_file_path, + True, + ), # NV domain in test_defineV22-SDTM.xml has def:HasNoData="Yes" + ], +) +def test_extract_domain_metadata_nv_has_no_data(filename, has_no_data): + """ + Unit test for DefineXMLReader.extract_domain_metadata for NV domain with has_no_data. + """ + with open(filename, "rb") as file: + contents: bytes = file.read() + reader = DefineXMLReaderFactory.from_file_contents(contents) + domain_metadata: dict = reader.extract_domain_metadata(domain_name="NV") + assert domain_metadata["define_dataset_has_no_data"] == has_no_data + assert domain_metadata["define_dataset_name"] == "NV" + assert domain_metadata["define_dataset_domain"] == "NV" + # Check that at least one expected variable is present + for v in ["NVSEQ", "NVTESTCD", "NVTEST"]: + assert v in domain_metadata["define_dataset_variables"]