View raw Markdown
type: sdc-pagesource: sdc/input/pagecontent/extraction.xml

SDC: Form Data Extraction

Questionnaires are excellent tools for data capture. They allow tight control over what data is gathered and ensure information is gathered consistently across multiple users. However, data gathered using different questionnaires - or even different versions of the same questionnaire - is often not comparable. It is also not very searchable or easily integrated with discrete data sources. Because of this, the general recommendation in FHIR is to use questionnaires for raw data capture but then to convert the resulting QuestionnaireResponse instances into other FHIR resources - Observations, MedicationStatements, FamilyMemberHistories, etc. This allows the data gathered to then be easily combined with other data into FHIR documents and messages and exposed over FHIR REST interfaces.

Such conversion can be done with custom code written on a Questionnaire by Questionnaire basis. However, it makes the process much easier if it's possible to write generic software that can convert any arbitrary QuestionnaireResponse into appropriate FHIR resources leveraging metadata embedded in the Questionnaire. This portion of the SDC guide defines mechanisms for doing so.

Caveats, considerations and rules with form data extraction

Extraction service

Like Questionnaire population, extracting data from a QuestionnaireResponse is a complex process involving querying existing FHIR data and using more advanced technologies such as FHIRPath and StructureMap. It's therefore a function that systems may also wish to offload to a separate system. The QuestionnaireResponse extract has been created for this purpose. It takes in a completed QuestionnaireResponse and returns either an individual FHIR resource or a Bundle of resources, depending on the type of Questionnaire. The operation does not post the created resources to a server. It's up to the client system to determine what action(s) to take with the created content.

NOTE: It's the responsibility of the client system to ensure that any generated resources are valid against necessary profiles, etc. before using content produced by this operation.

Designing Questionnaires to support data extraction

This specification defines four different mechanisms to embed information in Questionnaires to support subsequent resource extraction:

Systems are free to experiment with other extraction mechanisms but cannot expect support for those from other SDC-conformant systems.

Each mechanism has its own profile that includes the additional resource elements or extensions relevant for supporting a particular mechanism: SDC Questionnaire Extract - Observation, SDC Questionnaire Extract - Definition, SDC Questionnaire Extract - Template, and SDC Questionnaire Extract - Structure Map profiles.
Each profile identifies specific 'must support' elements and extensions that systems that claim to support a specific SDC extraction mechanism SHALL be capable of extracting data, as befits the CapabilityStatement(s) they claim conformance to. Each system should choose which approach(es) it wishes to use and support based on the elements specified in that profile.

Some of these mechanisms make use of FHIR-based queries, FHIRPath and/or CQL as well as extensions that include expressions in one of these languages. Implementers should read the Using Expressions page for background and guidance on these technologies and extensions.

Observation-based extraction

Profile:

SDC Questionnaire Extract - Observation

Relevant Extensions:

Example Questionnaires:

example-cqf-PHQ9

This is the simplest of the extraction mechanisms. It leverages the same data elements as are used for the Observation-based population mechanism. It takes advantage of the fact that most questions in the healthcare space typically correspond to the value element of an Observation. It also takes advantage of the Questionnaire.item.code element that identifies what a concept each question or group corresponds to.
Observation-based extraction can now also support cross-resource references (e.g., enabling a ServiceRequest to refer to an extracted Observation) by using the observationExtractEntry extension. This allows specifying metadata like fullUrl, resourceId, ifNoneExist, etc. that enable other resources to reference the extracted Observation. See Supporting Cross-Resource Referencing for details. .

