HCLS/ClinicalObservationsInteroperability/FHIR
FHIR as RDF
HL7 has garnered a lot of attention around a project called FHIR (Fast Healthcare Interoperability Resources). For instance, the US Integrated Program Office has selected FHIR as an exchange format between US DOD's AHLTA and the US Vererances Administration's VISTA EHR sysem¹. This task is to provide useful RDF representations of FHIR resources, with the goal that the Semantic Web advantages of simple, uniform representation and connectivity within a greater network are manifest in that RDF representation.
¹ HIT Standards Committee NwHIN Power Team Transport Standards for Consumer / Exchanges: Preliminary June 19, 2013
RDF representation of FHIR resoruces
Mapping
Given an XML representation of a FHIR resource, e.g.:
<DiagnosticReport xmlns="http://hl7.org/fhir"> <subject> <type value="Patient"/> <reference value="patient/@pat2"/> </subject> <diagnosticTime value="2011-03-04T08:30:00+11:00"/> <results> <name> <coding> <system value="http://loinc.org"/> <code value="15430-2"/> <display value="FULL BLOOD EXAMINATION"/> </coding> </name> <result> <type value="Observation"/> <reference value="#r1"/> </result> </results> </DiagnosticReport>
with some embedded or linked clinical observations:
<contained> <Observation id="r1"> <name> <coding> <system value="http://loinc.org"/> <code value="718-7"/> <display value="Haemoglobin"/> </coding> </name> <valueQuantity> <value value="176"/> <units value="g/L"/> <system value="http://unitsofmeasure.org"/> <code value="g/L"/> </valueQuantity> </Observation> </contained>
we represent the information in RDF as:
[] a fhir:DiagnosticReport; :subject [ a fhir:Reference; Reference:reference <patient/@pat2> ]; :results [ :results_name [ a fhir:Codeable; Codeable:coding [ a fhir:Coding; Coding:system [a fhir:Uri; fhir:value <http://loinc.org>]; Coding:code [a fhir:Code; fhir:value "15430-2"]; Coding:display [a fhir:String; fhir:value "FULL BLOOD EXAMINATION"]; ]; ]; :results_result [ a fhir:Reference; Reference:reference _:r1 ] ].
with corresponding clinical observations:
_:r1 a fhir:Observation; Observation:name [ a fhir:Coding; Coding:system [a fhir:Uri; fhir:value <http://loinc.org/>]; Coding:code [a fhir:Code; fhir:value "718-7"]; Coding:display [a fhir:String; fhir:value "Haemoglobin"] ]; Observation:valueQuantity [ a fhir:Quantity; Quantity:value [a fhir:Decimal; fhir:value "176"^^xsd:decimal]; Quantity:units [a fhir:String; fhir:value "g/L"]; Quantity:system [a fhir:Uri; fhir:value <http://unitsofmeasure.org>]; Quantity:code [a fhir:Code; fhir:value "g/L"] ].
fhir-rdf XSLT
- resource-specific XSLT
- generic transformer via python and XSLT pipeline (discussed)
Use
online
- use a generic XSLT service
- with the generated XSLT
- and some example instance data
- or hack the URL like http://services.w3.org/xslt?xslfile=https%3A%2F%2Fraw.githubusercontent.com%2Fw3c%2Fhcls-fhir-rdf%2Fmaster%2Fgeneric%2Ftransform.xsl&xmlfile=http%3A%2F%2Ffhir-dev.healthintersections.com.au%2Fopen%2FMedicationPrescription%2F124a6916-5d84-4b8c-b250-10cefb8e6e86&content-type=text%2Fplain&submit=transform
or use a specialized form
local
- download the XSLT and some example instance data, e.g. $(wget https://hl7-fhir.github.io/observation-example.xml)
- execute the XSLT via
- xsltproc (download or use a package manager to install libxml)
xsltproc --stringparam literals nest --stringparam contained ref --stringparam reference inline --stringparam docParam "http://some.example/server/path/" transform.xsl observation-example.xml
- saxon
@@fill in
- xsltproc (download or use a package manager to install libxml)
parameters
The parameter defaults should align with the current side-by-side proposal.
- docParam ./
- ./:
<./> a fhir:MedicationPrescription.
<./#med1> a fhir:Medication. - http://some.example/server/path/:
<http://some.example/server/path/> a fhir:MedicationPrescription.
<http://some.example/server/path/#med1> a fhir:Medication.
- contained ref|inline
- ref:
… fhir:contained <http://some.example/server/path/#med1>.
<http://some.example/server/path/#med1> a fhir:Medication;
fhir:Medication.id [ fhir:value "med1"^^fhir:id ];
fhir:Medication.name [ fhir:value "Theophylline 200mg" ];
fhir:Medication.code […]. - inline:
… fhir:contained [
a fhir:Medication;
fhir:Medication.id [ fhir:value "med1"^^fhir:id ];
fhir:Medication.name [ fhir:value "Theophylline 200mg" ];
fhir:Medication.code […];
];
- ref:
- reference ref|inline
- ref:
… fhir:MedicationPrescription.patient <http://fhir.healthintersections.com.au/open/Patient/d1>;
<http://fhir.healthintersections.com.au/open/Patient/d1> fhir:Reference.display [ fhir:value "Peter Patient" ] . - inline:
… fhir:MedicationPrescription.patient [
a fhir:Reference;
fhir:Reference.reference <http://fhir.healthintersections.com.au/open/Patient/d1>;
fhir:Reference.display [ fhir:value "Peter Patient" ]
]
- ref:
- literals nest|inline
- nest:
fhir:Reference.display [ fhir:value "Peter Patient" ]
- inline
fhir:Reference.display "Peter Patient"
- nest:
Development
- clone github repo
- cd generic
- $(make site) to download Josh Mandel's nightly FHIR build. This creates a directory site/ with files like allergyintolerance.profile.json
- $(make transform.xsl) creates a file transform.xsl which can be used to translate FHIR XML examples like allergyintolerance-example to XML.
- you will likely see that you need to install huTools:
- install pip (python's package manager); linux: $(sudo apt-get install python-pip), mac: ???, windows: ⸘⸮⁉
- install huTools: linux: $(sudo pip install huTools), mac: ???, windows: ⸘⸮⁉
- you will likely see that you need to install huTools:
- follow the instructions for runninng the XSLT locally
How it works
The process is driven by the Makefile.
- xslt_defs.xml: calls generate_xslt_defs.py to parse site/*.profile.xml and create monolithing XML resource definition xslt_defs.xml
- transform.xsl: concatonates a tiny top of an XSLT file head.xml with xslt_defs.xml and a more complex tail.xml to produce transform.xsl
tail.xml's match="/" calls the root templates which are either <xsl:template match="atom:feed" mode="root"> for packaging (needs to be updated to current encapsulation scheme) or or <xsl:template match="*" mode="root"> for everything else. The latter calls the workhorse ResourceRoot template which iteratively crawls through the FHIR Resource's XML matching it against elements in the tree from xslt_defs.xml. This includes a generic transformation for most properties and specific overrides:
- extensions (invocation in leaf, parent, renaming): align with Claude's model @@ref.
- contained
- datatypes, derive from FHIR defn
Issues
fhir:CodeableConcept.coding [ a fhir:Coding; fhir:Coding.system <http://snomed.info/sct>; fhir:Coding.code "66493003"^^fhir:code; ];
vs.
fhir:CodeableConcept.coding [ a fhir:Coding; fhir:Coding.system [ fhir:value <http://snomed.info/sct> ]; fhir:Coding.code [ fhir:value "66493003"^^fhir:code ]; ];
OWL representation of FHIR Schema
Tasks
- develop goal ontology
- reflect Resource properties in the derived ontology's shared properties
- capture the special rules in the XSLT footer in the ontology
- atom stuff: apparently obselete; need to track to current encapsulation scheme.
- extensions (invocation in leaf, parent, renaming): align with Claude's model @@ref.
- contained
- datatypes, derive from FHIR defn
- coding, per dbooth's JSON-LD work
{ :someNarrative Narrative:status fhir:generated . }
=
{ :someNarrative Narrative:status [ CodeableConcept:coding [ fhir:system fhir:sysID, Coding:code "generated" ] ] . }
- write code à la XML→Turtle XSLT generator to derive the goal ontology from schema steal Claude's code.