Accessing Data Definition Nodes in Velocity
Overview
In Accessing page data in Velocity, we covered metadata, global variables, and common page properties. The other half of the picture is structured data: the content fields defined by your page's Data Definition. This article covers how to navigate that data with getStructuredDataNode() and getChild().
How Data Definitions are stored
Structured assets in Cascade are built on a Data Definition, an XML schema that defines the content fields available on the page or asset. Each field maps to an XML element called a node.
Here's what that looks like under the hood:
<system-data-structure>
<group>
<heading>Welcome to our site</heading>
<content>Some text here</content>
</group>
</system-data-structure>
The <system-data-structure> element is the wrapper Cascade adds around all Data Definition content. Your nodes live inside it, and you never need to reference it directly in Velocity. Start with the nodes inside.
Each named element (<group>, <heading>, <content>) is a node. The name inside the tag is the node's Identifier, and that's what you'll use to access it in Velocity. Some nodes hold a single value; others allow multiple values, like a repeating group of content rows.
Accessing a root-level node
Top-level nodes in the Data Definition have their own access method, getStructuredDataNode(). Call it on $currentPage with the node's Identifier:
$currentPage.getStructuredDataNode("group")
That returns the <group> node.
Identifier, not Label: What goes inside the quotes is the Identifier of the Data Definition field, not its Label. The Identifier is what you set when building the Data Definition, and it's the tag name you see in the XML view of a page. The Label is just the user-facing display name shown in the editor. If you're not sure of an Identifier, check the XML view of the page (select the Context page that matches the format you're working on).
When a root node allows multiple values
If the field is configured to allow multiple values, add an s to the method name:
$currentPage.getStructuredDataNodes("row")
That returns an array of <row> nodes you can iterate with #foreach.
Accessing nested nodes
Anything below the root level is accessed with getChild(). You have three ways to get to a nested node, depending on what you already have on hand:
## If you already have $row in a variable:
$row.getChild("type")
## Chained directly from $currentPage:
$currentPage.getStructuredDataNode("row").getChild("type")
## Or pass the full path in one call:
$currentPage.getStructuredDataNode("row/type")
All three return the same <type> node. Which one you reach for depends on context: if you're already inside a loop and have the parent node in a variable, getChild() is the right choice. If you're starting fresh, the path syntax is often the most compact.
When a nested node allows multiple values
For repeating children, add ren to getChild:
## From a variable:
$banner.getChildren("slide")
## Chained from $currentPage:
$currentPage.getStructuredDataNode("banner").getChildren("slide")
## Or use the path with the plural getStructuredDataNodes:
$currentPage.getStructuredDataNodes("banner/slide")
All three return an array of <slide> nodes.
Quick reference
The method you call comes down to two questions: does the node sit at the root of the Data Definition or nested below it, and does it hold one value or many? The naming is consistent across the board: to get the multi-value version, add an s to getStructuredDataNode, or swap getChild for getChildren.
| Where the node lives | Single value | Multiple values |
|---|---|---|
| Root level | $currentPage.getStructuredDataNode("name") |
$currentPage.getStructuredDataNodes("name") |
| Nested, from a parent variable | $parent.getChild("name") |
$parent.getChildren("name") |
| Nested, by path from the page | $currentPage.getStructuredDataNode("parent/name") |
$currentPage.getStructuredDataNodes("parent/name") |
Testing your access
How do you know your access is working before you start pulling values out? Output the variable on its own:
$banner
If you see something like this in the output:
com.hannonhill.cascade.api.adapters.StructuredDataNodeAPIAdapter@4b1f41f4
Then you've found the node. That object reference is Cascade's internal representation of the node. It's not something you'd show to a user, but it confirms everything's wired up correctly. Once you see it, you're ready to start pulling values out.
If the output is blank, or you see literal $banner instead, something went wrong upstream.
Common mistakes: if your variable comes back empty, check for these:
- Using
getChild()when you neededgetStructuredDataNode(), or the other way around (root vs. nested) - A typo in the node name, method name, or variable (capitalization matters)
- Not following the full path to the node, like calling
getChild("type")directly on$currentPagewhentypeisn't a root-level node - Using the field's Label instead of its Identifier inside the quotes