Structured Data Capture
3.0.0 - STU 3 International flag

Structured Data Capture, published by HL7 International / FHIR Infrastructure. This guide is not an authorized publication; it is the continuous build for version 3.0.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/sdc/ and changes regularly. See the Directory of published versions

Modular Forms

Page standards status: Draft

Modular Questionnaire Background

Maintaining questionnaires can take a considerable amount of effort, particularly if they include logic to support population or extraction. At the same time, it is common for questionnaires to share content - the same questions or even the same sections might appear in multiple forms. Some organizations, particularly those with a research focus may have extensive libraries of questions intended to help drive re-use and consistency. This allows those organizations to increase consistency in how data is collected, which in turn increases the comparability of data captured, even when captured using different instruments. It also increases the quality of the data collected by encouraging the re-use of questions that have been vetted for readability, neutral phrasing and other quality considerations.

Achieving re-use with questionnaires is primarily focused on the benefit of authors. The use of modularization techniques is often transparent to the end users who must complete the questionnaires, unless they find themselves filling out many distinct forms and happen to notice the consistency of language and sections between those forms. In other words, questionnaire re-use is part of the authoring and publishing process, but generally not the form filling process.

Modular questionnaires should adhere to this SDC profile. An example for this profile can be found here.

This portion of the SDC specification describes two mechanisms for enabling re-use:

  • Modular Questionnaires allow one questionnaire to be composed of sub-questionnaires (which can in turn be composed of further sub-questionnaires, and so on).
  • Data Element-based Questionnaires are crafted by having items make use of the definition element. The referenced definitions include all of the metadata for the question, group or display item including the text, data type, optionality and other characteristics. Questionnaires are authored by assembling these minimal items referencing robust definitions.

In the first case, every single 'item' in the questionnaire must be specified, including all 'display' items, groups, etc. Re-use is limited to question text, value set, data type and other information that can be determined from the referenced definition element. On the other hand, with modular questionnaires, multiple items can be defined along with display text, enableWhen logic and other questionnaire characteristics. The first approach is best suited for "data-element"- based questionnaires and the latter for defining collections of questions. (While defining separate modules for every single question is possible, it would be quite a bit of overhead).

The two mechanisms are not mutually exclusive. It is possible to have a form that relies on sub-questionnaires and that also has some elements that rely on externally defined element definitions.

Modular workflow

Regardless of mechanism, there are two phases. First, the questionnaire is authored in its modular form, maximizing re-use and minimizing authoring effort. Then, there is then a need to take the re-useably authored form (or collection of forms) and generate a fully 'assembled' form that contains all of the details needed for a Form Filler to properly render and capture answers for the form. While this assembly process can be undertaken by the Form Filler, it is more typically managed by the form designer as part of the publication process.

The following diagram shows the results of the assembly process with a set of questionnaires that combine both approaches:

One parent questionnaire refernging two sub-questionnaires, which each in turn reference elements in a StructureDefinition,            followed by the resulting single assembled questionnaire

The first questionnaire (Q1) contains two items, each with a sub-module extension pointing to other questionnaires - Q2 and Q3. Those two sub-questionnaires in term make use of the 'definition' element to refer to data elements from a single StructureDefinition. (In practice, the elements could as easily have been pointed to from a variety of StructureDefinitions.) The assemble operation then produces a new instance of Q1 that combines all of the items referenced from the two sub-modules and brings in the question text and other metadata from the referenced element definitions.

The assembly process can be done internally or by invoking the $assemble operation. Questionnaires might use any combination of defining content traditionally (i.e. all item details defined inline), referencing sub-questionnaires, and/or referencing external data elements. There is also no theoretical limit to the amount of nesting that can happen with sub-questionnaires, though practically more than 2-3 levels of nesting are very unlikely.

When working with modular questionnaires, the 'assembly' step should be performed prior to any population steps.

Finding and distinguishing modular/assembly-relevant forms

