Stream: dotnet
Topic: FHIRPath and new library
Richard Kavanagh (Nov 16 2018 at 20:09):
Having recently updated my Nuget package I am having to try and deal with some of the changes in the API.
When evaluating FHIRPath expressions previously, I had code a bit like this....
Resource res FhirPathCompiler compiler = new FhirPathCompiler(); CompiledExpression xps = compiler.Compile("Bundle.repeat(children())"); var inputNav = new PocoNavigator(res); var prepopulatedValues = xps(inputNav, new EvaluationContext(inputNav)); _refOut = new ObservableCollection<ModelRefOut>(); foreach (PocoNavigator item in prepopulatedValues.Where(x => x.Type == "Reference")) { ........ }
Now that PocoNavigator is obsolete how d you evaluate FHIRPath's.
Ewout Kramer (Nov 19 2018 at 15:34):
Hi Richard, the problem with the code you are using is that it involves working with the quite low-level CompiledExpression classes. In the 1.0 release of the API, a compiled FhirPath expression takes an ITypedElement
as input (and not an IElementNavigator
). We have added backwards-compatibility overloads that take an IElementNavigator
to make your code compile and run.
However, the code above assumes too much intimate knowledge of the internals of the API, since you are assuming the result of the evaluation to be PocoNavigator instances. This was indeed the case in the previous versions of the API, but is no longer the case in the 1.0 version.
All you know is that you are going to input ITypedElement, and the result will be ITypedElement. So if you want to stick with calling the CompiledExpression explicitly, here's what you do:
var tpXml = TestData.ReadTextFile("fp-test-patient.xml"); var patient = (new FhirXmlParser()).Parse<Patient>(tpXml); FhirPathCompiler compiler = new FhirPathCompiler(); CompiledExpression xps = compiler.Compile("Patient.repeat(children())"); var input = patient.ToTypedElement(); var prepopulatedValues = xps(input, new EvaluationContext(input)); foreach (var item in prepopulatedValues.Where(x => x.InstanceType == "Reference")) { var reference = item.ToPoco<ResourceReference>(); Debug.Print(reference.Reference); // Alternative that does not require parsing: // var reference = item.Children("reference").Single(); // Debug.Print(reference.Value as string); }
As you can see, we're turning the POCO patient into an ITypedElement by calling ToTypedElement() on the POCO object. Now you can call the compiled expression xps()
with the correct inputs.
On the output side, you would see that the items returned are indeed IEnumerable<ITypedElement>
. Now, depending on whether you really need to work with POCO's, you can either turn each ITypedElement
back into a poco by parsing it with ToPoco()
. Alternatively, you can stay in the POCO-less domain, and navigate to "reference" and get the values (shown in the comments).
Ewout Kramer (Nov 19 2018 at 15:37):
But that's assuming you actually need to go that low-level. There are much more user-friendly methods available!
The code below will do the same, but in far less lines of code:
var tpXml = TestData.ReadTextFile("fp-test-patient.xml"); var patient = (new FhirXmlParser()).Parse<Patient>(tpXml); var prepopulatedValues = patient .Select("Patient.repeat(children())") .OfType<ResourceReference>() .Select(rr => rr.Reference);
Last updated: Apr 12 2022 at 19:14 UTC