HL7 C-CDA to FHIR STU3 Conversion

This blog post describes the mapping specifications and conversion from HL7 C-CDA to FHIR STU3.

The HL7 organization released version 2 decades ago. This version 2.x is still being updated and improved and is implemented worldwide. HL7 Version 3 messaging has also been implemented internationally, but not in the U.S. CDA (Clinical Document Architecture) and Consolidated-Clinical Document Architecture (C-CDA), both XML-based, are widely adopted in the U.S. and are considered the most successful HL7 version 3 standard. FHIR specification is a next-generation standards framework, which combines the best features of all previous HL7’s releases, including v2, v3, and CDA product lines, to facilitate interoperation between various healthcare systems.

The C-CDA contains a library of CDA templates and prescribes their use for a set of specific document types. The templates are defined in three levels: document, section, and entry.

  • Document: The document level templates define the type of CDA document, such as CCD (Continuity of Care Document).
  • Section: The section level templates define how data within specific sections will be structured, such as vital signs.
  • Entry: Entry-level templates define how specific observations, procedures, etc., will be structured, making entries appear the same regardless what document or section they are a part of.

A C-CDA message starts with a “ClinicalDocument” node. Inside the node, it has series of elements, such as realmCode, title, effectiveDate, recordTarget, participant, component, etc. The “component” node carries most of the information that will be mapped to FHIR. A “component” node typically contains a “section” node. A “section” node consists of one or many “entry” nodes. An “entry” node may have an act, substanceAdministration” or a resource node, such as “encounter”. Below is a typical example of the “component” structure in C-CDA.

Template identifier (templateId) is used in each node to assert conformance to a collection of business rules which provide various levels of interoperability.

C-CDA/FHIR STU3 Mapping

Our web-based tool is developed based on two specifications.

  • Below is a table that shows the mapping between C-CDA and FHIR STU3. Another good reference for mapping specification can be found here.
    Top Level *Title2nd Level **3rd Level ***FHIR
    templateId = 2.16.840.1.113883 .10.20.22.2.6.1Allergies, Adverse, Reactions & AlertsAllergyIntolerance
    templateId = 2.16.840.1.113883 .10.20.22.4.30AllergyIntolerance. clinicalStatus
    templateId = 2.16.840.1.113883 .10.20.22.4.7AllergyIntolerance. reaction AllergyIntolerance. substance AllergyIntolerance. type = ‘Allergy’ AllergyIntolerance. category
    templateId = 2.16.840.1.113883 .10.20.22.4.8AllergyIntolerance. criticality
    templateId = 2.16.840.1.113883 .10.20.22.2.22EncountersEncounter
    templateId = 2.16.840.1.113883 .10.20.22.4.49Encounter.type Encounter.period
    templateId = 2.16.840.1.113883 .10.20.22.4.19Encounter.code Encounter.period
    templateId = 2.16.840.1.113883 .10.20.22.2.2ImmunizationsImmunization
    templateId = 2.16.840.1.113883 .10.20.22.4.52Immunization.status Immunization.date Immunization.route Immunization. vaccineCode Immunization. performer
    Practitioner Practitioner.address Practitioner.telecom Practitioner.name Practitioner. practitionerRole
    templateId = 2.16.840.1.113883 .10.20.22.1.1MedicationsMedication
    templateId = 2.16.840.1.113883 .10.20.22.4.16Medication.code
    templateId = 2.16.840.1.113883 .10.20.22.2.5.1ProblemsCondition
    templateId = 2.16.840.1.113883 .10.20.22.4.3Condition.code Condition. clinicalStatus Condition. onsetPeriod Condition.category
    templateId = 2.16.840.1.113883 .10.20.22.2.7ProceduresProcedure
    templateId = 2.16.840.1.113883 .10.20.22.4.13Procedure.code Procedure.status Procedure. performedDateTime
    templateId = 2.16.840.1.113883 .10.20.22.2.3ResultsObservation
    templateId = 2.16.840.1.113883 .10.20.22.4.2Observation.code Observation.status Observation. effectiveDateTime Observation. valueQuantity Observation. interpretation Observation. referenceRange
    templateId = 2.16.840.1.113883 .10.20.22.2.17Social HistoryObservation
    templateId = 2.16.840.1.113883 .10.20.22.4.78Observation. valueCodeableConcept
    templateId = 2.16.840.1.113883 .10.20.22.2.4Vital Signs
    templateId = 2.16.840.1.113883 .10.20.22.4.26
    templateId = 2.16.840.1.113883 .10.20.22.4.27Observation.code Observation.status Observation. effectiveDateTime Observation. valueQuantity
    templateId = 2.16.840.1.113883 .19.5.99999.2Provider OrganizationOrganization Organization.name Organization.telecom Organization.address

    Patient
    Patient.name
    Patient.address
    Patient.telecom
    Patient.gender
    Patient.birthDate
    Patient.maritalStatus
    Patient.contact
    Patient.communication

    Top Level *: ClinicalDocument.component.strurceBody.component.section or ClinicalDocument.recordTarget.patientRole
    2nd Level **:  Section.entry.act or Section.entry or Section.entry.substanceAdministration
    3rd Level ***: Act.entryRelationship or Entry.substanceAdministration
  • The following is the mapping specifications between a CDA (R2) message and the Patient resource using STU3. Note that the section number can be changed in a different release.
    FHIR Resource Mapping Specification Section in the URL
    Patient http://hl7.org/fhir/stu3/patient-mappings.html. 8.1.14.3

    Typically, when converting a C-CDA message to FHIR, the following FHIR resources may be generated:

    • Patient,
    • Observation
    • Practitioner
    • Organization
    • Condition
    • Medication
    • Procedure
    • MedicationRequest
    • MedicationAdministration
    • Encounter
    • AllergyIntolerance

