DSTU2 Ballot Source

This page is part of the FHIR Specification (v0.5.0: DSTU 2 Ballot 2). The current version which supercedes this version is 5.0.0. For a full list of available versions, see the Directory of published versions . Page versions: R5 R4B R4 R3 R2

2.14.1 Slicing and Discriminator Examples

2.14.1.1 Extensions

As an example, consider slicing extensions. The base extension on every element is defined as a list (0..*) of extensions, and each extension has a url that identifies it, and a value. Consider an example where a profile defines that for a particular element (named Patient) two extensions, with URLs http://acme.com/a and http://acme.com/b. In addition, the profile allows other extensions to be used.

Technically, the profile achieves this by "slicing" the extension list, into two slices, and saying that the slicing is "open" - that there can be other slices introduced. Here's the relevant parts of the Profile on patient:


<Profile xmlns="http://hl7.org/fhir">
  <!-- snip -->
  <structure>
    <!-- snip -->
    <type value="Patient"/>
    <snapshot>
      <element>
        <path value="Patient"/>
        <!-- snip -->
      </element>
      <element>
        <path value="Patient.extension"/>
        <!-- this first element defines the slicing, and carries the base definition forward -->
        <slicing>  
          <discriminator value="url"/> <!-- Extensions are always discriminated by URL -->
          <ordered value="false"/>     <!-- we don't care what order they appear in -->
          <rules value="open"/>        <!-- other extensions can be used -->
        </slicing>        
        <!-- -- snip definition -->
      </element>
      <!-- first extension -->
      <element>
        <path value="Patient.extension"/>
        <definition>
          <!-- snip most of definition -->
         <type>  
          <code value="Extension"/>  
          <!-- the profile for an extension is a reference to the extension definition itself - 
            this implies a profile, and happens to fix the @url value to the desired URL -->
          <profile value="http://acme.com/a"/> 
         </type>
        </definition>
      </element>
      <!-- first extension -->
      <element>
        <path value="Patient.extension"/>
        <definition>
          <!-- snip most of definition -->
         <type>  
          <code value="Extension"/>  
          <!-- the profile for an extension is a reference to the extension definition itself - 
            this implies a profile, and happens to fix the @url value to the desired URL -->
          <profile value="http://acme.com/b"/> 
         </type>
        </definition>
      </element>
      <!-- snip rest of profile -->
    </snapshot>
  </structure>
</Profile>

Here's a patient example that conforms to this profile:

<Patient xmlns="http://hl7.org/fhir">
  <!-- two extensions, the order doesn't matter -->
  <extension url="http://acme.com/b">
    <!-- this has the right url, and so matches the second slice -->
    <!-- snip whatever value extension would have -->
  </extension>
  <extension url="http://acme.com/a">
    <!-- this has the right url, and so matches the first slice -->
    <!-- snip whatever value extension would have -->
  </extension>
  <!-- the rest of patient -->
</Patient>

2.14.1.2 Diagnostic Report & Observation

In this example, a profile on an diagnostic report says that it must have 4 observations, each with a different LOINC code (e.g. a classic lab panel). In this case (taken from the Example Lipid Profile), the structure that applies to DiagnosticReport will say that there is 4 slices on DiagnosticReport.result, each conforming to a different structure, which are also contained in the same profile. Each of those structures will constrain the LOINC code in the observation.

