This page is part of the FHIR Specification (v3.0.2: STU 3). 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
FHIR Infrastructure Work Group | Maturity Level: N/A | Ballot Status: Informative |
One common use of slicing is to describe different constraints on different kinds of patient contact details. In this example, as Patient.telecom is defined as: ContactPoint [0..*] where the ContactPoint has system, value and use.
Consider the case where the profile should say:
An example of a patient resource that meets these rules:
<Patient> ... snip ... <telecom> <system value="phone" /> <use value="home" /> <value value="5551234567" /> </telecom> <telecom> <system value="email" /> <value value="someone@acme.org" /> </telecom> ... snip ... </Patient>
To do this, the profile that implements these rules needs to do the following:
In a StructureDefinition, this will look like:
<!-- setting up the slicing --> <element> <path value="Patient.telecom"/> <slicing> <discriminator value="system"/> <discriminator value="use"/> <rules value="closed"/> </slicing> <!-- net cardinality rules --> <min value="1"/> <max value="3"/> </element> <!-- first slice: home phone --> <element> <path value="Patient.telecom"/> <name value="HomePhone"/> <!-- mandatory - gives the slice a name --> <min value="1"/> <max value="1"/> </element> <element> <path value="Patient.telecom.system"/> <min value="1"/> <fixedCode value="phone"/> </element> <element> <path value="Patient.telecom.value"/> <min value="1"/> </element> <element> <path value="Patient.telecom.use"/> <min value="1"/> <fixedCode value="home"/> </element> <!-- second slice: work phone --> <element> <path value="Patient.telecom"/> <name value="WorkPhone"/> <!-- mandatory - gives the slice a name --> <min value="0"/> <max value="1"/> </element> <element> <path value="Patient.telecom.system"/> <min value="1"/> <fixedCode value="phone"/> </element> <element> <path value="Patient.telecom.value"/> <min value="1"/> </element> <element> <path value="Patient.telecom.use"/> <min value="1"/> <fixedCode value="work"/> </element> <!-- third slice: email --> <element> <path value="Patient.telecom"/> <name value="Email"/> <!-- mandatory - gives the slice a name --> <min value="0"/> <max value="1"/> </element> <element> <path value="Patient.telecom.system"/> <min value="1"/> <fixedCode value="email"/> </element> <element> <path value="Patient.telecom.value"/> <min value="1"/> </element> <element> <path value="Patient.telecom.use"/> <min value="0"/> </element>
Note: lots of definition detail has been left out, and only the parts relevant to the pattern are shown. Also, providing a fixed value makes the minimum cardinality irrelevant, but it is shown here for completeness.
This table illustrates the relationship between the instance and the ElementDefinitions:
Path | Name | Min | Max | Fixed | |
<Patient> | Patient | ||||
Patient.telecom | 1 | 3 | |||
<telecom> | Patient.telecom | HomePhone | 1 | 1 | |
<system value="phone" /> | Patient.telecom.system | 1 | 1 | phone | |
<value value="5551234567" /> | Patient.telecom.value | 1 | 1 | ||
<use value="home" /> | Patient.telecom.use | 1 | 1 | home | |
</telecom> | |||||
Patient.telecom | WorkPhone | 0 | 1 | ||
<telecom> | Patient.telecom | 0 | 1 | ||
<system value="email" /> | Patient.telecom.system | 1 | 1 | ||
<value value="someone@acme.org" /> | Patient.telecom.value | 1 | 1 | ||
</telecom> | Patient.telecom.use |
Another use of Slicing is for Blood Pressure Measurements, where the profile says:
An example of an Observation resource that meets these rules:
<Observation> ... snip ... <component> <code> <coding> <system value="http://loinc.org" /> <code value="8480-6" /> <display value="Systolic blood pressure" /> </coding> </code> <valueQuantity> <value value="120" /> <unit value="mmHg" /> <system value="http://unitsofmeasure.org" /> <code value="mm[Hg]" /> </valueQuantity> </component> <component> <code> <coding> <system value="http://loinc.org" /> <code value="8462-4" /> <display value="Diastolic blood pressure" /> </coding> </code> <valueQuantity> <value value="80" /> <unit value="mmHg" /> <system value="http://unitsofmeasure.org" /> <code value="mm[Hg]" /> </valueQuantity> </component> </Patient>
To do this, the profile that implements these rules needs to do the following:
In a StructureDefinition, this will look like:
<!-- setting up the slicing --> <element> <path value="Observation.component"/> <slicing> <discriminator value="code"/> </slicing> <!-- net cardinality rules --> <min value="2"/> <max value="*"/> </element> <!-- first slice: systolic --> <element> <path value="Observation.component"/> <name value="systolic"/> <!-- mandatory - gives the slice a name --> <min value="1"/> <max value="1"/> </element> <element> <path value="Observation.component.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <code value="8480-6" /> <display value="Systolic blood pressure" /> </coding> </fixedCodeableConcept> </element> <element> <path value="Observation.component.valueQuantity"/> <min value="1"/> </element> <!-- second slice: diastolic --> <element> <path value="Observation.component"/> <name value="diastolic"/> <!-- mandatory - gives the slice a name --> <min value="1"/> <max value="1"/> </element> <element> <path value="Observation.component.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <code value="8462-4" /> <display value="Diastolic blood pressure" /> </coding> </fixedCodeableConcept> </element> <element> <path value="Observation.component.valueQuantity"/> <min value="1"/> </element>
Note: lots of definition detail has been left out, and only the parts relevant to the pattern are shown. E.g. A real blood pressure profile would fix unit, an overall Observation code etc.
For another 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), there are 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 are the relevant parts of the Profile on patient:
<StructureDefinition xmlns="http://hl7.org/fhir"> <!-- snip --> <baseType value="Patient" /> <baseDefinition value="http://hl7.org.fhir/StructureDefinition/Patient" /> <derivation value="constraint" /> <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"/> <!-- 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> </element> <!-- second extension --> <element> <path value="Patient.extension"/> <!-- 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> </element> <!-- snip rest of profile --> </snapshot> </StructureDefinition>
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>
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 are 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.
<!-- first structure, the DiagnosticReport --> <StructureDefinition xmlns="http://hl7.org/fhir"> <!-- snip --> <url value="http://acme.org/fhir/StructureDefinition/lipid-report"/> <name value="LipidProfile"/> <baseType value="DiagnosticReport"/> <baseDefinition value="http://hl7.org/fhir/StructureDefinition/DiagnosticReport"/> <derivation value="constraint" /> <!-- snip --> <snapshot> <!-- snip elements --> <element> <!-- first definition for result --> <path value="DiagnosticReport.result"/> <slicing> <!-- this is sliced by the code value of the target of the reference --> <discriminator value="reference.code"/> <!-- 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 value="Cholesterol"/> <!-- snip definition parts --> <type> <code value="Reference"/> <!-- this element must conform to the "Cholesterol" structure --> <profile value="http://acme.org/fhir/StructureDefinition/Cholesterol"/> </type> </element> <!-- next 3 slices all the same, but different names for profile --> <element> <path value="DiagnosticReport.result"/> <name value="Triglyceride"/> <!-- snip definition parts --> <type> <code value="Reference"/> <!-- this element must conform to the "Triglyceride" structure --> <profile value="http://acme.org/fhir/StructureDefinition/Triglyceride"/> </type> </element> <element> <path value="DiagnosticReport.result"/> <name value="LDLCholesterol"/> <!-- snip definition parts --> <type> <code value="Reference"/> <!-- this element must conform to the "LDLCholesterol" structure --> <profile value="http://acme.org/fhir/StructureDefinition/LDLCholesterol"/> </type> </element> <element> <path value="DiagnosticReport.result"/> <name value="HDLCholesterol"/> <!-- snip definition parts --> <type> <code value="Reference"/> <!-- this element must conform to the "HDLCholesterol" structure --> <profile value="http://acme.org/fhir/StructureDefinition/HDLCholesterol"/> </type> </element> <!-- snip elements --> </snapshot> </StructureDefinition> <!-- now, the second structure, for the Cholesterol profile --> <StructureDefinition> <url value="http://acme.org/fhir/StructureDefinition/Cholesterol"/> <name value="Cholesterol"/> <baseType value="Observation"/> <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Observation"/> <derivation value="constraint" /> <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.code"/> <definition> <!-- there are 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> </StructureDefinition> <!-- Triglyceride profile --> <StructureDefinition> <url value="http://acme.org/fhir/StructureDefinition/Triglyceride"/> <name value="Triglyceride"/> <baseType value="Observation"/> <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Observation"/> <derivation value="constraint" /> <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.code"/> <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> </StructureDefinition> <!-- LDLCholesterol profile --> <StructureDefinition> <url value="http://acme.org/fhir/StructureDefinition/LDLCholesterol"/> <name value="LDLCholesterol"/> <baseType value="Observation"/> <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Observation"/> <derivation value="constraint" /> <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.code"/> <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> <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> </StructureDefinition> <!-- HDLCholesterol profile --> <StructureDefinition> <url value="http://acme.org/fhir/StructureDefinition/HDLCholesterol"/> <name value="HDLCholesterol"/> <baseType value="Observation"/> <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Observation"/> <derivation value="constraint" /> <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.code"/> <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> </StructureDefinition>
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 --> <code> <coding> <system value="http://loinc.org"/> <code value="35200-5"/> <display value="Cholesterol"/> </coding> </code> <!-- snip --> </Observation> <!-- Observation, id = triglyceride --> <!-- this code matches the second slice. good --> <Observation xmlns="http://hl7.org/fhir"> <code> <coding> <system value="http://loinc.org"/> <code value="35217-9"/> <display value="Triglyceride"/> </coding> </code> <!-- snip --> </Observation> <!-- Observation, id = hdlcholesterol --> <!-- this code matches the fourth slice. good --> <Observation xmlns="http://hl7.org/fhir"> <code> <coding> <system value="http://loinc.org"/> <code value="2085-9"/> <display value="HDL Cholesterol"/> </coding> </code> <!-- snip --> </Observation> <!-- Observation, id = ldlcholesterol --> <!-- this code matches the third slice. good --> <Observation id="ldlcholesterol"> <code> <coding> <system value="http://loinc.org"/> <code value="13457-7"/> <display value="LDL Chol. (Calc)"/> </coding> </code> <!-- 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> <!-- Oops the last two are out of order --> <result> <reference value="Observation/hdlcholesterol"/> </result> <result> <reference value="Observation/ldlcholesterol"/> </result> <!-- snip --> </DiagnosticReport>
Most uses of Composition involve conformance to a profile that specifies which sections will exist, and what their contents will be. This is yet another example of slicing. A typical document content profile might specify a section structure something like this:
Real profiles will contain lots of detail about the sections, but these are omitted here in the interests of clarity.
An example of a Composition that meets these rules:
<Composition> ... snip ... <section> <code> <coding> <system value="http://loinc.org" /> <use value="29299-5" /> <value value="Reason for visit Narrative" /> </coding> </code> ... snip ... </section> <section> <code> <coding> <system value="http://loinc.org" /> <use value="46057-6" /> <value value="Medications section" /> </coding> </code> ... snip ... <section> <code> <coding> <system value="http://loinc.org" /> <use value="66149-6" /> <value value="Prescribed medications" /> </coding> </code> ... snip ... </section> <section> <code> <coding> <system value="http://loinc.org" /> <use value="66150-4" /> <value value="O medications" /> </coding> </code> ... snip ... </section> </section> <section> <code> <coding> <system value="http://loinc.org" /> <use value="8716-3" /> <value value="Vital signs" /> </coding> </code> ... snip ... </section> </Composition>
To do this, the profile that implements these rules needs to do the following:
In a StructureDefinition, this will look like:
<!-- setting up the slicing on Composition.section --> <element> <path value="Composition.section"/> <slicing> <discriminator value="code"/> <ordered value="true"/> <rules value="closed"/> </slicing> <!-- net cardinality rules --> <min value="3"/> <max value="3"/> </element> <!-- first slice: reason for visit --> <element> <path value="Composition.section"/> <name value="reason-for-visit"/> <min value="1"/> <max value="1"/> </element> <element> <path value="Composition.section.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <use value="29299-5" /> <value value="Reason for visit Narrative" /> </coding> </fixedCodeableConcept> </element> <!-- second slice: medications --> <element> <path value="Composition.section"/> <name value="medications"/> <min value="1"/> <max value="1"/> </element> <element> <path value="Composition.section.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <use value="46057-6" /> <value value="Medications section" /> </coding> </fixedCodeableConcept> </element> <!-- setting up the inner slicing on medication Composition.section.section --> <element> <path value="Composition.section.section"/> <slicing> <discriminator value="code"/> <ordered value="true"/> <rules value="closed"/> </slicing> <!-- net cardinality rules --> <min value="1"/> <max value="2"/> </element> <!-- first inner slice: prescribed medications --> <element> <path value="Composition.section.section"/> <name value="prescribed"/> <min value="1"/> <max value="1"/> </element> <element> <path value="Composition.section.section.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <use value="66149-6" /> <value value="Prescribed medications" /> </coding> </fixedCodeableConcept> </element> <!-- second inner slice: over the counter medications --> <element> <path value="Composition.section.section"/> <name value="otc"/> <min value="0"/> <max value="1"/> </element> <element> <path value="Composition.section.section.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <use value="66150-4" /> <value value="Over the counter medications" /> </coding> </fixedCodeableConcept> </element> <!-- third slice: Vital Signs --> <element> <path value="Composition.section"/> <name value="vital-signs"/> <min value="1"/> <max value="1"/> </element> <element> <path value="Composition.section.code"/> <min value="1"/> <fixedCodeableConcept> <coding> <system value="http://loinc.org" /> <use value="8716-3" /> <value value="Vital signs" /> </coding> </fixedCodeableConcept> </element>