FHIR Extensions Working Page

From HL7Wiki
Jump to: navigation, search

Discussion Thurs Q6 Oct 2015

Consideration of alternatives in the wire format for extensions

Here is the existing form:

<Patient xmlns="http://hl7.org/fhir">
 <id value="patient-example"/>
 <extension url="http://hl7.org/fhir/StructureDefinition/us-core-race">
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Race"/>
       <code value="2106-3"/>
     </coding>
   </valueCodeableConcept>
 </extension>
 <extension url="http://hl7.org/fhir/StructureDefinition/us-core-ethnicity">
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Ethnicity"/>
       <code value="2135-2"/>
     </coding>
   </valueCodeableConcept>
 </extension>
 <extension url="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial">
   <extension url="clinicalTrialNCT">
     <valueString value="NCT01647425"/>
   </extension>
   <extension url="clinicalTrialPeriod">
     <valuePeriod>
       <start value="2012-04-01"/>
       <end value="2013-09-30"/>
     </valuePeriod>
   </extension>
   <extension url="clinicalTrialReason">
     <valueCodeableConcept>
       <coding>
         <system value="http://snomed.info/sct"/>
         <code value="254637007"/>
         <display value="NSCLC - Non-small cell lung cancer"/>
       </coding>
     </valueCodeableConcept>
   </extension>
 </extension>
 <extension url="http://hl7.org/fhir/StructureDefinition/patient-birthTime">
   <valueDateTime value="2012-06-07T06:12:45-05:00"/>
 </extension>

We considered this variation (Option 1):


<Patient xmlns="http://hl7.org/fhir" definition="http://...qicore-patient">
 <id value="patient-example"/>
 <us-core-race>
   <coding>
     <system value="http://hl7.org/fhir/v3/Race"/>
     <code value="2106-3"/>
   </coding>
 </us-core-race>
 <us-core-ethnicity>
   <coding>
     <system value="http://hl7.org/fhir/v3/Ethnicity"/>
     <code value="2135-2"/>
   </coding>
 </us-core-ethnicity>
 <clinicalTrial>
   <NCT value="NCT01647425"/>
   <clinicalTrialPeriod>
       <start value="2012-04-01"/>
       <end value="2013-09-30"/>
   </clinicalTrialPeriod>
   <clinicalTrialReason>
     <coding>
       <system value="http://snomed.info/sct"/>
       <code value="254637007"/>
       <display value="NSCLC - Non-small cell lung cancer"/>
     </coding>
   </clinicalTrialReason>
 </clinicalTrial>

In this scheme, you must get the full definition from the definition attribute in the root, and parse that along with the instance. It tells you what the names 'us-core-race' etc are, and what their types are

There are several problems with this:

  • if you can't get the definition, you can't parse the unknown content
    • This can be an issue of networks, but also time. (E.g. Looking at a record 20 years later). It would essentially force systems to store the definition with the data
  • you have to pick one definition, and fall back to the old extension syntax for other extensions
  • if you do this, it's basically a 'local syntax', and you have to have perimeter exchange methods, or use a reference implementation to read the content. The practical ramifications of this are less than ideal

Then there's this variation (Option 2):

<Patient xmlns="http://hl7.org/fhir">
 <id value="patient-example"/>
 <us-core-race xmlns="http://hl7.org/fhir/StructureDefinition/">
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Race"/>
       <code value="2106-3"/>
     </coding>
   </valueCodeableConcept>
 </us-core-race>


This misuses the namespace technique in xml to inline the extension name. You'd just inline the name in json. We didn't seriously talk about this. The biggest problem is that names are variable because there's no uniqueness on them. Unless you ban using name clashes (while we have no ability to prevent getting caught that way), the names have to change depending on the local context.

This is also the form that json implementers didn't like (and, btw, there's no way to deal with modifiers)

The next form we considered was this (Option 3):

<Patient xmlns="http://hl7.org/fhir">
 <schema>
   <item name="us-core-race" 
     url="http://hl7.org/fhir/StructureDefinition/us-core-race" type="CodeableConcept"/>
   <item name="clinicalTrial" 
     url="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial">
     <item name="clinicalTrialNCT" 
       url="clinicalTrialNCT" type="string">
     <item name="clinicalTrialPeriod" 
       url="clinicalTrialNCT" type="Period">
     <item name="patient-clinicalTrialReason" 
       url="clinicalTrialNCT" type="CodeableConcept">
   </item>  
 </schema>
 
 <us-core-race>
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Race"/>
       <code value="2106-3"/>
     </coding>
   </valueCodeableConcept>
 </us-core-race>
 <clinicalTrial>
   <clinicalTrialNCT value="NCT01647425"/>
   <clinicalTrialPeriod>
       <start value="2012-04-01"/>
       <end value="2013-09-30"/>
   </clinicalTrialPeriod>
   <clinicalTrialReason>
     <coding>
       <system value="http://snomed.info/sct"/>
       <code value="254637007"/>
       <display value="NSCLC - Non-small cell lung cancer"/>
     </coding>
   </clinicalTrialReason>
 </clinicalTrial>

The ramification of this is that you have to iterate the content twice when you write, so the schema can be complete upfront - and the names are still variable too. It's also really hard to build with xslt or equivalent - you need serious logic to build the schema on the fly

None of these approaches represents a net benefit of the current approach - while they look good, the practical ramifications are unhappy.

The final approach we considered was radically simple (Option 4):

