Navigating POCOs as a tree
Note
This section describes advanced functionality that can be safely skipped when you are learning the basics of the SDK.
Using the techniques described in the section on dynamic features, you can use EnumerateElements() and TryGetValue() to navigate the POCO model dynamically. By applying these methods recursively you can walk the entire POCO tree. In some scenarios, however, navigating only downward is not enough: both FhirPath and the validator need a couple of additional capabilities:
Ability to navigate back to the parent node
Ability to obtain a path from the root to the current node
Users of earlier SDK versions may recognize these features from the ITypedElement interface. Two limitations of that approach were that ITypedElement did not expose a parent (unless you wrapped nodes with ScopedNode) and it was a separate abstraction outside the POCO model, which made direct access to POCO-specific behavior harder.
SDK6 introduces PocoNode, a lightweight wrapper around POCOs that presents a POCO as a node in a tree. For backwards compatibility PocoNode implements both the ITypedElement and ISourceNode interfaces, so it can be used wherever ITypedElement was used before, while still providing direct access to the underlying POCO.
You can obtain a PocoNode for any element by calling ToPocoNode() on any Base instance.
Note
ToPocoNode() accepts an optional ModelInspector (see model metadata). Providing a ModelInspector is useful when deriving accurate type information for ITypedElement or for FhirPath’s ofType() when working with shared datatypes (see datatypes). In those cases the concrete POCO types may not fully align with the FHIR specification for a particular version.
Once you have a PocoNode, you can navigate both up and down the tree using the Parent property and the Children() method (to enumerate all children). Use Child() to get a specific child by name.
When you navigate down from the node created by ToPocoNode(), the PocoNode instances record the path back to that root node. Each PocoNode therefore exposes:
The node
NameThe
Indexif the node is an element in a list
Use the extension method GetLocation() to obtain the full path from the root to the current node as a string.
Note
The parent pointers and location are established when you call ToPocoNode(). Holding references to parent resources can retain large object graphs in memory (for example, large Bundles), so exercise caution in memory-constrained or performance-critical environments.
Nodes which are lists
In the POCO tree, a node can be either a single node (represented by PocoNode) or a list of nodes (represented by PocoNodeList). Both derive from the abstract class PocoNodeOrList and implement IEnumerable<PocoNode>. This allows you to traverse the tree using LINQ — for example SelectMany(Children) — similar to how ITypedElement is often consumed.
Because any child can be a single POCO or a collection of POCOs (if the fhir data is repeating), the return type of Child() is PocoNodeOrList?. The Parent property will always provide a single PocoNode (or null, if the node in question is the root of the tree).
Common uses for PocoNode
The SDK provides several extension methods that leverage the extra information in PocoNode. These make PocoNode a suitable replacement for the earlier ScopedNode used by the FhirPath engine and the profile validator.
Examples include:
Resolve()— resolves a local reference in the POCOs represented by thisPocoNode.ContainedResources()— returns the nodes that represent contained resources.Descendants()— returns all child nodes recursively.NavigateTo()— navigates to a simple dotted path below the current node.
These utilities make tree-based operations and validation straightforward while keeping direct access to the underlying POCOs. Navigating POCOs as a tree