<Profile xmlns="http://hl7.org/fhir">
  <!-- snip -->
  <structure>
    <!-- first structure, the DiagnosticReport -->
    <type value="DiagnosticReport"/>
    <base value="http://hl7.org/fhir/StructureDefinition/DiagnosticReport"/>
    <name value="LipidProfile"/>
    <!-- snip -->
    <snapshot>
      <!-- snip elements -->
      <element>
        <!-- first definition for result -->
        <path value="DiagnosticReport.result"/>
        <slicing>
          <!-- this is sliced by the name value of the target of the reference -->
          <discriminator value="reference.name"/>
          <!-- have to be in the specified order -->
          <ordered value="true"/>     
          <!-- this profile says, no other observations allowed -->
          <rules value="closed"/>
        </slicing>
        <!-- snip definition -->
      </element>
      <!-- first slice: Cholesterol -->
      <element>
        <path value="DiagnosticReport.result"/>
        <!-- name is just for documentation purposes - not used any other way -->
        <name value="Cholesterol"/> 
        <definition>
          <!-- snip definition parts -->
          <type>
            <code value="Reference"/>
            <!-- this element must conform to the "Cholesterol" structure -->
            <profile value="#Cholesterol"/>
          </type>
        </definition>
      </element>
      <!-- next 3 slices all the same, but different names for profile -->
      <element>
        <path value="DiagnosticReport.result"/>
        <!-- name is just for documentation purposes - not used any other way -->
        <name value="Triglyceride"/> 
        <definition>
          <!-- snip definition parts -->
          <type>
            <code value="Reference"/>
            <!-- this element must conform to the "Cholesterol" structure -->
            <profile value="#Triglyceride"/>
          </type>
        </definition>
      </element>
      <element>
        <path value="DiagnosticReport.result"/>
        <!-- name is just for documentation purposes - not used any other way -->
        <name value="LDLCholesterol"/> 
        <definition>
          <!-- snip definition parts -->
          <type>
            <code value="Reference"/>
            <!-- this element must conform to the "Cholesterol" structure -->
            <profile value="#LDLCholesterol"/>
          </type>
        </definition>
      </element>
      <element>
        <path value="DiagnosticReport.result"/>
        <!-- name is just for documentation purposes - not used any other way -->
        <name value="HDLCholesterol"/> 
        <definition>
          <!-- snip definition parts -->
          <type>
            <code value="Reference"/>
            <!-- this element must conform to the "Cholesterol" structure -->
            <profile value="#HDLCholesterol"/>
          </type>
        </definition>
      </element>
      <!-- snip elements -->
    </snapshot>
  </structure>
  
  <!-- now, the second structure, for the Cholesterol profile -->
  <structure>
    <type value="Observation"/>
    <base value="http://hl7.org/fhir/StructureDefinition/Observation"/>
    <name value="Cholesterol"/> <!-- this is the target of #Cholesterol -->
    <snapshot>
      <!-- snip elements -->
      <element>
        <!-- this the element definition for name. Because of the 
          slicing / discriminator rules in the LipidReport profile 
          that references it, it is required to fix the value of 
          the name element -->
        <path value="Observation.name"/>
        <definition>
           <!-- there's actually 3 ways to fix a CodeableConcept
           to a single fixed value. Here, we used the simplest one -->
           <valueCodeableConcept>
             <!-- just fix the value to the right code -->
             <coding>
               <system value="http://loinc.org"/>
               <code value="35200-5"/>
               <display value="Cholesterol"/>
             </coding>
           </valueCodeableConcept>
        </definition>
      </element>
      <!-- snip elements -->
    </snapshot>
  </structure>

  <!-- Triglyceride profile -->
  <structure>
    <type value="Observation"/>
    <base value="http://hl7.org/fhir/StructureDefinition/Observation"/>
    <name value="Triglyceride"/> <!-- this is the target of #Cholesterol -->
    <snapshot>
      <!-- snip elements -->
      <element>
        <!-- this the element definition for name. Because of the 
          slicing / discriminator rules in the LipidReport profile 
          that references it, it is required to fix the value of 
          the name element -->
        <path value="Observation.name"/>
        <definition>
           <!-- there's actually 3 ways to fix a CodeableConcept
           to a single fixed value. Here, we used the simplest one -->
           <valueCodeableConcept>
             <!-- just fix the value to the right code -->
             <coding>
               <system value="http://loinc.org"/>
               <code value="35217-9"/>
               <display value="Triglyceride"/>
             </coding>
           </valueCodeableConcept>
        </definition>
      </element>
      <!-- snip elements -->
    </snapshot>
  </structure>
  
  <!-- LDLCholesterol profile -->
  <structure>
    <type value="Observation"/>
    <base value="http://hl7.org/fhir/StructureDefinition/Observation"/>
    <name value="LDLCholesterol"/> <!-- this is the target of #Cholesterol -->
    <snapshot>
      <!-- snip elements -->
      <element>
        <!-- this the element definition for name. Because of the 
          slicing / discriminator rules in the LipidReport profile 
          that references it, it is required to fix the value of 
          the name element -->
        <path value="Observation.name"/>
        <definition>
           <!-- because of the way that LDL cholesterol measurements works 
             (well, in this context- it varies), there's 2 different LOINC
             codes for either measured or calculated. So here, we bind to
             a value set -->
         <binding>  
          <name value="LDL Cholesterol codes"/>
          <conformance value="required"/> <!-- must be required if this is a discriminator -->
          <!-- snip the actual value set reference, but it refers to a value 
               set with two LOINC codes, one for each kind of LDL, which in 
               this case are LOINC codes 18262-6 and 13457-7 -->
         </binding>
       </definition>
      </element>
      <!-- snip elements -->
    </snapshot>
  </structure>
  
  <!-- HDLCholesterol profile -->
  <structure>
    <type value="Observation"/>
    <base value="http://hl7.org/fhir/StructureDefinition/Observation"/>
    <name value="HDLCholesterol"/> <!-- this is the target of #Cholesterol -->
    <snapshot>
      <!-- snip elements -->
      <element>
        <!-- this the element definition for name. Because of the 
          slicing / discriminator rules in the LipidReport profile 
          that references it, it is required to fix the value of 
          the name element -->
        <path value="Observation.name"/>
        <definition>
           <!-- there's actually 3 ways to fix a CodeableConcept
           to a single fixed value. Here, we used the simplest one -->
           <valueCodeableConcept>
             <!-- just fix the value to the right code -->
             <coding>
               <system value="http://loinc.org"/>
               <code value="2085-9"/>
               <display value="LDL Cholesterol"/>
             </coding>
           </valueCodeableConcept>
        </definition>
      </element>
      <!-- snip elements -->
    </snapshot>
  </structure>