To use this method:

  1. Include the item.code element on each question to be extracted. Typically, this will be a LOINC code, but in some jurisdictions/environments, SNOMED CT or other codes may be relevant.

  2. Groups can also have an item.code present - this might represent the code of the panel or the Observation.code of an Observation with no value but with multiple Observation.component elements. Child question items can then assert the item.code of the "member-of" Observations or the Observation.component.code values.

  3. To signal that the item.code is intended for use in extraction (as opposed to just providing metadata about the Questionnaire item), the observationExtract extension must also be included (and set to true). This extension can be specified either at the root Questionnaire or on an individual question or group item (not a display item) that indicates that the observation-based approach should be used to extract either that particular item (based on the code present) or all items in the questionnaire (if they have a code present).

  4. The extension can also be applied to specific item.code elements to control which codes should be propagated during extraction. For example, an item might list codes for "Body weight", "Body weight (clothed)" and "Body weight (unclothed)". If only the "Body weight" code should be included in the extracted content, the extension should be set to 'true' only on that specific code element. When any item.code elements are tagged with 'true', only the tagged codes will propagate - sibling codes with no extension are considered to have an implicit extension value of 'false'. If no extension appears on any of the item.code elements but an extension appears on the item itself, an ancestor item, or the Questionnaire root, then all codes are considered equivalent and appropriate to include as sibling codings within Observation.code.

    The observation-extract extension is inherited. If an item or code doesn't declare a value for the extension, the element is treated as though it declared the same value as its nearest ancestor that has the extension. Note that codes have no descendants, so extensions on a code will not propagate.

  5. Optionally, use the observationExtractEntry extension on a Questionnaire.item to define metadata such as fullUrl, resourceId, or conditional fields (ifNoneExist, ifMatch, etc.) for the extracted Observation. This enables other extracted resources (e.g., ServiceRequest.supportingInfo) to reference the Observation within the same transaction Bundle. See Supporting Cross-Resource Referencing for more details.

Category assignment: The observation-extract-category extension only applies when extraction has been determined to occur. The category value on an item or code will override any category declared on ancestor elements. If multiple categories are needed, all must be declared on the specific item.

When performing the extraction process, the system will create a batch that will contain creates or updates of Observation instances. It will go through the QuestionnaireResponse and identify all answers marked for extraction (if the corresponding Questionnaire item or the root Questionnaire has a observationExtract extension). For each of those it will then determine whether to create a new observation, update an existing observation or do nothing. Guidelines for making this decision are as follows:

Take no action if:

Update if:

Create a new Observation if:

the conditions in the preceding two rows are not met

If updating, the original Observation SHALL be adjusted to have the new value or component.value and the status changed to "amended", then PUT to the source system. If creating, data elements SHOULD be populated as follows:

If the Questionnaire.item that is linked to an Observation contains child items that are also linked to Observations, then things get more complex as a determination will need to be made on whether to link the parent to child as Observation.component or as Observation.hasMember. The appropriate relationship to use is conveyed using the code value found in the observationExtract extension. If no extension is present or the value is only a boolean, the expected relationship is undefined and behavior is up to the extracting system.

Considerations and rules when using this approach:

Supporting Cross-Resource Referencing

To enable extracted Observations to be referenced by other resources (e.g., a ServiceRequest.supportingInfo), a new extension ObservationExtractEntry is introduced. This extension may be used on Questionnaire.item to predefine bundle-related metadata for the extracted Observation, such as its fullUrl or resourceId.

The extension supports the following elements:

Definition-based extraction

Profile:

SDC Questionnaire Extract - Definition

Relevant Extensions:

Example Questionnaires:

This approach to extraction is more generic than the observation-based extraction. It supports extracting data into any type of FHIR resource rather than being limited to only Observation. It also supports extracting additional Observation properties not defined for the observation-based extract, e.g. explicit effective time ranges, interpretations, comments, etc.
The technique is called "definition-based" because it uses StructureDefinitions to identify resource types/profiles, and their properties which are then associated with items in the Questionnaire using the Questionnaire.item.definition element.

The basic approach to the definition-based extraction mechanism is to walk the QuestionnaireResponse and for each item that has the definitionExtract extension, create a new stub resource of that type/profile, then scan the item and all its children and populate values in the resource based on items that have a matching definition property set, or have definitionExtractValue extensions on them that have the same definition canonical URL value as in the definitionExtract extension. Once all the children have been processed, the system will populate the bundle.entry.resource property with the extracted resource, and the bundle.entry.request.method and other properties with values based on the definitionExtract extension. If the definition was to a profile, any slicing information or fixed/pattern values should also be extracted from the profile and applied to the resource where appropriate. For example an identifier might have a fixed system property defined in a profile slice.