It is helpful to know when a Questionnaire is going to require assembly or not. It is also helful to know whether a particular questionnaire can be used as a 'root' form for entry, can be used as a sub-module or either. A system can search through for items that declare the subQuestionnaire extension, though doing so isn't terribly efficient. However, for Data Element-based Questionnaires, there is no mechanism to tell with certainty that assembly is required - the 'definition' element may be included in questions for a variety of reasons and some degree of metadata may be maintained in the 'master' Questionnaire for readability. Therefore, this specification defines a assemble-expectation extension that allows flagging whether a particular Questionnaire requires assembly, whether it is safe to use as a subQuestionnaire and/or whether it can be used as a 'root' Questionnaire.

code $assemble before use? Can be subQuestionnaire? Can be root questionnaire?
assemble-root-or-child Yes Yes Yes
assemble-root Yes No Yes
assemble-child Yes Yes No
independent-root-or-child No Yes Yes
independent-child No Yes No

There is no code for a questionnaire that's intended for use as a stand-alone form, doesn't require assembly and isn't intended for use as a child form, because that's the default.

In addition to these codes, the code system has a few additional abstract codes that are only available to aid in searching:

  • assembly encompasses all codes that mean assembly is required and independent encompasses all codes that don't require assembly (though it won't include Questionnaires where the extension isn't present at all). E.g. to find all Questionnaires that don't require assembly, you would search Questionnaire?assemble-expectation:below=independent as well as Questionnaire?assemble-expectation:missing=true. Alternatively, if 'missing' and 'below' aren't supported, you could simply use Questionnaire?assemble-expectation:not=assemble-root-or-child,assemble-root,assemble-child.
  • root encompasses all codes that mean the form can be the 'root' for data entry. To find all Questionnaires that can be the root for data capture, you would search Questionnaire?assemble-expectation:below=root as well as Questionnaire?assemble-expectation:missing=true. Alternatively, if 'missing' and 'below' aren't supported, you could simply use Questionnaire?assemble-expectation:not=assemble-child,independent-child.
  • child encompasses all codes that mean the form can be used as a sub-module. To find all Questionnaires that can be safely used as sub-modules, you would search Questionnaire?assemble-expectation=assemble-root-or-child,assemble-child,indelpendent-root-or-child,independent-child.

Modular Questionnaires

