Release 5 Draft Ballot

 

 

This document is stages contents for the FHIR Resource Description Framework (RDF) Representation page. Formatting issues related to headers and style will be resolved when the content is transfered.

This page and the RDF forms are jointly maintained by the HL7 FHIR project -- especially the RDF subgroup of the ITS work group -- and the W3C Semantic Web Health Care and Life Sciences Interest Group .

@@ TODO: Add Maturity: FMM 2 Standards Status: Trial Use @@

Resource Description Framework (RDF) Representation

FHIR resources can be represented as an RDF graph serialized in the Turtle format . The RDF format is defined to assist the process of bridging between operational data exchange and formal knowledge processing systems. While the RDF form offers a fully functional representation of FHIR resources, it has different operational characteristics from the JSON and XML representations, and would be used for different reasons. Systems focused on operational exchange of data would not generally choose to use RDF.

This page describes:

@@ TODO 1: Mark the FHIR Ontology draft on W3C github document as obsolete and point it to to generated FHIR RDF vocabulary/ontology @@

Turtle Template for Resources

Each resource page has a set of language templates describing the expression FHIR in that language. The Turtle representation for a resource is described using this convention:

Turtle Template

[ a fhir:Observation; fhir:nodeRole fhir:treeRoot;
  # from Resource: id; meta; implicitRules; and language
  # from DomainResource: text; contained; extension; and modifierExtension
  fhir:Obervation.identifier [ Identifier ]; # 0..* Unique Id for this particular observation
  fhir:Obervation.status [ fhir:v "<code>" ]; # R!  registered | preliminary | final | amended +
  fhir:Obervation.code [ CodeableConcept ]; # 1..1 R!  Type of observation (code / type)
  fhir:Obervation.subject [ fhir:reference [ Patient|Group|Device|Location ] ]; # 0..1 Who and/or what this is about
  fhir:Obervation.encounter [ fhir:reference [ Encounter ] ]; # 0..1 Healthcare event during which this observation is made
  # effective[x]: 0..1 Clinically relevant time/time-period for observation. One of these 2:
    fhir:Obervation.effectiveDateTime [ fhir:v "<dateTime>" ];
    fhir:Obervation.effectivePeriod [ Period ];
]

Using this format:

FHIR RDF Example

An example FHIR RDF Observation illustrates the Turtle language and the additional conventions used by FHIR RDF:

PREFIX fhir: <http://hl7.org/fhir/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

                                  # Obs123 (subject) hasType (predicate) fhir:Observation
<http://hl7.org/fhir/Observation/Obs123> a fhir:Observation;
  fhir:nodeRole fhir:treeRoot;    # (subject) is the serialization root of this document
  fhir:status [ fhir:v "final" ]; # (subject) has an (extensible) status of "final"
  fhir:code [                     # (subject) as a code
    fhir:coding (                 #  which has codings
      [                           #   with a system, code and concept identifier
        a <http://loinc.org/rdf#29463-7>
        fhir:system [
          fhir:v "http://loinc.org"^^xsd:anyURI
        ];
        fhir:code [ fhir:v "29463-7" ]
      ]
      [                           #  and another with a display
        a <http://loinc.org/rdf#3141-9>
        fhir:system [
          fhir:v "http://loinc.org"^^xsd:anyURI
        ];
        fhir:code [ fhir:v "3141-9" ];
        fhir:display [ fhir:v "Body weight Measured" ]
      ]
    )
  ];
  fhir:value [                    # the value is an anonymous node
    a fhir:Quantity;              #   which has a type (Quantity), and 21090 parts.
    fhir:value [ fhir:v "185"^^xsd:decimal ];
    fhir:unit [ fhir:v "lbs" ];
    fhir:system [
      fhir:v "http://unitsofmeasure.org"^^xsd:anyURI
    ];
    fhir:code [ fhir:v "[lb_av]" ]
  ].

                                  # Metadata about OWL interpretation
<http://hl7.org/fhir/Observation/Obs123.ttl> a owl:Ontology;
  owl:imports fhir:fhir.ttl;
  owl:versionIRI <http://hl7.org/fhir/Observation/Obs123.ttl>.

In this example,

FHIR RDF Serialization Conventions

FHIR RDF imposes additional conventions to simplify recognition and manipulation of FHIR RDF graphs.  Although RDF graphs in general may be serialized in various RDF formats, FHIR RDF mandates support specifically for Turtle. All FHIR RDF documentation is expressed in Turtle.   And while the standard media type for Turtle is text/turtle, the use of Turtle for FHIR RDF uses the specialized media type application/fhir+turtle.

FHIR uses Shape Expressions (ShEx) to define and validate FHIR RDF. See fhir.shex for the complete FHIR RDF schema. Each Resource page includes a link for the subset of fhir.shex needed to describe that Resource. The media type for ShEx is text/shex.

