POC - Mapping CDA to FHIR
0.1.0 - ci-build
POC - Mapping CDA to FHIR - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
| Official URL: https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/ImplementationGuide/ans.fhir.fr.mappingcdafhir | Version: 0.1.0 | |||
| Draft as of 2025-11-07 | Computable Name: CDA2FHIRMAP | |||
FHIR Mapping Language for CDA to FHIR transformation
Proof of concept for CDA to FHIR transformation
Cet Implementation Guide n'est pas la version courante, il s'agit de la version en intégration continue soumise à des changements fréquents uniquement destinée à suivre les travaux en cours. La version courante sera accessible via l'URL canonique suite à la première release : http://interop.esante.gouv.fr/ig/fhir/[code - ig]
Dans le cadre de l'Espace Européen des Données de Santé, l'ANS a entrepris des travaux pour anticiper la transition CDA vers FHIR dans le cadre des 5 cas d'usages priorisés par l'Europe : le compte rendu de biologie, la ePrescription et eDispensiation, le compte rendu d'hospitalisation, le résumé patient et le compte rendu d'imagerie.
Les travaux de l'ANS se distinguent en deux parties :
Ce guide vous permet de tester rapidement la transformation de documents CDA vers FHIR en utilisant matchbox et les exemples fournis.
docker pull europe-west6-docker.pkg.dev/ahdis-ch/ahdis/matchbox:v4.0.12
Important : Adaptez le chemin selon votre installation locale. Le chemin doit pointer vers le dossier input/with-all de votre projet.
docker run -d --name matchbox -p 8080:8080 \
-v /chemin/absolu/vers/IG-mapping-cda-fhir/input/with-all:/config \
europe-west6-docker.pkg.dev/ahdis-ch/ahdis/matchbox:v4.0.12
Ou utilisez le script de démarrage automatique :
./start-matchbox.sh
Pour suivre les logs de matchbox :
docker logs --follow matchbox
Attendez que matchbox ait terminé son démarrage. L'interface sera accessible sur : http://localhost:8080/matchbox
Certains StructureMaps utilisent des ConceptMaps externes pour la traduction de codes terminologiques. Il faut les charger avant les StructureMaps.
# Charger le ConceptMap pour le genre (administrative-gender)
curl -X POST http://localhost:8080/matchbox/fhir/ConceptMap \
-H "Content-Type: application/fhir+json" \
--data-binary @input/resources/ConceptMap-cm-v3-administrative-gender.json
Les fichiers HTTP de test se trouvent dans le dossier http-test/. Utilisez le fichier fr_cdatofhir_mde.http avec votre client REST.
Avec VS Code et l'extension REST Client :
http-test/fr_cdatofhir_mde.httpAvec curl (exemple complet) :
# 1. Charger les ConceptMaps nécessaires
curl -X POST http://localhost:8080/matchbox/fhir/ConceptMap \
-H "Content-Type: application/fhir+json" \
--data-binary @input/resources/ConceptMap-cm-v3-administrative-gender.json
# 2. Charger les StructureMaps dans l'ordre
curl -X POST http://localhost:8080/matchbox/fhir/StructureMap \
-H "Accept: application/fhir+xml;fhirVersion=4.0" \
-H "Content-Type: text/fhir-mapping" \
--data-binary @input/fml/CDAtoFHIRTypes.fml
curl -X POST http://localhost:8080/matchbox/fhir/StructureMap \
-H "Accept: application/fhir+xml;fhirVersion=4.0" \
-H "Content-Type: text/fhir-mapping" \
--data-binary @input/fml/CdaToBundle.fml
curl -X POST http://localhost:8080/matchbox/fhir/StructureMap \
-H "Accept: application/fhir+xml;fhirVersion=4.0" \
-H "Content-Type: text/fhir-mapping" \
--data-binary @input/fml/CDAFrToBundle.fml
curl -X POST http://localhost:8080/matchbox/fhir/StructureMap \
-H "Accept: application/fhir+xml;fhirVersion=4.0" \
-H "Content-Type: text/fhir-mapping" \
--data-binary @input/fml/CDAFrMDEToBundle.fml
# 3. Transformer un document CDA
curl -X POST "http://localhost:8080/matchbox/fhir/StructureMap/\$transform?source=https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaFrMDEToBundle" \
-H "Accept: application/fhir+json;fhirVersion=4.0" \
-H "Content-Type: application/fhir+xml;fhirVersion=4.0" \
--data-binary @input/attachments/CSE-MDE_2023.01.xml
Le dossier input/attachments/ contient un exemple de document CDA français :
Si la transformation réussit, vous obtiendrez un Bundle FHIR contenant les ressources converties depuis le document CDA.
Note importante : Il peut y avoir des erreurs dans les fichiers FML lors de la transformation. L'objectif de ce POC est de valider le processus de transformation. Les erreurs dans les mappings seront traitées ultérieurement.
Les transformations CDA-FHIR ont été exécutées avec les résultats suivants :
| Fichier source | StructureMap utilisé | Fichier résultat | Ressources FHIR | Observations | Statut |
|---|---|---|---|---|---|
| CSE-MDE_2023.01.xml | CdaFrMDEToBundle | Bundle-fe569e1f-32d4-4ba4-b5ad-88082bf5470a.json | 11 | 3 | ✅ Succès complet |
Détails de la transformation :
Document CSE-MDE (Carnet de Santé de l'Enfant - Mesures) :
CdaFrMDEToBundle - Mapping spécifique pour le contexte françaisCdaToFHIRTypes, CdaToBundle et CdaFrToBundleLe mapping CdaFrMDEToBundle.fml est un mapping spécialisé pour les documents CSE-MDE français qui combine :
Architecture du mapping :
CdaToFHIRTypes, CdaToBundle, CdaFrToBundle)Résultats obtenus :
organizer > component > observationExemple d'Observation générée :
{
"resourceType": "Observation",
"status": "final",
"category": [{
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs"
}]
}],
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "29463-7",
"display": "Poids"
}]
},
"subject": {
"reference": "urn:uuid:..."
},
"effectiveDateTime": "2023-01-06",
"valueQuantity": {
"value": 3900,
"unit": "g",
"system": "http://unitsofmeasure.org",
"code": "g"
}
}
Améliorations récentes apportées au mapping :
Observation.category : Toutes les observations sont catégorisées comme vital-signs conformément au package ANS ans.fhir.fr.mesures#3.1.0Observation.effectiveDateTime : Extrait depuis effectiveTime de l'observation CDA (si présent et non nullFlavor)Observation.status : Mapping de CDA "completed" vers FHIR "final"valueQuantity incluent system: "http://unitsofmeasure.org" et code en plus de unithttp://loinc.orgEncounter.status : Défini à finished pour les rencontres terminéesEncounter.class : Extrait du code CDA de la rencontrePatient.birthDate : Format date simple conforme FHIRComposition.confidentiality : Code simple au lieu d'objet complexeattester.time : Format dateTime conforme FHIRmeta.profile : Profils ANS ajoutés selon le code LOINC (mesures-fr-observation-body-weight, mesures-fr-observation-bodyheight, mesures-observation-head-circumference)Limitations identifiées dans les données CDA source :
Les exemples CDA fournis présentent certaines limitations qui génèrent des warnings FHIR (non bloquants) :
Encounter.period : Les dates/heures de la rencontre dans le CDA n'incluent pas de timezone
<!-- CDA source -->
<effectiveTime>
<low value="20250106111510"/> <!-- Pas de timezone +0100 -->
<high value="20250106113623"/> <!-- Pas de timezone +0100 -->
</effectiveTime>
Impact : Warning FHIR "If a date has a time, it must have a timezone"
Solution : Ajouter le timezone dans le CDA source (ex: 20250106111510+0100)
Observation.effectiveDateTime : Les observations CDA utilisent nullFlavor="NASK" (Not Asked)
<!-- CDA source -->
<observation>
<code code="29463-7" displayName="Poids" codeSystem="2.16.840.1.113883.6.1"/>
<effectiveTime nullFlavor="NASK"/> <!-- Pas de date effective -->
<value xsi:type="PQ" value="3900" unit="g"/>
</observation>
Impact : Warning FHIR "Best Practice Recommendation: In general, all observations should have an effective[x]"
Solution : Fournir une date/heure effective dans le CDA source (ex: <effectiveTime value="20230106"/>)
Note : Ces limitations proviennent des données CDA d'exemple et non du mapping FML. Le mapping transforme fidèlement les données CDA disponibles.
Le processus de transformation automatique CDA vers FHIR présente certaines difficultés inhérentes aux différences de modélisation entre les deux standards :
Problème identifié : healthCareFacility et serviceProviderOrganization
Dans le CDA, la structure componentOf > encompassingEncounter > location > healthCareFacility contient :
code décrivant le type d'établissement (ex: SA05 "Centre de santé" du TRE_R02-SecteurActivite)location (lieu physique avec adresse)serviceProviderOrganization (organisation gestionnaire)Difficulté de mapping :
Le code SA05 du healthCareFacility devrait logiquement être mappé vers :
Location.type - pour indiquer le type de lieu physiqueOrganization.type:secteurActiviteRASS - pour indiquer le secteur d'activité de l'organisationCependant, il existe une ambiguïté sémantique :
serviceProviderOrganization dans le CDA peut représenter :
Impact :
healthCareFacility vers l'Organization peut introduire des incohérences sémantiquesSolutions possibles :
Location.type (approche actuelle)Organization.type en documentant l'hypothèse que le serviceProviderOrganization est l'établissement lui-mêmeCette difficulté illustre que le mapping CDA-FHIR n'est pas toujours une transformation mécanique 1:1, mais nécessite parfois des choix d'implémentation basés sur la compréhension du contexte métier.
Pour arrêter le conteneur :
docker stop matchbox
Pour redémarrer :
docker start matchbox
Pour supprimer le conteneur (et repartir de zéro) :
docker rm -f matchbox
Le fichier input/with-all/application.yaml configure matchbox avec :
Pour modifier la configuration, éditez application.yaml puis supprimez et recréez le conteneur Docker.
| Role | Nom | Organisation | Contact |
|---|---|---|---|
| Primary Editor | Prenom Nom | Agence du Numérique en Santé | prenom.nom@address.email |
Merci à Oliver Egger (Ahdis, HL7 Suisse) qui a travaillé sur la première brique sur laquelle repose ces travaux et sur l'outil matchbox permettant d'effectuer la transformation.
https://github.com/hl7ch/cda-fhir-maps
Package hl7.fhir.uv.extensions.r4#5.2.0 This IG defines the global extensions - the ones defined for everyone. These extensions are always in scope wherever FHIR is being used (built Mon, Feb 10, 2025 21:45+1100+11:00) |
Package hl7.fhir.uv.extensions.r5#5.1.0 This IG defines the global extensions - the ones defined for everyone. These extensions are always in scope wherever FHIR is being used (built Sat, Apr 27, 2024 18:39+1000+10:00) |
Package hl7.fhir.uv.extensions.r4#1.0.0 This IG defines the global extensions - the ones defined for everyone. These extensions are always in scope wherever FHIR is being used (built Sun, Mar 26, 2023 08:46+1100+11:00) |
Package ans.fr.nos#1.3.0 Les nomenclatures des objets de Sante (built Thu, Aug 29, 2024 14:54+0000+00:00) |
Package ans.fr.nos#1.5.0 Les nomenclatures des objets de Sante (built Tue, Feb 11, 2025 10:50+0000+00:00) |
Package ans.fhir.fr.annuaire#1.1.0 Ressources de conformité basées sur le modèle d'exposition de l'Annuaire Santé. (built Mon, Apr 14, 2025 13:04+0000+00:00) |
Package hl7.fhir.fr.core#1.1.0 The FR Core Implementation Guide is based on FHIR Version R4 and defines the minimum set of constraints on the FHIR resources to create the FR Core Profiles. It also defines the minimum set of FHIR RESTful interactions for each of the FR Core Profiles to access patient data. By establishing the “floor” of standards to promote interoperability and adoption through common implementation, it allows for further standards development evolution for specific uses cases. |
Package hl7.fhir.uv.tools.r4#0.8.0 This IG defines the extensions that the tools use internally. Some of these extensions are content that are being evaluated for elevation into the main spec, and others are tooling concerns (built Tue, Aug 5, 2025 20:09+1000+10:00) |
Certaines ressources sémantiques de ce guide sont protégées par des droits de propriété intellectuelle couverte par les déclarations ci-dessous. L’utilisation de ces ressources est soumise à l’acceptation et au respect des conditions précisées dans la licence d’utilisation de chacune d’entre elle.