Notes about the Conversion

1.     Use Composition to bundle resources

Once a CDA file is validated and converted successfully, the output JSON file is using the “Composition” to “bundle” various resources. In this example, Organization and AllergyIntolerance are bundled in the reference tag.

"resource": {
  "resourceType": "Composition",
  "id": "Composition/0",
  "section": [
    {
      "entry": [
        {
          "reference": "Organization/1"
        }
      ]
    },
    {
      "entry": [
        {
          "reference": "AllergyIntolerance/2"
        }
      ]
    },
    …

The reference tag, as shown in the above, contains a resource name and a sequence number, so that the reference will be unique. The “Organization/1” can then be found in the same JSON file, as follows:

 {
  "resource": {
    "resourceType": "Organization",
    "id": "Organization/1",
    "name": "Community Health and Hospitals",
    "telecom": [
      {
        "use": "work",
        "system": "phone",
        "value": " 555-555-5000"
      }
    ],
    "address": [
      {
        "line": [
          "1001 Village Avenue"
        ],
        "city": "Portland",
        "state": "OR",
        "postalCode": "99123",
        "country": "US"
      }
    ]
  },
  "request": {
    "method": "POST",
    "url": "Organization"
  }
}

2.     Use uuid for the patient id

The patient id is uniquely assigned using uuid. Following is an example of the Patient.id, highlighted in red color.

"resource": {
    "resourceType": "Patient",
    "id": "Patient/898688b8-014b-466a-9962-e1da96c1161d",
    "identifier": [
     {
        "system": "urn:oid:2.16.840.1.113883.3.6309.11",
        "value": "72929"
      }
     ],

For resources that refer to the Patient resource, it has the syntax like “Patient/uuid”. The following is an example of MedicationRequest that refers to the same patient, highlighted in red color.

"resource": {
    "resourceType": "MedicationRequest",
    "id": "MedicationRequest/4",
    
    "patient": {
      "reference": "Patient/898688b8-014b-466a-9962-e1da96c1161d"
     },

3.     Use the root id for the identifier value

The identifier in FHIR is mapped using the “root” attribute defined in the “id” tag in the CDA. In the following example, the templateId “2.16.840.1.113883.10.20.22.4.49” (encounter) has the following information:

<encounter classCode="ENC" moodCode="EVN">
   <templateId root="2.16.840.1.113883.10.20.22.4.49"/>
   <!-- Encounter activity template -->
   <id root="2a620155-9d11-439e-92b3-5d9815ff4de8"/>

The root value is mapped to the “identifier.value” in the Encounter resource:

"resource": {
    "resourceType": "Encounter",
    "id": "Encounter/5",
    "patient": {
      "reference": "Patient/8ee6b5c6-e280-4805-9869-b8d8fa7902eb"
    },
    "identifier": [
      {
        "value": "2a620155-9d11-439e-92b3-5d9815ff4de8"
      }
    ],

Web-based Tool

You can test the conversion tool online by going to Redix HIPAA Compliance and Conversions, and then enter your C-CDA file by pressing the “Select File” button.

After a file is selected, your file will be automatically converted to an FHIR message, providing the file is a valid HL7 C-CDA file. Once the file is converted, you will see two outputs:

  1. XSL View: This view is generated by using the cda.xsl (https://github.com/chb/sample_ccdas/blob/master/CDA.xsl).

  1. FHIR Output:

The output JSON file can be viewed in a tree:

 

After the conversion, you might want to upload the FHIR JSON message to your FHIR data server. The default FHIR data server is HAPI, http://fhirtest.uhn.ca/. You can press the button “Upload to FHIR Data Server” to upload your FHIR resources to the FHIR data server.

You can, of course, use your own FHIR data server. To do so, you will need to first signup and then define your data server as a default FHIR data server.

References

There are several good resources that you may be interested in this topic.