<Patient xmlns="http://hl7.org/fhir">
 <id value="patient-example"/>
 <birthTime value="2012-06-07T06:12:45-05:00"/>
 <active value="true"/>
 <name>
   <use value="official"/>
   <family value="Lerr"/>
   <given value="Todd"/>
   <given value="G."/>
   <suffix value="Jr"/>
 </name>
 <telecom>
   <system value="phone"/>
   <value value="(555) 555 1212"/>
   <use value="work"/>
 </telecom>
 <telecom>
   <system value="email"/>
   <value value="person@example.org"/>
   <use value="work"/>
 </telecom>
 <gender value="male"/>
 <birthDate value="2012-06-07"/>
 <deceased type="boolean" value="false"/>
 <address>
   <use value="home"/>
   <line value="123 North 102nd Street"/>
   <line value="Apt 4d"/>
   <city value="Harrisburg"/>
   <state value="PA"/>
   <postalCode value="17102"/>
   <country value="USA"/>
 </address>
 <us-core-race type="CodeableConcept" list="true">
   <coding>
     <system value="http://hl7.org/fhir/v3/Race"/>
     <code value="2106-3"/>
   </coding>
 </us-core-race>
 <us-core-ethnicity type="CodeableConcept">
   <coding>
     <system value="http://hl7.org/fhir/v3/Ethnicity"/>
     <code value="2135-2"/>
   </coding>
 </us-core-ethnicity>
 <clinicalTrial>
   <clinicalTrial.NCT type="string" value="NCT01647425"/>
   <clinicalTrial.period type="Period">
     <start value="2012-04-01"/>
     <end value="2013-09-30"/>
   </clinicalTrial.period>
   <clinicalTrial.reason type="CodeableConcept">
     <coding>
       <system value="http://snomed.info/sct"/>
       <code value="254637007"/>
       <display value="NSCLC - Non-small cell lung cancer"/>
     </coding>
   </clinicalTrial.reason>
 </clinicalTrial>
</Patient>
  • Note the changed to deceased - using type= there as well.
  • note that in json, extensions can be arrays or not. primitive extensions still need type, so they are represented with a value and a type property

This is lovely, and possible on the basis that there is a single global - curated - registry of names. The registry contains

 name - the name in the instance
 url - the canonical url for the extension 
 modifier - whether this is a modifier
 list - whether this is repeats or not 
 type[] - what types this name can be
 path[] - where the name can appear
 children[]
   name
   type
   list
   children[]

The interesting thing about this approach is that you can still generate schema for this one - though you need to do so based on a profile

The utility of this approach depends heavily on the quality of the curation, policy, and sla of the name registry.

Since this cannot be applied for now anyway, we tabled the discussion at this point so we could consider the ramifications and provisioning of such a regsitry. Further discussion in committee in Orlando Jan 2015

Brian's Thoughts

Would like to consider if we used standard XML namespaces using the Option 4 would work better.

This would then remove clashes from namespaces. The URL of the extension can be "recomposed" by appending the (XML namespace) + "-" + (element name) _(Where the element has a fhir:type attribute present, otherwise should be ignored XML content)_

<Patient xmlns="http://hl7.org/fhir" 
       xmlns:fhir="http://hl7.org/fhir"
       xmlns:usc="http://hl7.org/fhir/StructureDefinition/us-core"
       xmlns:pse="http://hl7.org/fhir/StructureDefinition/patient">
   <id value="patient-example"/>
   <usc:race fhir:type="CodeableConcept">
       <coding>
           <system value="http://hl7.org/fhir/v3/Race"/>
           <code value="2106-3"/>
       </coding>
   </usc:race>
   <usc:ethnicity fhir:type="CodeableConcept">
       <coding>
           <system value="http://hl7.org/fhir/v3/Ethnicity"/>
           <code value="2135-2"/>
       </coding>
   </usc:ethnicity>
   <pse:clinicalTrial fhir:type="Extension">
       <pse:clinicalTrialNCT fhir:type="String">
           <valueString value="NCT01647425"/>
       </pse:clinicalTrialNCT>
       <pse:clinicalTrialPeriod fhir:type="Period">
           <start value="2012-04-01"/>
           <end value="2013-09-30"/>
       </pse:clinicalTrialPeriod>
       <pse:clinicalTrialReason fhir:type="CodeableConcept">
           <coding>
               <system value="http://snomed.info/sct"/>
               <code value="254637007"/>
               <display value="NSCLC - Non-small cell lung cancer"/>
           </coding>
       </pse:clinicalTrialReason>
   </pse:clinicalTrial>
   <pse:birthTime fhir:type="DateTime">
       <valueDateTime value="2012-06-07T06:12:45-05:00"/>
   </pse:birthTime>
</Patient>

And yes, I haven't considered how this would be represented in the json format (not one of my first languages - yet)

Grahame's comments: this is mash up of options 2 and 4 above. In JSON, you'd just use the URL directly. It doesn't consider array issues. And namespaces are super yucky Lloyd's comments: I don't understand the name for namespaces. In option 4, names are all in one namespace - maintained by HL7 or some other authority.

Discussion Mon Q2 Jan 2016

As an alternative approach, Chris G. pointed out that a Profile can be used to accomplish a similar solution (albeit with its own issues and considerations):

<Patient xmlns="http://hl7.org/fhir">
  <extension url="http://example.com/Patient.Confidential">
    <valueBoolean value="false"/>
  </extension>
</Patient>

becomes:

<Patient xmlns="http://hl7.org/fhir">
  <confidential value="false" />
</Patient>

with a profile entry of:

<element>
  <path value="Patient.extension"/>
  <name value="confidential"/>
  <min value="0"/>
  <max value="1"/>
  <type>
    <code value="Extension"/>
    <profile value="http://example.com/StructureDefinition/Patient.Confidential"/>
  </type>
</element>

Copyright © Health Level Seven International ® ALL RIGHTS RESERVED. The reproduction of this material in any form is strictly forbidden without the written permission of the publisher.