Representing Resources

Each resource is represented as a set of RDF triples. When a resource has a persistent identity (e.g. it can be found at a particular URL - usually a FHIR RESTful server), then that URL is its identity. Resources with no persistent identity (e.g. bundles from search results) have the identity of the root document - "<>" in Turtle syntax. In the above example, the resource is the subject: <http://hl7.org/fhir/Observation/Obs123>.

Some resources can contain other resources. Given that the relationships can appear in any order in RDF, it cannot be assumed that the first encountered element represents the resource of interest that is being represented by the set of Turtle statements. The focal resource - where to start when parsing - is the resource with the relationship fhir:nodeRole to fhir:treeRoot. If there is more than one node labeled as a 'treeRoot' in a set of Turtle statements, it cannot be determined how to parse them as a single resource.

Case Sensitivity

While RDF predicate names are case-sensitive, FHIR avoids confusion by assuring that there are no predicates that differ only in case. For example, there will be no fhir:Code predicate because there is already a fhir:code predicate.

Nested Anonymous Nodes

Content within a resource is always represented with anonymous nodes (a/k/a "blank nodes").  Only FHIR Resource nodes can be IRIs. For example, <…/Obs123> fhir:status [ fhir:v "final" ] asserts that:

  • <…/Obs123> has a status of some anonymous node.
  • That anonymous node has a fhir:v of "final" (the literal "final").

Property Names

A great deal of effort has gone into unifying FHIR property names across resources and datatypes. These defined properties effectively declare the FHIR RDF namespace with a set of polymorphic, reuseable predicates. For example, fhir:status is spelled the same way regardless of whether it appears in an Observation, Diagnosis, or any other FHIR Resource.

In other formats (XML, JSON), FHIR properties with choice datatypes, like value[x], are appended with the datatype, e.g. valueQuantity. In RDF, this is written fhir:value and the object asserts its type, as in the above example:

  fhir:value [ a fhir:Quantity; … ]

Representing Repeating Elements

Elements that can repeat are represented with RDF lists (officially called "RDF collections") in order to retain the order of their elements.

(elt1 elt2 …)

