Structured Data Capture, published by HL7 International / FHIR Infrastructure. This guide is not an authorized publication; it is the continuous build for version 4.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
Page standards status: Trial-use |
Contents:
The Form Behavior, Questionnaire Population and Data Extraction all rely on (or have features that rely on) the use of expressions. This page provides specific guidelines for use and defines some additional conventions that can be leveraged in queries, FHIRPath and CQL by implementations that comply with this implementation guide.
The Expression data type has 5 elements:
description
provides a human-readable explanation of what the expression is doing. This is development documentation. While
not required, it's strongly encouraged unless the expression is so simple there will not be any question as to its intent and function.name
allows the result of the expression to be referenced within other expressions. Whether this is necessary depends on the context.
(e.g. itemExtractionContext doesn't typically need a name when used for extraction of the element it is on.
However, if the value is leveraged in downstream itemExtractionContexts, then it will need a name. When an extension with a type of Expression has a name, the result of evaluating that expression becomes available in subsequent expressions (either
following extensions within the same element, or extensions appearing on descendant items) as a 'variable'. These variables are referenced by
prepending '%' to the 'name' of the expression. I.e. the result of an expression named 'patient' would be available for use in subsequent expressions
as %patient
.language
indicates the type of expression. SDC only uses three languages: FHIR queries as described below,
FHIRPath and CQL. Also see the discussion on
FHIRPath vs. CQL.
expression
contains the expression if it is written in-line (as opposed to by reference). In the case of CQL, this element may be instead used to contain just the name of an expression (aka identifier) found in a Library. (In this case the mime type is text/cql-identifier
instead of text/cql-expression
). Also see the additional guidance on the use of expressions in CQL.
reference
could theoretically be used to point to x-fhir-query or FHIRPath content maintained in libraries. However, so far no official syntax for managing or referencing such content in libraries is defined. Therefore, this element SHOULD
be omitted by SDC implementations."
CQL identifiers SHALL
be prefixed with the Library.name
(with a .
separator) if there is more than one Library in scope.
CQL identifiers also need to be qualified if they appear as part of inline CQL if they're referring to content found in a Library. In this case, it doesn't matter if there's only one Library.
Expressions are introduced into Questionnaires using extensions - none of the 'core' data elements of Questionnaire make use of extensions because they're considered an 'advanced' capability that is not currently supported by a large portion of the systems that make use of the Questionnaire resource. The extensions that make use of expressions are shown in the table below. Columns are interpreted as follows:
http://hl7.org/fhir/StructureDefinition/[code]
. Those from SDC will have
http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-[code]
Questionnaire
element), 'item' (for those that can appear on any type of item), 'question' (for those that can only appear on question
items), or 'group' (for those that can appear on group items). In some cases, additional restrictions/guidance will be provided.text/cql
" (CQL), "text/fhirpath
" (FHIRPath), or "application/x-fhir-query
" (query) or is unrestricted (any)Beneath each extension row is an explanation of the purpose of the extension and guidance on its use.
Extension | Source | Location | Content | Use Cases | Example |
---|---|---|---|---|---|
variable | Core | Questionnaire, item | any | all | example |
This expression sets a variable that is available for use in expressions within the same item and any descendant items. It has two main uses:
The content type of a variable can be pretty much anything. It can be a collection or an individual item. It can be a simple element, a complex type, a resource or even a Bundle of resources.
The variable can be referenced by its name. Variable expressions |
|||||
answerExpression | SDC | question | any | population | example |
This is the most sophisticated of the three different mechanisms for defining the allowed set of answers to a set of questions.
(The others being the Questionnaire.answerOption and the answerValueSet core elements.
(This extension is mutually exclusive with the other two mechanisms.) This expression must evaluate to a collection
of elements with the same type as the
This expression could be based on other answers within the questionnaire. If the allowed set of answers for a question change
after an answer has been specified (whether via population or user entry), the prior answer
If an answer becomes invalid based on evaluation of answerExpression, calculated values falling out of range, etc., the form Note that if the answerExpression relies on content outside the QuestionnaireResponse (e.g. launch context or query results), the ability to consistently check the validity of the QuestionnaireResponse - particularly for downstream systems - may be difficult. One potential solution is to populate internal (and potentially hidden questions) with information passed in by context or found through query such that validation of answers can be based entirely on information stored within the QuestionnaireResponse, though privacy and/or storage considerations may make this impractical in some cases. |
|||||
initialExpression | SDC | question | any | all | example |
This expression serves the same purpose as the initial.value on Questionnaire.item, except that rather than specifying a fixed value, the value is calculable. Like initial.value, initialExpression is evaluated only once. The value is set on initial creation of the QuestionnaireResponse or upon the question first becoming enabled. NOTE: This implementation guide does not prohibit lazy initialization (e.g., delayed calculation of an answer, delayed initialization of a field, etc.), but Questionnaire authors cannot assume implementors will use lazy initialization. If used for a readOnly and/or hidden element, initialExpression essentially calculates a 'fixed value' for the element. If used for an editable element, this extension sets the initial value for the element. Since both initial.value and initialExpression generate values before the user has access to the form, it is not allowed to have both present on a Questionnaire.item. In scenarios where the user edits the response directly or edits other dependent elements that cause the re-evaluation of the response (e.g., calculatedExpression), the value MAY subsequently be overridden by the user authoring or editing the response (see considerations in Expression-based Population). In theory, this expression can rely on the values of the answers to child questions or on variables calculated from the values of other questions, however such questions would have to have initial values (see the discussion below on dependencies). Most typically, it will draw on launchContext extension and itemPopulationContext extension to populate questionnaire elements based on information available from outside the QuestionnaireResponse. Examples of use for Form Behavior might include defaulting one date or provider in a form to one entered earlier in the form, defaulting a selected location based on patient address, etc. For population, this is the primary mechanism of populating fields. Information passed in launchContext or queried from the health record is used to determine the initial value for the field. The response author then can review and potentially adjust the values. Finally, for extraction, this can be used to fill in 'hidden' elements that are needed for extraction but are not actually seen or edited by the user (e.g., FHIR resource ids when updating existing records). It is possible for the value of an initialExpression to be referenced by name within other sibling expressions or by expressions on descendant items. However, this is not likely to be common. As such, initialExpressions only need to declare a name if their value will be referenced elsewhere. |
|||||
candidateExpression | SDC | question | any | population | example |
This extension is used to support data entry. It is only invoked when the user is entering/editing the answer for the question linked to the candidateExpression. It is used when a population process cannot determine the specific value to fill in to a form (like when an answer depends on answers to other questions that are unknown at the population phase), but it can identify a list of candidates to choose from. For example, forms might ask for relevant co-morbidities, other practitioners to inform, etc. The specific answers require human decision-making, but this expression can provide a list of initial candidates based on the patient's recorded health conditions, the patient's care team members or others involved in their care, etc. Another example might be filtering a list of possible dosage instructions based on the patient's age, gender and the previously selected indication but where there are still possibly multiple recommended options. While this expression could be based on other answers within the questionnaire, most typically it will be based on information found within the health record. The expression must evaluate to a collection of elements with the same type as the question answer. For choice and Reference questions, choiceColumn can be used to manage display.
NOTE: the set of candidate expressions is intended to be a starter set, not exhaustive. The user needs to be free to enter or look-up additional
values. The overall set of values from which answers are allowed to be selected (typically independent of what happens to be in the
patient record) is defined by answerExpression. Systems As an example, a question might ask "Please identify any concurrent medications that might be related to the reaction". A candidateExpression could provide a list of all of a patient's known current medications (via medicationrequest, medicationstatement, etc. On the other hand, an answerExpression might evaluate to the value set of medications appropriate for the jurisdiction in which the questionnaire is being completed, allowing the user to select medications that were not listed in the patient's record in addition to the candidates found. CandidateExpressions may use name in situations where a user will select a candidate for one question which will in turn lead to population of other questions. For example, if in the above example, a question about concomitant medications might have child questions that capture information about the dose, start date or other information. The query that returned the candidates might be referenced by name in initialExpressions for child questions that use the parent answer together with the candidates to grab the additional details about the selected medication to populate the child answers. |
|||||
contextExpression | SDC | question | any | population | example |
This is similar to candidateExpression extension, in that it is also only used when the user is editing the answer for the question associated with the candidateExpression. However, instead of giving candidate answers that can simply be "selected", this option instead presents potentially relevant information. For example, a question might be "Has the patient been admitted for this or a related condition in the past year?". To help guide the answers, the contextExpression could retrieve a list of admission reasons for that patient for encounters in the past year and display that with a label of "Reasons for admissions in the last year". The user completing the questionnaire could then use that information to guide whether they choose to answer 'yes' or 'no'. The extension is complex including both an expression that defines the results to make available as well as a label so the user completing the Questionnaire understands what the data being returned means. ContextExpression is not intended for read-only questions. The user must answer a question - but the user may want to look at context information to help guide the answer. Also, like candidateExpressions, contextExpressions will rarely, if ever, declare a name element. |
|||||
calculatedExpression | SDC | question | any | behavior | example |
This expression allows for dynamic calculation of answers to questions as other questions are answered. It behaves similarly to initialExpression extension, but instead of only setting its value when the QuestionnaireResponse is originally created or when a question is enabled, the value updates continuously as the answers to dependent questions change. This expression will be most used for displaying scores, but can be used for any calculated element - patient age (based on current date and birth date), BMI (based on recent weight and height), estimated cost (based on selected items and quantities), etc. Managing the updating of calculatedExpressions can be tricky as they can have many dependencies. Implementing an event-based listener approach may prove more efficient than simply recalculating all expressions every time any value in the questionnaire changes anywhere. Also, refer to the section below on dependencies that explains how to handle order of evaluation and other concerns.
In most cases, 'calculated' answers will be marked as 'readOnly', however in some cases it may be legitimate to override a calculated element,
for example if the calculation cannot be made due to non-available information, but the user still knows the calculated value. This statement applies
to any context information of any sort. [For example, it might be possible to enter an age but not a date of birth. If a user has edited a calculated value,
it Like initialExpression, it is possible for the value of a calculatedExpression to be referenced by name within other sibling expressions or by expressions on descendant items. However, this is not likely to be common. As such, calculatedExpressions only need to declare a name if their value will be referenced elsewhere. NOTE: query information can change over time and thus influence the results of calculatedExpression. |
|||||
enableWhenExpression | SDC | question | FHIRPath or CQL | behavior | example |
This expression does the same thing as the Questionnaire.item.enableWhen structure (and is mutually exclusive with it), but allows for more complex logic like nested bracketed expressions with AND/OR, use of NOT, comparison of values across questions, etc. (If enableWhen can meet the need, it ought to be used instead as it will be more broadly supported.) Specifically, enableWhenExpression allows more complex logic such as support for different types of logic operators (e.g. 'and', 'or', 'not', 'nand', 'nor') among conditions and a mixture of them (e.g. "Enable if Q1=5 and Q2 nand Q3 are true"). It also allows for logic to be based on calculations across questions (possibly leveraging variable) or even based on values passed in by launchContext or queried from outside the questionnaire. Like calculatedExpression extension, enableWhenExpression needs to be evaluated each time any of the answers it depends on changes. The same event monitoring approach may be appropriate (and even shared). And the dependencies section will be relevant here as well. The Expression.name element only needs to be populated in the unlikely circumstance the expression is going to be referenced by other expressions on the same item or in descendant items. |
|||||
answerOptionToggleExpression | SDC | choice, open-choice | FHIRPath or CQL | behavior | example |
This is a complex extension that performs a similar function to enableWhen, except that rather than acting on items, it acts on individual answer options within
an item. The extension does NOT define what options exist. Instead, it toggles a subset of the possible options (specified in the
The base set of options available comes from answerOption, answerValueSet
or answerExpression. If any of the options listed in the More than one repetition of this extension is possible. If an option appears in more than one repetition, then it SHALL be enabled if it appears in ANY of the extensions whose expressions are evaluated as true. I.e. the expressions that pertain to a given option are treated as 'or'. AnswerOptionToggleExpressions will generally never need a 'name' declared. |
|||||
itemPopulationContext | SDC | any | any | population | example |
This expression identifies the resource(s) that correspond either to an overall questionnaire, a group within the questionnaire or, occasionally, a single question. The results of executing the specified expression are used to indicate the resources used to populate the item when performing population and also indicate the relevant resource type. If an expression results in multiple repetitions for a single for the root Questionnaire or for an item where 'repeat' is false, it is an error and no population can occur. This expression does not actually populate an element (that's handled by initialExpression). Instead, it establishes a variable that is used to aid in population, often by providing a variable that can be used within the initialExpression that determines what the element is be populated with.
|
|||||
targetConstraint | Core | Questionnaire, item | any | behavior | example |
An invariant that SHALL or SHOULD be satisfied before responses to the questionnaire can be considered "complete". It contains an expression as part of the complex extension, but SHALL never have a 'name'.
Note: The relative path SHOULD follow the same syntax as |
Please note that the expressions in calculatedExpression, initialExpression and answerExpression are expected to resolve to the same type as the question type, allowing for the [implicit conversions](http://hl7.org/fhirpath/#conversion) defined in FHIRPath. The only exception is that an expression that resolves to a Resource can satisfy a question of type 'Reference', in which case the result will be treated as a Reference to the returned resource.
Ordering of environment-variable extensions: When extensions define an environment variable (i.e. information that can be accessed in FHIRPath or CQL using
'%' followed by a name), then for readability, those extensions SHOULD
be ordered such that the extension that defines an environment variable always appears
on a higher node, or earlier on the current node, than an extension with an expression that uses that variable. However, tools cannot rely on this ordering occurring. For
example, if there's a launchContext extension that defines the %patient
environment variable and a variable extension that defines %patientContact that leverages %patient,
then the launchContext extension would logically be declared in the instance hierarchy prior to the variable extension, but systems can only assume that the extension
is declared on an ancestor node or on the same node, not necessarily prior to the location where it's used. If a reference is not resolved once all in-scope extensions have
been processed, that SHOULD
be treated as an error.
There are a couple of additional extensions that are also relevant when working with expressions. They are:
Extension | Source | Location | Use Cases | Example |
---|---|---|---|---|
library | core | Questionnaire | all | example |
Library allows queries, CQL and FHIRPath expressions to be maintained independently from the Questionnaires that use them. This means that the "programmatic" content of the Questionnaire can be updated and adjusted without revising the Questionnaire, which may be appropriate in certain form management environments. It also means that the population and extraction mechanisms can be adjusted as data representations evolve or be adjusted to reflect the needs of additional data repositories. Additionally, it allows re-use of expressions across questionnaires. This extension identifies libraries that the questionnaire relies on for some or all its expressions. (The mechanism by which expressions point to library content is discussed above.) |
||||
launchContext | SDC | Questionnaire | all | example |
The launch context allows information to be passed into the execution environment based on the context in which the Questionnaire is being evaluated. For example, what patient, what encounter, what user, etc. is "in context" at the time the questionnaire response is being completed. Note that this context could potentially change if a questionnaire is edited after it was initially created, which means that if launchContext elements drive calculatedExpression elements rather than initialExpression elements, they'll be updated to reflect the new user.
Launch context information is passed to the QuestionnaireResponse evaluation process by the launching application. It SHOULD pass whatever contexts
it is aware of. SDC systems The resource corresponding to each context SHALL be made available at the indicated launch context name as if the value had been set in a variable. It is not allowed to define names that are already reserved by the base specification or by other variables in the questionnaire. |
Not all sdc extensions are available in all places. Specifically the $extract (definition and template) related extensions are only used during extraction, and the others defined above are not available during extraction.
The fhirpath expressions used in the $extract processing only have access to:
Extension | Source | Location | Use Cases | Example | |
---|---|---|---|---|---|
allocateId | SDC | Questionnaire, item | definition + template extraction | example | |
The allocateId extension is used to allocate a new uuid to be able to use in fhirpath expressions during extraction, specifically to support cross referencing resources in the output transaction bundle which still using server side ID allocation and POST(s).
It's value is allocated once for each context that it appears in the QR. |
|||||
definitionExtract | SDC | Questionnaire, item | definition extraction | example | |
The fhirpath expressions in the definitionExtract are used to provide dynamic values for the
|
|||||
definitionExtractValue | SDC | Questionnaire, item | definition extraction | example | |
The fhirpath expressions in the definitionExtractValue provides dynamic values to set a value in the output
resource property (based on the definition property in the extension). |
|||||
itemExtractionContext (deprecated) | SDC | any | definition extraction | example | |
This expression identifies the resource(s) that correspond either to an overall questionnaire, a group within the questionnaire or, occasionally, a single question. The results of executing the specified expression are used to indicate the resources used to identify the data to replace when performing an extraction and also indicate the relevant resource type. If an expression results in multiple repetitions for a single for the root Questionnaire or for an item where 'repeat' is false, it is an error and no extraction can occur. When performing an extraction and the expression is executed, if a record is found, the data in the QuestionnaireResponse will be used to update that record. If the expression returns no results, the data in the QuestionnaireResponse will be used to create a new record. Expression.name does not necessarily need to be present for definition-based extraction, as that relies on item.definition rather than other expressions. However, including it is generally a good idea. |
|||||
templateExtractContext | SDC | (any element - in contained resource)) | template extraction | example | |
Selects a new context in the QuestionnaireResponse to be used by subsequent child templateExtractContexts or templateExtractValue expressions. |
|||||
templateExtractValue | SDC | (any element - in contained resource)) | template extraction | example | |
Selects a value to replace a value in the extracted resource template.
If there is no result, then the property with the template extension will be removed.
With jason, that means removing both the For collections, there may be more than 1 template value to replace in the template collection, so don't just clear the collection, remove the templated item. |
x-fhir-query is now formally defined in the FHIR R5 specification. Updates and clarifications may be found in the equivalent page in the FHIR continuous-integration build. Even though this content was formally migrated into the FHIR core specification in R5, it can still be used with FHIR R4, R4B, and other earlier releases.
When used within the context of a Questionnare, the base URL for the queries is typically that of the server where the QuestionnaireResponse is stored (or whatever FHIR repository the Form Filler is configured to use). The FHIRPath may use any variables that are in-scope at the point in the x-fhir-query expression is defined (for example, launch-context parameters, variable declarations, etc.).
It is possible that search responses resulting from executing a query could be paged. This specification provides no specific guidance on appropriate behavior in such situations. The desired behavior could vary depending on where the results are being used. Possibilities include:
Feedback from the implementer community on specific guidance we could/should include in a future version of this specification around handling paging is welcome.
Expressions will often have dependencies on other expressions. For example, a calculatedExpression might depend on variables that in turn depend on the answers to other questions which might themselves have initialExpressions which might rely on itemPopulationContext queries that in turn have embedded FHIRPaths that reference elements defined in launchContext. If care is not taken, it's possible to construct a questionnaire where the value of an answer depends indirectly on itself, or where filling out an answer disables the question being answered or other inappropriate behavior. Questionnaire rendering systems need to check for these situations and gracefully handle them by raising appropriate error messages rather than crashing or locking in an endless loop.
When evaluating expressions, the typical order of calculation will be in the order the expressions appear in the Questionnaire. Those at the root are evaluated first, then items are evaluated in order, evaluating on a depth-first basis. Children of the first item in a group are evaluated before the second item in the group.
However, in some cases, updates to later elements may trigger an update to earlier elements, which then cascade through again. Systems ought to allow for this and allow for iterative updating of expressions until values reach a stable state - or until an unstable looping condition is detected.
The FHIRPath language defines a set of contexts that get passed into expressions and also allows the definition of additional contexts and functions. SDC provides the following supplemental guidance for evaluating FHIRPath, and CQL and FHIR Queries in the context of a Questionnaire:
%resource
variable when it appears in expressions on elements in Questionnaire SHALL be evaluated as the root of the QuestionnaireResponse.%context
variable SHALL be set to the QuestionnaireResponse if the expression extension is defined on the Questionnaire root.
Otherwise, it SHALL be interpreted as the QuestionnaireResponse.item(s) whose linkId matches the linkId of the Questionnaire.item the expression
extension was defined in. I.e. while the extensions and expressions are defined in the Questionnaire, they are evaluated in the context of
the corresponding item(s) in the QuestionnaireResponse.%score
. (Note: It is an error if a questionnaire is designed such
that there is more than one element in the same scope with a colliding context name.)
In addition, a number of extensions have been proposed to the FHIRPath language - some to the base language and some to the FHIR-specific set of extensions
to the language. These extensions have been adopted as 'local' FHIRPath extensions for implementers of this implementation guide. Systems that accept
FHIRPath, CQL or FHIRQuery expressions SHOULD
support all of these extensions in their FHIRPath implementations:
%questionnaire
variable is defined that corresponds to the Questionnaire resource resolved to by the QuestionnaireResponse.questionnaire
element. It is in scope for all expressions defined in the Questionnaire.%qitem
variable is defined as a shortcut to get to the Questionnaire.item that corresponds to the context QuestionnaireResponse.item. It
is only valid for FHIRPath expressions defined within a Questionnaire item.The following FHIRPath extension functions are also defined:
sum()
, min()
, max()
, count()
, and avg()
. These are short-cuts for the equivalent
.aggregate()
. The sum, min and average expressions are already listed
here. The equivalents of the remainder are:
value.aggregate(iif($total.empty(), $this, iif($this > $total, $this, $total)))
value.aggregate(1 + $total, 0)
weight()
returns the itemWeight for a code, Coding or other element eligible to have the itemWeight
extension. If an itemWeight extension
is defined on the QuestionnaireResponse answer, it SHALL be returned. If not, it will be looked up either as an extension on an answerOption in the Questionnaire or as a
property on the bound value set expansion (or for Questionnaires, on the
corresponding Questionnaire.answerOption). If not found there, will be looked up on property in the underlying CodeSystem. If the type is other than code or Coding or no weight
is defined for the context element, the result SHALL be an empty set. If the FHIRPath engine is unable to resolve the corresponding value set, code system or questionnaire
options, it SHOULD cause the expression to fail.The change requests proposing the addition of these concepts to the base FHIRPath specification and to the FHIR-specific supplement can be found here and here.
Variable names SHOULD be unique in a context (e.g. Questionnaire root or a specific item). It is an error if the same variable name is assigned a value more than once in a single node. It is also an error to define a variable name that has the same name as one of the standard FHIRPath names (e.g. %qitem). If the same variable is assigned on both an element and a descendant element, a warning SHOULD be generated, however it is not an error. The descendant declaration SHALL be treated as overriding the higher-level declaration. It is perfectly acceptable for the same variable name to appear in multiple disjoint contexts (for example on sibling items within a Questionnaire).
SDC supports both FHIRPath and CQL as languages for defining expressions. In practice, FHIRPath is a proper subset of CQL, so the question of whether to use one or the other comes down to whether any of the additional capabilities of CQL (such as defining internal variables, iterating loops, etc.) is needed. FHIRPath is more widely implemented than CQL, so questionnaires that only make use of FHIRPath will typically be more widely supported.
Some of the elements and expressions used in Questionnaires depend on information that is outside the scope of the QuestionnaireResponse being completed and its associated QuestionnaireResponse. This includes elements that depend on the environment of the user filling out the form (i.e. launchContext) as well as elements that point directly to other resources such as sourceQuery and answerValueSet - though in some cases these direct references may be to resources 'contained' within the Questionnaire. However, it also includes any expression that makes use of x-fhir-query, any FHIRPath expression that uses resolve()
, and any CQL that performs queries.
When a Questionnaire is defined to depend on external sources, it is possible that information might change between different launches of the editing process and between editing and validation, meaning that information that was once valid might become invalid. (E.g. Questions that were enabled are no longer enabled, questions that were optional are now required, answer choices have changed to exclude previously valid answers, etc.) It can also cause another problem - that the set of choices available to the user that they didn't pick could be different, possibly creating confusion about what answers were deliberately excluded.
When referencing external answerValueSets, consideration should be given to linking to a specific version of the ValueSet and/or ensuring that the ValueSet binds to specific versions of the underlying systems. Otherwise, a change to the ValueSet definition or deprecation of codes from one of the referenced code systems could invalidate previously valid QuestionnaireResponses. Validators SHOULD
check validity against a value set based on the date of QuestionnaireResponse completion (i.e. QuestionnaireResponse.authored) to mitigate this issue.
Information gleaned from other types of external sources (e.g. launch context, fhir-x-query, etc.) SHOULD
only be used for initialExpression and calculatedExpression logic and that any other desired behavior (enableWhen, answerExpression, etc.) SHOULD always be driven off of answers within the Questionnaire (even if they're hidden answers that are populated from an initialExpression) because launchContext and search results may vary between edit sessions and will also be different (or perhaps non-existent) when validating the Questionnaire.
Changes in external context that impacts the value of a calculatedExpression will not cause a problem because if the new calculated value upon re-opening a QuestionnaireResponse differs from the stored value, the form filler SHALL interpret the answer as having been overridden and it will therefore remain unchanged.
Sometimes information needed for an expression will not be available. Perhaps the system cannot pass encounter information - or maybe the form is being filled in outside the context of an encounter at all. Perhaps a query results in an error because of a server issue or perhaps the user or system filling in the questionnaire does not have permission to access the relevant data. Systems SHOULD fail gracefully in such situations. Populated or calculated elements can be left empty. Extracted elements can be omitted. If control logic such as enableWhen is impacted, either display a helpful error message or permit entry of potentially relevant information if it cannot be determined whether the data should be allowed or not.
For unanswered items, expressions or %context that refer to QuestionnaireResponse items that don't actually 'exist' (because they don't have an answer) will resolve to an empty set, as per standard FHIRPath rules.
In some cases, a Questionnaire may contain expressions that result in an error. This could be the result of an invalid expression, unexpected data, or an expression handling engine that does not handle some aspect of the expression provided (e.g. FHIRPath library doesn't support certain Questionnaire-specific variables. In other cases, the system might support some expression languages, but not others. E.g. The system can handle FHIRPath but not CQL. In either case, the system needs to determine whether it can safely expose the Questionnaire and what information, if any, about the failure/limitation it should expose.
SHOULD NOT
prevent the user from completing the form and marking it 'completed'SHOULD
indicate to the user up-front that the authoring system cannot properly
validate or enforce the Questionnaire rules. The Form Filler SHOULD NOT
mark a QuestionnaireResponse as 'completed' or submit it as complete if it cannot
validate all enabled items or determine whether items SHOULD
be enabled. It may still be useful for a user to complete the QuestionnaireResponse if
there's a possibility of a different client allowing subsequent editing or if the associated Questionnaire logic might be corrected to allow marking
the response as 'completed' in the future. Also, in some cases, a user reading human-readable directions may be able to make the determination that a
QuestionnaireResponse is 'completed' even if the software can't make that determination. (Because the user might do this in error, systems consuming
'completed' QuestionnaireResponses might still want to check that the response is 'valid' against the rules of the Questionnaire.)SHOULD
still allow the form to be filled in and marked as 'completed'.Obviously, if the issue with population, extraction or validation comes from invoking an external operation rather than handling the process inline, the result will be an OperationOutcome indicating failure and why. The Form Filler will then need to relay that information to the user in whatever it deems to be the most appropriate manner.
The other side of this issue is how a Form Filler can search for a Form Manager that will be able to populate or extract for a particular Questionnaire.
At present, there is no computable way for systems to expose what expression languages they support, what 'extensions' they support within those languages, etc.
However, systems SHALL
document their capabilities around languages and language extensions in the textual documentation of their CapabilityStatements so
that it is clear to human readers. A proposed R5 CapabilityStatement refactoring might provide such support in the future. We will evaluate using those new features
in a future release.