From 79579ec82a027dd00c3e870f30547dc331ec5cd6 Mon Sep 17 00:00:00 2001 From: mandalkam Date: Mon, 18 May 2026 15:28:52 +0200 Subject: [PATCH] Support alternate validator / newer validation result property names and do additional aggregations --- home/fhirvalidation.py | 71 +++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/home/fhirvalidation.py b/home/fhirvalidation.py index 5898b9c..96585aa 100644 --- a/home/fhirvalidation.py +++ b/home/fhirvalidation.py @@ -29,7 +29,8 @@ class Validator(): def fhir_operation_validate(self, resource_type, resource, send_pretty=False): headers = {'User-Agent': 'Bulk FHIR validator', - 'Content-Type': 'application/fhir+json'} + 'Content-Type': 'application/fhir+json', + 'Accept': 'application/fhir+json'} if send_pretty: data = json.dumps(resource, indent=4) @@ -55,14 +56,21 @@ class Validator(): df = pd.DataFrame() for issue in outcome.get('issue'): - diagnostics = issue.get('diagnostics') + diagnostics = issue.get('details').get('text') + if not diagnostics: + # fallback to (old?) HAPI validator properties + diagnostics = issue.get('diagnostics') diagnostics_aggregated = remove_value_code(diagnostics) diagnostics_aggregated = remove_array_index(diagnostics_aggregated) severity = issue.get('severity') - location = issue.get('location') + location = issue.get('expression') + if not location: + # fallback to (old?) HAPI validator properties + location = issue.get('location') + location = location[0] location_aggregated = remove_array_index(location) @@ -188,18 +196,45 @@ def get_next_page_url(bundle_dict): def remove_value_code(diagnostics): - find_value_code = re.search(r"Coding provided \(.+?\#(.+?)\) is not in the value set", diagnostics) - if not find_value_code: - find_value_code = re.search(r"Unknown code in fragment CodeSystem \'.+?\#(.+?)\'", diagnostics) + find_value_code = re.search(r"Coding provided \(.+?\#(.+?)\)", diagnostics) if find_value_code: value_code = find_value_code.groups()[0] - diagnostics_removed_valuecode = diagnostics.replace(value_code, "REMOVEDCODE") - else: - diagnostics_removed_valuecode = diagnostics + diagnostics = diagnostics.replace(value_code, "REMOVEDCODE") - return diagnostics_removed_valuecode + find_value_code = re.search(r"code provided \(.+?\#(.+?)\) was not found", diagnostics) + if find_value_code: + value_code = find_value_code.groups()[0] + diagnostics = diagnostics.replace(value_code, "REMOVEDCODE") + + find_value_code = re.search(r"Unknown code in fragment CodeSystem \'.+?\#(.+?)\'", diagnostics) + if find_value_code: + value_code = find_value_code.groups()[0] + diagnostics = diagnostics.replace(value_code, "REMOVEDCODE") + + find_value_code = re.search(r"code \`(.+?)\` was not found in the code system", diagnostics) + if find_value_code: + value_code = find_value_code.groups()[0] + diagnostics = diagnostics.replace(value_code, "REMOVEDCODE") + + find_value_code = re.search(r"Invalid display \`(.+?)\` for code \`.+?\#(.+?)\`. A valid display is \`(.+?)\`", diagnostics) + if find_value_code: + value_display = find_value_code.groups()[0] + value_code = find_value_code.groups()[1] + valid_display = find_value_code.groups()[2] + diagnostics = diagnostics.replace(value_code, "REMOVEDCODE") + diagnostics = diagnostics.replace(value_display, "REMOVEDDISPLAY") + diagnostics = diagnostics.replace(valid_display, "REMOVEDVALIDDISPLAY") + + find_value_code = re.search(r"Invalid display \`(.+?)\` for code \`.+?\#(.+?)\`", diagnostics) + if find_value_code: + value_display = find_value_code.groups()[0] + value_code = find_value_code.groups()[1] + diagnostics = diagnostics.replace(value_code, "REMOVEDCODE") + diagnostics = diagnostics.replace(value_display, "REMOVEDDISPLAY") + + return diagnostics def remove_array_index(diagnostics): @@ -256,7 +291,13 @@ def render_validation_outcome(resource, outcome, resource_url=None, do_print_lin summary_html = '' for issue in issues_sorted: - location_element = issue['location'][0] + + location_element = issue.get('expression') + + if not location_element: + # Fallback to old(?) HAPI validator properties + location_element = issue['location'][0] + location_line = select_location_line(issue) match issue['severity']: @@ -285,8 +326,14 @@ def render_validation_outcome(resource, outcome, resource_url=None, do_print_lin issue_html += '
' + + diagnostics = issue.get('details').get('text') + if not diagnostics: + # fallback to (old?) HAPI validator properties + diagnostics = issue.get('diagnostics') + issue_html += f'{issue["severity"]} for element {location_element} (beginning at line ' + str( - location_line) + f'):
{issue["diagnostics"]}' + location_line) + f'):
{diagnostics}' issue_html += ''