The notion of a modular Questionnaire is that a 'display' item in a parent questionnaire can include an extension pointing to a specific Questionnaire whose items should be embedded in the resulting assembled Questionnaire in place of the 'display' item. The details of how this works are as follows:

  1. The subQuestionnaire extension will contain the canonical reference to the Questionnaire whose content should be substituted for the display item
  2. The canonical reference SHOULD be version-specific to ensure that the author of the parent questionnaire has full control over what content they are importing. If the subQuestionnaire is not version-specific, then the same version of the parent Questionnaire could include varying items as the subQuestionnaires evolve and this is considered an error. I.e. if canonical references are not version-specific, the content of the referenced Questionnaires cannot change in a way that results in differences in allowed QuestionnaireResponses.
  3. It is possible that the assembly option will be unable to substitute the display item for the referenced Questionnaire or that the system that tries to make use of the modular Questionnaire might not recognize or be able to support assembly of the Questionnaire at all. For this reason, the 'text' of the display element SHOULD say something that is meaningful in situations where it is not replaced. For example: "Sub-questionnaire [some URL] not available. Unable to display all questions."
  4. When the Questionnaire goes through the 'assembly' process, the display item having the subQuestionnaire extension will be removed entirely. I.e. that linkId and the associated text will not appear in the assembled Questionnaire. Instead, all of the 'root' items of the referenced Questionnaire - including their descendant elements and items will appear in the same position as the replaced 'display' item was.
  5. In addition to propagating the items from the referenced Questionnaire, additional items are also propagated as follows:
    • All meta information, including security and other tags declared on the imported Questionnaire are ignored. (If a Questionnaire references a sub-Questionnaire with security restrictions, this needs to be reflected in the referencing Questionnaire as part of its original design
    • If language is declared on the imported Questionnaire, it must match the language on the importing Questionnaire.
    • implicitRules and modifierExtension are prohibited and are considered an error if present.
    • Any contained resources in the subQuestionnaire are added as contained resources in the parent Questionnaire with the exception that, barring linkIdPrefix requirements (see further below), if a subQuestionnaire is imported more than once, contained resources will only be included once in the assembled Questionnaire.
    • Extensions are propagated differently, depending on the nature of the extension:
      • propagate to the 'root' of the base Questionnaire:
        • cqf-library (check for uniqueness by url and only import once)
        • launch-context (check for uniqueness by code and only import once)
      • propagate to the item that contains the 'display' item being substituted. (If the display item is at the root, then this will also be at the root.):
      • all other extensions are ignored
    • All metadata elements on the subQuestionnaire are ignored. If there are copyright limitations on the referenced Questionnaire, it is the responsibility of the referencing Questionnaire to reflect those in its own Questionnaire.copyright element.
    • The assemble-expectation on the resulting Questionnaire should be adjusted to change the 'assemble' part of the code to 'independent', with the exception that if the code was 'assemble-root', then the extension should be removed entirely. E.g. assemble-root-or-child would change to independent-root-or-child.
  6. This process occurs recursively. I.e. If an imported Questionnaire contains display elements with a subQuestionnaire extension, those display elements are also replaced by the referenced Questionnaire, repeating the process until no further subQuestionnaire extensions are found.
  7. It is possible that the same Questionnaire might be substituted more than once as part of this process, however it is in an error if the module references recurse. E.g. if Questionnaire A contains an item that references subQuestionnaire B, which in turn has an element that references subQuestionnaire A.
  8. It is also an error if the resulting fully-assembled Questionnaire has any duplicate linkIds.
  9. In order to avoid duplicate linkIds, a parent Questionnaire MAY declare a special variable with the name linkIdPrefix. If there is a linkIdPrefix in context at the time a subQuestionnaire is substituted, that linkIdPrefix SHALL be pre-pended to the linkId and enableWhen.question elements of all items in that Questionnaire. See the examples to see how this works in practice. If linkIdPrefix is not used, care should be taken to ensure that linkIds are appropriately coordinated to avoid overlap across all referenced Questionnaires
  10. LinkIdPrefixes are also prepended to the 'id' elements of any contained resources and all references to contained resources (i.e. references or canonicals that start with '#').
  11. linkIdPrefixes will need to be referenced in any expressions that are dependent on linkId. For example, if there is an expression that says "%root.descendants().select(item.where(linkId='1.1'))" would need to change to "%root.descendants().select(item.where(linkId=%linkIdPrefix + '1.1'))"
  12. Imported Questionnaires may be defined to be dependent on contextual information passed in from the referencing Questionnaire (including 'linkIdPrefix'). To allow validating these subQuestionnaires independent of their inclusion in a parent, all such dependencies must be declared using the assembleContext extension on the root of the Questionnaire. As well, if a Questionnaire is referenced by a subQuestionnaire extension, it is an error if the listed variables are not available in the context of the referencing element.
  13. The presence of an assembleContext extension on a Questionnaire indicates that it can ONLY be used as a part of a modular Questionnaire.
  14. If stored, an assembled Questionnaire SHALL have the same URL as the base Questionnaire but must have a distinct version - typically either a UUID or "[version]-assembled"
  15. An assembled Questionnaire SHALL refer to the original base Questionnaire with a version-specific reference using the assembledFrom extension. Questionnaires can also be searched by this extension using the If a QuestionnaireResponse is based on an assembled Questionnaire, it SHOULD use the URL specified in the assembledFrom extension rather than the URL and version of the assembled Questionnaire itself.
We will set an expectation in SDC about what changes are permitted for 'active' questionnaires while keeping version unchanged and which changes force a new version.

Data Element-based Questionnaires

Data Element-based Questionnaires rely on the fact that Questionnaire 'item' elements largely correspond to the information found in the ElementDefinitions that are part of StructureDefinitions. These might be FHIR resources or data types, FHIR profiles, or logical models that represent any type of data at all. Full details on the mappings between Questionnaire.item and StructureDefinition.snapshot.element as well as general guidance on how definitions are to be mapped, including mapping to version-specific artifacts, mapping to slices, etc. are found in the FHIR core specification here.

The process for 'assembling' a Questionnaire that leverages Data Element-based mappings is as follows:

  1. For each item in the questionnaire, if an item.definition element is present, try to resolve the referenced element.
  2. If the URL refers to an element in a StructureDefinition and the StructureDefinition resolves but the referenced element does not raise an error.
  3. Otherwise, if the referenced element cannot be resolved, raise a warning unless the item has no text element or the item.type is 'choice' or 'open-choice' and no answerOptions, answerValueSet or answerExpression is available, in which case raise an error.
  4. Go through each property and extension on the element and see if the corresponding property or extension already exists on the Questionnaire.item. (Extensions are matched by URL and then 'value.name' if the extension is an expression.)
    • If the property or extension is not present (and the property has a mapping to a Questionnaire.item property or the extension is one allowed to appear on Questionnaire.item), then propagate the property or extension to the Questionnaire.item.
    • If the property or extension already exists, leave it as is, but provide a warning if the content in the element definition differs from that on the Questionnaire.item. I.e. Elements defined on the Questionnaire item override information found on the referenced definition, but a warning will be raised noting any discrepancies.
  5. If any of the properties include references to contained resources (e.g. a value set referenced by a binding), those resources should also be propagated. The Form Filler might need to re-assign the contained resource id (and update references) to avoid id collision. A given contained resource should only be propagated into the assembled Questionnaire once.
  6. If the item.type is 'group' and the group has no child items with a type other than 'display', then child question items of the appropriate type should be generated for each child element of the ElementDefinition pointed to by the item.definition. This process recurses. The linkId of the generated items should be a concatenation of the linkId of the group and the path of the element.
  7. Alternatively, if the item.type is 'group' and the group does have child questions, the child questions should be matched against the children of the ElementDefinition (using item.definition) and any ElementDefinition child elements not present as child questions should produce a warning.

If a system wants to create a library of 'questions' that can be drawn on by Questionnaires, this can be accomplished by:

  • using a single StructureDefinition as a logical model with elements for each item;
  • creating a distinct StructureDefinition for each item; or
  • a combination where there are multiple StructureDefinition 'sub-libraries', each with a collection of elements

The approach taken will depend on whether metadata such as status, publisher, etc. needs to be tracked on a per element basis or can be tracked at a higher level of granularity. Note that even when creating a separate data model for each item, some items may be 'complex', representing a 'group' with multiple child questions, and thus there will still be multiple elements in the StructureDefinition.

The only thing this implementation guide adds to the capabilities described in the base specification is the formal definition of the $assemble operation, including expectations of behavior for situations when the properties for an item in the base Questionnaire differ from those in the referenced definition.

Examples

This specification includes a simple set of examples that highlight the functionality of the two different modular questionnaire mechanisms. They also serve as test cases for systems that might want to check their support for the $assemble operation (or equivalent internal functionality). The files are as follows:

  • modular-root - A simple questionnaire with a couple of items of its own (some using definitions, some defined inline) as well as references to sub-questionnaires
  • modular-name - A re-useable questionnaire that can capture a person's name
  • modular-contact - A re-useable questionnaire that can capture a person's contacts
  • question-library - A library of re-useable questionnaire questions
  • modular-root-assembled - An assembled version of the modular-root questionnaire