
# Accessing data definition nodes in Velocity

> How to read structured data from a page's Data Definition with getStructuredDataNode() and getChild(): root-level nodes, nested children, multi-value variants, path syntax, and how to verify your access is working.

URL: https://www.hannonhill.com/cascadecms/latest/articles/developing-in-cascade/script-formats/accessing-data-definition-nodes-velocity.html
category: Developing in Cascade
article-type: how-to
content-kind: article
release-availability: all
tags: data-definitions, velocity
updated: 2026-10-06

In [Accessing page data in Velocity](https://www.hannonhill.com/cascadecms/latest/articles/developing-in-cascade/script-formats/accessing-page-data-velocity.html), 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:

```xml
<​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:

```velocity
$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:

```velocity
$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:

```velocity
## 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`:

```velocity
## 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`.

**Choosing a structured data access method.**

| 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:

```velocity
$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 needed `getStructuredDataNode()`, 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 `$currentPage` when `type` isn't a root-level node
> - Using the field's Label instead of its Identifier inside the quotes

## Related articles

- [Accessing page data in Velocity](https://www.hannonhill.com/cascadecms/latest/articles/developing-in-cascade/script-formats/accessing-page-data-velocity.html)
- [Velocity Tools](https://www.hannonhill.com/cascadecms/latest/articles/developing-in-cascade/script-formats/velocity-tools.html)
- [Best practices for performance](https://www.hannonhill.com/cascadecms/latest/articles/developing-in-cascade/script-formats/velocity-best-practices.html)
- [Variable scope in Velocity](https://www.hannonhill.com/cascadecms/latest/articles/developing-in-cascade/script-formats/velocity-variable-scope.html)