</Profile>

Here is an instance that meets the rules for this profile:

<!-- first, the diagnostic report -->
<DiagnosticReport xmlns="http://hl7.org/fhir">
  <!-- snip -->
  <!-- here's the set of results. We don't know what 
    slices they are or anything until we go off, find 
    the references, and look in them -->
  <result>
    <reference value="Observation/cholesterol"/>
  </result>  
  <result>
    <reference value="Observation/triglyceride"/>
  </result>
  <result>
    <reference value="Observation/ldlcholesterol"/>
  </result>
  <result>
    <reference value="Observation/hdlcholesterol"/>
  </result>
  <!-- snip -->
</DiagnosticReport>

<!-- Observation, id = cholesterol -->
<Observation xmlns="http://hl7.org/fhir">
  <!-- the observation starts with the name, as specified
    by the profile for the first slice  -->
  <name>
    <coding>
      <system value="http://loinc.org"/>
      <code value="35200-5"/>
      <display value="Cholesterol"/>
    </coding>
  </name>
  <!-- snip -->
</Observation>

<!-- Observation, id = triglyceride -->
<!-- this code matches the second slice. good -->
<Observation xmlns="http://hl7.org/fhir">
  <name>
    <coding>
      <system value="http://loinc.org"/>
      <code value="35217-9"/>
      <display value="Triglyceride"/>
    </coding>
  </name>
  <!-- snip -->
</Observation>

<!-- Observation, id = hdlcholesterol -->
<!-- this code matches the fourth slice. good -->
<Observation xmlns="http://hl7.org/fhir">
  <name>
    <coding>
      <system value="http://loinc.org"/>
      <code value="2085-9"/>
      <display value="HDL Cholesterol"/>
    </coding>
  </name>
  <!-- snip -->
</Observation>

<!-- Observation, id = ldlcholesterol -->
<!-- this code matches the third slice. good -->
<Observation id="ldlcholesterol">
  <name>
    <coding>
      <system value="http://loinc.org"/>
      <code value="13457-7"/>
      <display value="LDL Chol. (Calc)"/>
    </coding>
  </name>
  <!-- snip -->
</Observation>

Note that this version isn't valid, because the slices are not in the correct order:

<!-- first, the diagnostic report -->
<DiagnosticReport xmlns="http://hl7.org/fhir">
  <!-- snip -->
  <!-- here's the set of results. We don't know what 
    slices they are or anything until we go off, find 
    the references, and look in them -->
  <result>
    <reference value="Observation/cholesterol"/>
  </result>  
  <result>
    <reference value="Observation/triglyceride"/>
  </result>
  <result>
    <reference value="Observation/hdlcholesterol"/>
  </result>
  <result>
    <reference value="Observation/ldlcholesterol"/>
  </result>
  <!-- snip -->
</DiagnosticReport>