which produces an RDF list structure the the elements elt1 and elt2. In the above example, the fhir:code has a fhir:coding with two members:

    fhir:coding (
      [ a <http://loinc.org/rdf#29463-7> … ]
      [ a <http://loinc.org/rdf#3141-9> … ]
    )

A script (TODO: write said script) can convert lists to OLO-style lists.

Representing Primitive Elements

Primitive elements - elements with a primitive type - are represented as regular (anonymous) nodes so that the element extensions can be represented.  The actual value of the primitive type is represented as an RDF Literal using the fhir:v predicate.  fhir:v is the only FHIR property that directly holds an RDF literal, and it always holds an RDF Literal:

  fhir:v "[value]"^^xs:type

The value has two parts: a literal string that contains the value, and, if applicable, one of the following schema types:

  • boolean
  • integer
  • decimal
  • base64Binary
  • dateTime
  • date
  • gYear
  • gYearMonth
  • time

In the above example, the Quantity has a fhir:value which is an anonymous node with a fhir:v in it:

[ fhir:v "185"^^xsd:decimal ]

Note that the correct XSD type for a FHIR decimal, date, or dateTime must be determined by inspecting the value of the date for conformance with one of the union types for that type. In the case of FHIR decimal, which is a union of XSD decimal and double, any value with an 'e' or 'E' in it is a double, otherwise it is a decimal. For example, the lexical value "185" is given the datatype xsd:decimal.

The fhir:v property can never be empty. Either the relationship is absent, or it is present with at least one character of content. XHTML is represented as an escaped xs:string.  @@ TODO 4: Which XSD prefix should we use?  xs: or xsd: ? We should be consistent.  The rest of the FHIR spec seems to use an xs: prefix.  -- YES, CHANGE TO xs: @@

Representing References

A Reference element is represented using the same rules as above:

 fhir:Observation.subjectReference [
     fhir:Reference.reference [ fhir:v "Patient/example" ];
     fhir:Reference.display [ fhir:v "Example Patient" ];
  ];

This allows faithful round tripping of the resource between the Turtle format and the JSON and XML formats. However, it's very useful for an RDF processor if the RDF graph links to the target of the reference directly. This can be represented using the (optional) fhir:link property:

 fhir:Observation.subjectReference [
     fhir:link <http://hl7.org/fhir/Patient/example>
     fhir:Reference.reference [ fhir:v "Patient/example" ]
  ];

The correct value for the fhir:link relationship must be determined by resolving the rules for resolving references for the various reference types to a literal URL that refers to the correct content in the local RDF context.

The fhir:link relationship can be added automatically as part of generating the resource representation, or it can be injected by a post-processor that knows how to convert the raw references into RDF-suitable references.

Representing Inline Resources

Inline resources - when a resource is contained directly in another element occur in the following places:

Inline resources are represented directly as anonymous nodes. This is an example for a contained Medication resource:

  fhir:DomainResource.contained ([
     a fhir:Medication;
     # triples for the Medication
  ])

Note that DomainResource.contained has a cardinality of 0..*, so an RDF List is used to order the array.

Modifier Extensions

A Resource may have any number of non-modifier extensions:

<http://hl7.org/fhir/MedicationRequest/MR321> a fhir:Observation;
  fhir:nodeRole fhir:treeRoot;
  fhir:extension (
    [ fhir:url "http://hl7.org/fhir/StructureDefinition/observation-bodyPosition"^^xsd:anyURI;  @@ TODO 5: Should this use a bnode and fhir:v?  
If not, how will readers know which FHIR properties have direct scalar values and which use a bnode with fhir:v? And how would it be extended?
https://build.fhir.org/datatypes.html says "All data types (including primitives) may have extensions". @@ fhir:value [ fhir:coding ( a sct:33586001; fhir:system [ fhir:v "http://snomed.info/sct" ]; fhir:code [ fhir:v "33586001" ]; fhir:display [ fhir:v "Sitting position (finding)" ] ) ] ]
[ fhir:url "http://hl7.org/fhir/StructureDefinition/observation-delta"^^xsd:anyURI; fhir:value [ fhir:coding ( a sct:1250004; fhir:system [ fhir:v "http://snomed.info/sct" ]; fhir:code [ fhir:v "1250004" ]; fhir:display [ fhir:v "Decreased (qualifier value)" ] ) ] ] ) …

FHIR allows modifierExtensions on DomainResources, BackboneElements and BackboneTypes. The type of any DomainResource with any modifierExtension is prefixed with '_' in RDF:

<http://hl7.org/fhir/MedicationRequest/MR321> a fhir:_MedicationRequest;
  fhir:nodeRole fhir:treeRoot;
  fhir:extension ( … );           # above bodyPosition and delta extensions
  fhir:modifierExtension (
    [
      fhir:url [ fhir:v "http://example.org/fhir/StructureDefinition/anti-prescription"^^xsd:anyURI ] ;
      fhir:value [ a fhir:boolean ; fhir:v true
    ]
  )

BackboneElements and BackboneTypes are object types. Any RDF predicate which references a modified BackboneElement or BackboneType is prefixed with a '_'.

<http://hl7.org/fhir/Observation/Obs123> a fhir:Observation;
  …
  fhir:_value [
    a fhir:Quantity;
    fhir:value [ fhir:v "185"^^xsd:decimal ];
    fhir:unit [ fhir:v "lbs" ];
    fhir:system [
      fhir:v "http://unitsofmeasure.org"^^xsd:anyURI
    ];
    fhir:code [ fhir:v "[lb_av]" ];
    fhir:modifierExtension ([
      fhir:url [ fhir:v "http://example.org/fhir/StructureDefinition/anti-observation"^^xsd:anyURI ] ;
      fhir:value [ a fhir:Code ; fhir:v "draft" ] ;  @@ TODO 8: Verify this example. @@
    ]);
  ]
The '_' prefix helps prevent FHIR RDF processors that do not understand a particular modifier extension from blindly processing it as though it still had the original semantics.  However, the structure of the element is otherwise unchanged.

Representing Concepts

The same logic applies to the Coding data type. These are represented directly in Turtle by serializing their properties as specified above:

fhir:Observation.code [
    fhir:CodeableConcept.coding (
        [
            fhir:Coding.system [ fhir:v "http://loinc.org" ];
            fhir:Coding.code [ fhir:v "29463-7" ];
            fhir:Coding.display [ fhir:v "Body Weight" ]
        ]
        [
            fhir:Coding.system [ fhir:v "http://snomed.info/sct" ];
            fhir:Coding.code [ fhir:v "27113001" ];
            fhir:Coding.display [ fhir:v "Body weight" ]
        ]
    )
];

For reasoners using the RDF graph, it's very useful to make the implicit concept references in these Codings explicit, by specifying a concept IRI in an (optional) rdf:type assertion, written as a in Turtle:

fhir:Observation.code [
    fhir:CodeableConcept.coding (
        [
            a loinc:29463-7;
            fhir:Coding.system [ fhir:v "http://loinc.org" ];
            fhir:Coding.code [ fhir:v "29463-7" ];
            fhir:Coding.display [ fhir:v "Body Weight" ]
        ]
        [
            a sct:27113001;
            fhir:Coding.system [ fhir:v "http://snomed.info/sct" ];
            fhir:Coding.code [ fhir:v "27113001" ];
            fhir:Coding.display [ fhir:v "Body weight" ]
        ]
    )
];

A concept IRI typically has two parts: an IRI stem and a code.  An IRI stem is the initial substring, of an IRI, that is used to create concept IRIs for codes in a particular vocabulary.  The IRI stem normally corresponds directly to an IRI prefix in Turtle, such as loinc: or sct: in the above example.  The concept IRI for a given <Coding.system, Coding.code> pair is typically formed by: 1. looking up the appropriate IRI stem corresponding to the Coding.system; 2. concatenating the IRI stem with the percent encoded Coding.code .  If an IRI stem for the Coding.system is published at https://terminology.hl7.org/ it SHOULD be used.  An NPM package is available for automated lookup.

@@ TODO 9: Should we include the Concept IRI algorithm here?  Or reference the google doc proposal? AGREED: Make it an appendix.  @@

RDF Representation of FHIR Definitions

In addition to the basic representation of FHIR resources in Turtle format, a Turtle representation of the FHIR infrastructure and definitions is also published, for the following purposes:

The RDF definitions are published as a series of Turtle files: HL7 v3 RIM (Reference Information Model) and FHIRShEx schemas that describe FHIR's RDF format are also available.

Relationship between RDF, FHIR, and ontologies

This page documents an RDF format that can be used to exchange FHIR data, on the basis that RDF is a universal information representation. Using RDF enables FHIR data to be used with other RDF data and RDF-aware applications to support inference, shared semantics across multiple standards and data formats, data integration, semantic data validation, compliance enforcement, SPARQL queries and other uses. Implementers using FHIR in this fashion should be aware of the relationship between FHIR's RDF format and other uses of ontologies.

FHIR's RDF format is based on the same abstract information model as the XML and JSON formats and carries the same information content. Resources are losslessly round-trippable between XML, JSON and RDF formats and data expressed in the RDF format corresponds closely to the XML and JSON formats in its look and feel. However, there are a few additional terms that may appear in the RDF format, which are explained on this page fhir:nodeRole, fhir:treeRoot, fhir:v and fhir:concept.

In addition to defining the RDF format, this specification provides an associated ontology that provides formal definitions for the relationships that appear in the RDF format. Ontologies that were designed independently almost always have some impedance mismatch when attempting to use them together. Many of the ontologies in the medical and life sciences domain are designed to capture facts about the world for research, such as the fact that the mitral valve is a kind of heart valve. But FHIR was designed to support the day-to-day operations of healthcare providers exchanging electronic health records (EHRs), and in this context, the orientation has historically been different. When using FHIR RDF with other ontologies, impedance differences are likely to show up in two main ways:

For both of these reasons, to maintain monotonicity in RDF, FHIR RDF should not be directly interpreted as stating facts; transformations are required to remove or isolate non-monotonic elements and reconcile the records across time and perspective.

Application developers should also be aware that some FHIR data attributes have a major impact on the interpretation of the enclosing data element: the meaning of the enclosing element cannot be determined in isolation. For example, a status of 'entered-in-error' means that the resource was created accidentally and should be ignored for most purposes.

Using RDF with the REST API

TODO

Usage Guidance

Application developers wishing to use FHIR RDF will often need to perform the following rough steps, though exact steps will depend on your application:

  1. Convert FHIR XML or FHIR JSON data to/from FHIR RDF. Open source implementations that can perform this conversion include:
  2. Download the FHIR ontology.
  3. Download other ontologies that you wish to use with your application, such as the SNOMED-CT ontology. ( Because of license restrictions, the process of obtaining the SNOMED-CT ontology is more complex than a simple download. Some guidance is provided here . )
  4. Create or obtain a bridge ontology that relates terms in the FHIR ontology to terms in your other ontologies.
  5. Load your FHIR RDF instance data and your ontologies into a reasoner and/or a triplestore, and perform SPARQL queries and/or reasoning.
  6. If you are creating FHIR RDF then you might also wish to validate it, using ShEx . If so, you can download the ShEx schema for FHIR RDF
A webinar by Harold Solbrig shows how FHIR RDF data can be used with the SNOMED-CT ontology to recognize a cancer diagnosis.  An associated tutorial details the steps used.  Caveat: this webinar and tutorial used a previous version of FHIR RDF.

Slides by Eric Prud'hommeaux illustrate how inference can be used on FHIR RDF data to perform a query for FHIR Observations of rheumatoid arthritis, using the SNOMED-CT ontology . Caveat: those slides are based on an earlier version of FHIR RDF and also show some terms in the fhir: namespace that do not actually exist in the fhir: namespace, such as fhir:Observation-of-Rheumatoid_arthritis-disorder and fhir:Coding-of-Rheumatoid_arthritis-disorder. A different namespace should have been used in the example.