The item's definition property is composed of:

Putting this all together, a definition property looks like this: http://hl7.org/fhir/StructureDefinition/Patient#Patient.name.given.

If the Questionnaire author needs to indicate a specific version of a StructureDefinition or profile to use for extraction, they can append a pipe-delimited version before the hash fragment. For example: http://example.org/fhir/StructureDefinition/LocalizedPatientProfile|2.1.1#Patient.name.given will indicate that the extraction logic should reference version 2.1.1 of the profile when resolving the element path.

Note: The complete element id does not actually need to appear in a profile snapshot, it is also possible to 'extend' an id to walk further into the data types of the specified element.
For example, the example above http://hl7.org/fhir/StructureDefinition/Patient#Patient.name.given is valid, even though the referenced profile's snapshot only contains Patient.name, not Patient.name.given.
However, for more complex references (e.g. referring to a particular extension or a particular repetition), it will be necessary to define a distinct profile where slicing ensures that a single element id corresponds to the desired element. I.e. you would need to use http://example.org/fhir/StructureDefinition/LocalizedPatientProfile|2.1.1#Patient.name.given:foo where 'foo' was a slice that referred to the first middle name in order to tie to a definition that specific.

To use this method:

  1. Traverse the QuestionnaireResponse from its root through each item iteratively, based on the structure in the Questionnaire.

  2. Allocate fullUrl uuid variables (if needed): If an extracted resource needs to reference a resource that is created within the transaction bundle it requires a known entry.fulUrl value (as a new uuid value for each resource instance). The extractAllocateId extension can be used to allocate a named new uuid for this purpose. It should be defined on the item (or root) such that its children cover the resource that is to be created, and also the resources that are to reference it. This variable name can then be used in the definitionExtract extensions's fullUrl FHIRPath expression, and also in any reference properties - typically using the definitionExtractValue extension (further described below).

    • This string value is not a FHIRPath expression to be evaluated, it is the name for the variable that will be available to FHIRPath expressions.
    • The allocateId extension will be made available to all FHIRPath expressions on that node, and any child items.
    • Use the variable name in the allocateId to set the entry.fullUrl of the resource you want to reference in the definitionExtract extension's fullUrl property.
    • Use the variable name to set the reference property using the definitionExtractValue extension's expression property.
    • If this allocateId extension is defined at the root of the questionnaire, a single value will be allocated for the entire extracted transaction bundle.
    • If this allocateId extension is defined on a repeating group, a new value will be allocated for each repetition of the item.
    • It is recommended to use meaningful names in the allocateId extension value, e.g. %newPatientUuid or %newEncounterUuidIf the extracted resource being referenced repeats (multiple instances could be extracted), then the extract rules for the resources that reference that repeating item must also be within the same repeating group item in order for them to use the same allocated id.
  3. Initiate Resource extraction: Include the definitionExtract extension on either the Questionnaire root or on other items within the Questionnaire to mark the point at which a new resource will be extracted (and what resource type/profile if applicable).
    This is a complex extension that includes the following properties: definition (resource/profile canonical URL), and optionally fullUrl, ifNoneMatch, ifModifiedSince, ifMatch and ifNoneExist (FHIRPath expression expressions used to populate the transaction bundle entry containing the extracted resource).

    • If the extension is at the root of the Questionnaire, the resource will always be extracted, even if there are no answer items within the fully completed QuestionnaireResponse.
    • If the extension is on a specific item, the resource will only be extracted if there are answers to that item in the QuestionnaireResponse. (For items that repeat, a new instance of the resource will be created for each repetition).
    • If the resource is created by a profile definition rather than a core resource type profile, the profile name will be added to the meta of the extracted resource.
    • Once the resource is completely extracted, the system SHALL populate the bundle.entry.resource property with the extracted resource, then populate the other bundle.entry properties:
      • fullUrl - the result of the FHIRPath expression for the fullUrl property, if none is provided, a new uuid will be allocated for the resource. (this will often be an expression that uses the named variable from the allocateId extension e.g. %newPatientUuid)
      • request.method - if the resource has no id property set the value to POST (requesting a create), otherwise set the value to PUT (requesting an update).
        The resource.id could be set using a hidden item (pre-populated during data-entry), or using the definitionExtractValue extension.
      • request.url - if the resource is being updated the url will be the resource type and the id property of the resource. e.g. Patient/123, otherwise it will be the resource type. e.g. Patient.
      • request.ifNoneMatch - the result of the FHIRPath expression for the ifNoneMatch property
      • request.ifModifiedSince - the result of the FHIRPath expression for the ifModifiedSince property (evaluates to a date time value - or nothing)
      • request.ifMatch - the result of the FHIRPath expression for the ifMatch property
      • request.ifNoneExist - the result of the FHIRPath expression for the ifNoneExist property
    • There can be multiple of these extensions interleaved on separate items, and also on the same item. However the definition property in the extension SHALL be unique in the scope that they are introduced in the questionnaire. i.e. You can't define two http://hl7.org/fhir/StructureDefinition/Condition extractions on the same item (or any of its children), but you can have multiple on sibling items do this.
      You could however have different profiles of the same resource overlapping. This is due to the definition property being the "scoper" to identify the resource/property to extract the item answer into.

    Note: In previous versions of the SDC specification the itemExtractionContext extension was used to indicate the resource type, however this has been deprecated and we encourage moving to the newer definitionExtract extension.

  4. Indicate properties to populate in extracted resource: For the item and any descendant items of an item (or root) with the definitionExtractValue extension:

    • Set the Questionnaire.item.definition to associate an answer to the item with a property in the extracted resource.
      Note that the canonical URL to the profile in the definition MUST match the canonical URL in the definitionExtract extension (or the canonical URL of the resource type in the deprecated itemExtractionContext).
      (when interleaving profiles, the definitionExtract extension is the "scoper" for the property to extract the answer into).
    • In cases where you need to make a group item match up with a collection, or backbone element in the StructureDefinition, just use that element to connect them.
      e.g. Use the definition: http://hl7.org/fhir/StructureDefinition/Patient#Patient.name on a group item to collect the child items to the same Patient.name element. During extraction, the system will create a new patient name element for each repetition of the group item, and then populate each name with the child items.
      With this example, the nested child items would have definitions like http://hl7.org/fhir/StructureDefinition/Patient#Patient.name.given and http://hl7.org/fhir/StructureDefinition/Patient#Patient.name.family.
    • Items are not required in the questionnaire for every element level in the StructureDefinition. The system will create the necessary elements as needed.
      e.g. You could have a single item that captures Patient.contact.name.text and the system will create the necessary Patient.contact and Patient.contact.name elements to then set the text values in. In this case if the item was repeating, the last node in the iteration is the one that will be repeated (name in this case).
      If you intend to have a specific level of the element repeated, you should have a group item that repeats, and then have the item that corresponds to the element within that group.
      This technique is particularly useful when populating properties in CodeableConcepts, where you can drill directly into the Coding, or text property, and don't require another level in your questionnaire just to add that in.
    • Add definitionExtractValue extension(s) to the root/item to specify calculated or fixed values to populate into the resource when an answer for this item is entered (or always when at the root of questionnaire).
      This is particularly useful for populating fixed values, or calculated values that are not directly entered by the user.
      e.g. To assign the value from the QuestionnaireResponse.subject property into a property in the extracted resource.
      If definitionExtractValue is used on an item that also has its item.definition property set, that would be assumed to be extracted resource context. Hence you could set the system and type values in an identifier when associated with that item.
    • If a profile is used in the definition, any fixed values or patterns in the profile will be included in the extracted resource. These MAY be processed when stepping through sliced properties in the profile.
      e.g. To set other properties in an identifier property that is associated with a specific slice, such as a fixed system and type value.
    • Although the answer for a QuestionnaireResponse.item can repeat (indicated by the repeat property), the evaluation of the item will only occur once, and the multiple answers are processed for the one item at the same time. For FHIRPath expressions, the answer will be a list of values (for the one item) that the expression must handle correctly to populate the item.
      e.g. If the item was for Patient.name.given (which can repeat), that "set" of answers will directly map into the resource property (which is also a collection). However if you tried to map that into the text property, which is singular, this would be an error. A FHIRPath expression would be required to concatenate the values together such as answer.join(', ').
      As "group" items iterate differently to "question" items, the evaluation will process each iteration of the group separately.
    • Some type casting will be required as not all data-types are available in questionnaire items, however these can all be mapped.
  5. Matching parent/child properties in the extracted resource instance: As described above, the system will create the necessary elements in the resource as needed, but this is not always obvious what to do when it's not a direct 1..1 mapping from the questionnaire to the resource.
    So this table is here to help guide the process with examples of how to populate the resource properties based various parent/child questionnaire item configurations:

    Example Parent

    Parent Type

    Example Child Definition

    Possible Child Type

    Notes

    Patient

    definitionExtract

    Patient.name

    group item

    Create a new HumanName object and add it to the name collection in patient

    Patient.name

    group item

    Patient.name.text

    value item

    Set the text property in the name object

    Patient

    definitionExtract

    Patient.name.text

    value item/extractValue

    Create a new HumanName object, add it to the name collection in patient, and set the text property

    Patient

    definitionExtract

    Patient.identifier.value

    value item/extractValue

    Create a new Identifier object, add it to the identifier collection in patient, and set the value property

    Patient

    definitionExtract

    Patient.extension

    group item

    Create a new Extension object and add it to the extension collection in patient

    Patient.extension

    group item

    Patient.extension.value

    value item

    Set the value property in the extension object

    Patient.extension

    group item

    Patient.extension.url

    value item/extractValue

    Set the URL property in the extension object

    Patient.extension.value

    value item

    Patient.extension.url

    value item/extractValue

    Set the URL property for the same extension instance that has the value in it (walks up the tree to the common ancestor)

    Patient.identifier.value

    value item

    Patient.identifier.type.text

    value item/extractValue

    Create a new CodeableConcept object, add it to the type collection of the identifier object that has the value in it, and set the text property in that type object

    Note: Anywhere in a resource that you need to set multiple item's values into properties of a backbone element, you will need to use a group item to collect the values together, and set the definition property on this group item to the backbone element. The system will then create the backbone element and populate it with the child items.

  6. Handling sliced properties: If extracting a property via a sliced property:

    • If there are any associated fixed or pattern values in the slice, also populate those values into the resource instance
    • If the slice limits the types supported, ensure that the created type is supported (and cast the value if required)
    • After the property is extracted, if there are any required properties that have fixed/pattern values, also extract those
      e.g. In the body height profile, the category slice VSCat is required, and has a required coding property with a fixed value of "vital-signs". This would also need to be extracted.
    • A type slice can be invoked without an actual slice for choice typed properties e.g. value[x]
      The extraction process is able to determine the correct type to use based on the answer in the QuestionnaireResponse, or explicitly define it in the property name in the "definition" value e.g. http://hl7.org/fhir/StructureDefinition/Observation#Observation.valueQuantity
      This type slicing is really only required where the type is a choice and the value being set is not directly coming from the QuestionnaireResponse item and there is no ambiguity on the type to use. E.g. assigning an item to Patient.extension.value.code could be a Quantity or a Coding, thus needs to be disambiguated. Patient.extension.valueCoding.code or Patient.extension.valueQuantity.value would be the appropriate definitions to use. However if I was using the definition Patient.extension.value and the item was of type boolean or Coding, there is no need to type slice, as the value is of the correct type to just assign (it doesn't need to create the intermediate valueQuantity or valueCoding before trying to set the actual value from the item).

    (These could also be considered at the root level when processing a profiled resource)

  7. Supporting the extraction process: If necessary, define items with the hidden extension that have Questionnaire.item.initial.value[x] or that use the questionnaire-initialExpression extension to define their content to use to populate resource elements that the user will not be filling in. (The initialExpressions might in turn depend on variable and questionnaire-launchContext extensions, used as described in the Expression-based population section, however that evaluation is all outside the scope of the $extract operation, and those variables are not available to $extract processing.
    This is particularly useful for retaining the resource ID of a resource that is extracted to use to update the resource (method = PUT).

Note: The extraction processes as defined does not support "merging" the answers into an existing instance of a resource as an update. Instead the "update" mode of this extraction process is a "replace" style process. So if you need to update content that was not created by the extraction routine, you will need to inject ALL data from the resource into the questionnaire (and hide properties as needed). This way all the data will be available to fill out into the resource so that it can be included as an update in the outgoing transaction bundle. This design was used as the target server for the bundle isn't necessarily going to be the same server that was pre-populated from.

Other considerations and rules when using this approach:

Template-based extraction

Profile:

Relevant Extensions:

Example Questionnaires:

The template based approach provides an alternative to the definition based approach and where the full power of StructureMaps isn't required. It supports the same level of capability, however is unable to leverage any of the information inside a profile where the definition based approach can.
The SDC Questionnaire Extract - Template profile has been created to support this mechanism.

This technique is called "template-based" because it uses a template resource(s) to provide all the "boiler-plate" content for the resource that is to be extracted. These templated resources are contained within the Questionnaire resource and referred to by either the sdc-questionnaire-templateExtract or sdc-questionnaire-templateExtractBundle extensions.

The template is annotated with expressions to indicate which parts of the template should be populated with data from the QuestionnaireResponse, and which parts should be removed if no data is present. The expressions are defined using the FHIRPath language, and the QuestionnaireResponse context of the expressions is based on the location of the template reference in the questionnaire, and/or any inline context expressions defined in the template.

The difference between the templateExtract (resource) and templateExtractBundle extensions is that the template resource extension will extract each resource individually as a separate bundle entry and includes expressions to populate the other bundle entry properties, whereas the template bundle extension extract the transaction bundle as a single resource. The processing of the template is otherwise identical between the two extensions.

To use this method:

  1. Include the sdc-questionnaire-templateExtract extension at the root or the questionnaire, and/or any items in the questionnaire that indicate a resource should be created for each answer in a questionnaire response for that item.
    This extension includes a relative reference to the resource template which SHALL be contained within the same Questionnaire resource, and will be extracted into a new entry in the output transaction bundle (with other values processed from the complex extension).
    Alternately use the sdc-questionnaire-templateExtractBundle extension at the root to use a template bundle. This is the same as the templateExtract extension but leverages a single bundle that has all templated resources in it.

  2. Include any required template resources as contained resources in the questionnaire and refer to them using either the sdc-questionnaire-templateExtract or sdc-questionnaire-templateExtractBundle extension as described above.

  3. If you need to dynamically reference between resources created in the output transaction bundle (using the entry.fullUrl property), include the allocateId extension at a point in the questionnaire that defines the scope that a new uuid is required for each iteration of the item. If at the root, a new value will be allocated only once, if on an item, it will be allocated for each related item that has the extension (a new value per item in a collection). The value is only available to child items of the item that has the extension (or itself).
    This value can be used in the templateExtract extension to set the fullUrl property of the extracted resource, and in the templateExtractValue extension to set the value for the referencing property.
    The allocateId extension is not a FHIRPath expression to be evaluated, it is the name for the variable that will be available to FHIRPath expressions, and it's value will be a new uuid for each iteration of the item that has the extension, before any expressions in the templateExtract, templateExtractBundle or templateExtractValue are evaluated.

  4. During extraction a new resource will be created for each answer in the QuestionnaireResponse for the item that contains the templateExtract extension.
    The resource.id of the new resource will be removed (as it currently has the resource id to refer to in the template from the questionnaire definition). To set the resource.id property use the resourceId property in the templateExtract extension (this is not possible using the templateExtractBundle based extraction).

  5. The FHIRPath context of the extracted resource will be based on the location of the templateExtract extension in the questionnaire.
    If templateExtract is on the root of the questionnaire, the FHIRPath context will be the QuestionnaireResponse resource.
    If templateExtract is on an item, the FHIRPath context will be the item in the QuestionnaireResponse associated with that item's linkId.

  6. The extraction engine SHALL scan the templated resource for any sdc-questionnaire-templateExtractContext or sdc-questionnaire-templateExtractValue extensions (in that order) and then:

    • Evaluate the FHIRPath expression defined in the extension (only FHIRPath is supported).
    • If the expression returns no results, this templated property (context or value) will be removed from the extracted resource, and no further processing of that property will occur.
      If the template property is a in a collection, simply remove the templated value from the collection, don't clear the entire collection. There MAY be other templated properties to process in the collection (or static template data).
    • For every result returned by the expression, a new copy of the templated property will be cloned and scanning the child properties will continue.
    • If the context expression is defined as an Expression datatype, and it has a name property, then that variable will be made available to any child property extraction expressions.
    • Any context results will change the context to use for processing any child properties (and templateExtractValues on the same node).
    • Any extractValue results will be used to replace the property value in the extracted resource.
      Note that for primitive properties in json the _value and value represent the same FHIR property and must be considered the same property. So ensure that the extract extension is removed from _value, the value is set (and any other extensions can remain).
      This is important as some properties such as reference properties are required to have a valid value and not just an extension so they will have a value that is expected to be either removed (when no data) or replaced (when data is present).
  7. When using the templateExtract extension (not the templateExtractBundle extension), the extraction engine SHALL create a transaction Bundle containing all the resources that were extracted from the QuestionnaireResponse. Each resource that is extracted will be added into the transaction bundle that is returned by the $extract operation.
    The fullUrl, resourceID and entry.request properties SHALL be updated with values calculated from the templateExtract complex extension.
    If a resource has it's ID populated, then it will be treated as an update to the existing resource (entry.request.method='PUT'), otherwise it will be treated as a create (entry.request.method='POST').

If FHIRPath expressions produce errors/exceptions or invalid/incompatible value types, the extraction engine SHALL log the error and continue processing the next property. If there were any fatal or error level issues, the extraction engine SHALL return an OperationOutcome with the issues.
If there are only warning/information issues, they can be returned along with the transaction bundle.

Template based extraction using the templateExtractBundle extension is incompatible with modular forms.
If using the templateExtract extension with modular forms, the assembly will merge all the contained resources from the module into the output Questionnaire, and may need to rename the contained reference ids if collisions are to occur.

Note: Many templating engines have constructs like conditionals and loops. Although not immediately obvious, these can be implemented using this template approach. Conditional properties are implemented with the FHIRPath expression in the templateExtractContext or templateExtractValue extension returning no results, and thus excluding the property, backbone element or entry in a collection from the extracted resource.
Loops are similar in nature where the looping is provided based on the FHIRPath expression returning multiple results, and thus creating multiple entries in an array, or even multiple resources in the transaction bundle driven by either multiple items in the questionnaire, or contexts in the bundle template.
There are several examples of both of these in the template examples here and here, such as how they create multiple names in the patient resource from multiple items in the questionnaire name item group, or where there is no IHI identifier added if the relevant item hasn't been answered in the questionnaire.

StructureMap-based extraction

Profile:

Relevant Extensions:

Example Questionnaires:

The StructureMap approach is the most sophisticated approach of the four - and the most powerful. It allows significant transformation of data, including code translations when generating output resources. It also allows the conversion process between data and Questionnaire to be maintained independently and to draw on shared sources across Questionnaires. This can be an advantage in certain environments where the content of the questionnaire may need tight control, but the data environment can be more dynamic. This comes at the cost of requiring expertise in the FHIR mapping language, which is not (yet?) a common skill.
The SDC Questionnaire Extract - StructureMap profile has been created to support this mechanism. An example for this profile can be found here.

To use this method:

  1. Include the questionnaire-targetStructureMap extension. This SHALL define a transform between the QuestionnaireResponse and either a single resource or a transaction Bundle containing the set of resources extracted from the QuestionnaireResponse.

To extract data from the completed QuestionnaireResponse, simply invoke the StructureMap on it. A sample Questionnaire and associated StructureMap that shows this approach can be found here and here.

Considerations when using this approach:

Output expectations

Following are the output expectations of $extract: