Stream: fhirpath
Topic: Behaviour of the root
Felix Chapman (Dec 08 2020 at 17:44):
I'm implementing FHIRPath and was wondering the exact behaviour of the root path. In particular, why this expression behaves the way it does:
type!='display' or code.empty()
Notice code
is also a type (full name FHIR.code).
In this case, code
is meant to be interpreted as a label - but why is that the case? It's the root of a path, which means it should be interpreted as a type. Or does "path" refer only to the entire expression, and not sub-expressions?
A related question, how would this on its own behave?
code.empty()
Are there some cases where it would be interpreted as a type, and other cases where it would be interpreted as a label?
Lloyd McKenzie (Dec 08 2020 at 18:22):
Each invariant specifies a 'context'. That establishes the node in which the expression will be evaluated.
Felix Chapman (Dec 08 2020 at 18:30):
I see, so in this case the context is Questionnaire.item, which has type BackboneElement
.
The spec says this:
When resolving an identifier that is also the root of a FHIRPath expression, it is resolved as a type name first, and if it resolves to a type, it must resolve to the type of the context (or a supertype). Otherwise, it is resolved as a path on the context. If the identifier cannot be resolved, the evaluation will end and signal an error to the calling environment.
Applying to this example: code
resolves to a type, so it "must resolve to the type of the context". The type of the context is BackboneElement
, so it fails. After this point I'm uncertain, should it:
- Resolve to a path on the context?
- End evaluation and signal an error?
I read it as the latter, because I thought "Otherwise, it is resolved as a path on the context" referred to the condition "if it resolves as a type". But perhaps it's the former?
Paul Lynch (Dec 08 2020 at 23:09):
That is an interesting question. In the fhirpath.js library, we assumed that the "type" was referring to a resource type (e.g. Patient, Observation), not primitive types. Otherwise, if you had an Observation in the context, wrote code
, it would fail, unless you wrote Observation.code
. I am not sure which behavior is correct. @Bryn Rhodes ?
Bryn Rhodes (Dec 08 2020 at 23:49):
It would be the former, the intent being to ensure that paths written against base resource types resolve correctly (e.g. Resource.id = '123'
, though I agree the language can be tightened. Please submit a tracker on that?
Bryn Rhodes (Dec 08 2020 at 23:50):
Should probably be 'if it resolves to a type and that type is the type of the context (or a supertype).'
Bryn Rhodes (Dec 08 2020 at 23:50):
Only in the case that the identifier can't resolve at all should it result in an error.
Grahame Grieve (Dec 09 2020 at 20:52):
there is a corner case where this is a problem, which is where the focus element has a sub-element with the same name as the type.
Grahame Grieve (Dec 09 2020 at 20:52):
I don't think that we have any of these in FHIR, but it might happen elsewhere
Felix Chapman (Dec 14 2020 at 15:04):
Thanks for the help, the behaviour is clear to me now!
I've requested a HL7 JIRA account, then I'll submit an issue to clarify that paragraph.
Felix Chapman (Dec 15 2020 at 16:39):
https://jira.hl7.org/browse/FHIR-30008
Paul Lynch (Dec 15 2020 at 19:18):
Agreed, but added a comment.
Paul Lynch (Dec 15 2020 at 19:36):
Actually, for processing JSON (e.g. fhirpath.js) I am wondering whether that sentence could be a bit clearer about handling primitive types. If someone passes in a JSON string (not a string of JSON, but just a JSON string value, e.g. '"hi"'), then per the data types page it might be one of several FHIR types: string, uri, url, canonical, base64Binary, date, dateTime, time, code, oid, id, markdown, or uuid. One might guess at the intended type (or at least rule out some possibilities) by looking at the content of the string, but there will be ambiguous cases. Is '"2014"' a date, an id, or markdown? So if that is the context, and someone writes "markdown" for the FHIRPath expression, is it valid or not?
Paul Lynch (Dec 15 2020 at 19:38):
I think the same issue arises for complex types. If the context is {"text": "George"}
is that a CodeableConcept or a HumanName? So, if someone writes HumanName.text
, should that be permitted because it is possible?
Grahame Grieve (Dec 23 2020 at 01:28):
FHIRPath doesn't really work on untyped content, though we can approximate it if we declare than any untyped primitive content is treated as as string
Paul Lynch (Dec 23 2020 at 13:54):
"FHIRPath doesn't really work on untyped content"
In Questionnaire expressions (e.g. calculatedExpresion) the context is QuestionnaireResponse.item (or item.item), which as a fragment of a resource, does not contain the resource type. Therefore expressions like "answer.value" won't work, because the structure will really be something like "answer.valueCoding", and there is no type information to translate "valueCoding" to "value". Just yesterday I worked around that by using "answer.children()".
ryan moehrke (Dec 23 2020 at 15:23):
valueCoding isn't fhirpath anyways, you would use value.ofType(Coding)
Paul Lynch (Dec 23 2020 at 15:27):
If you are working in JSON, the fragment passed in for an item would have valueCoding (or other type) not "value". But you are correct that if the choice type could be recognized, the proper FHIRPath syntax would be "value".
Grahame Grieve (Dec 23 2020 at 18:26):
which as a fragment of a resource, does not contain the resource type
but it is still known, since they are always contained by the resource
Paul Lynch (Jan 05 2021 at 18:05):
Grahame Grieve said:
which as a fragment of a resource, does not contain the resource type
but it is still known, since they are always contained by the resource
I suppose you mean that "item" could have some extra property which points back to its parent node, or to the containing resource. That extra property would have to be named carefully to avoid conflicting with possible resource element names.
Last updated: Apr 12 2022 at 19:14 UTC