YAML example¶ We can use the ampersand & character to create a named anchor, that we can then reference later on with an asterisk *. Anchor names must not contain the [, ], {, } and , characters. This came in use when I had to create some elasticsearch mappings that were being duplicated all over the place.
The <<: inserts the content of that node. Allow me to quote the YAML spec here: Repeated nodes (objects) are first identified by an anchor (marked with the ampersand - “&”), and are then aliased (referenced with an asterisk - “*”) thereafter.
I don't think it is possible. You can reuse "node" but not part of it.
bill-to: &id001
given : Chris
family : Dumars
ship-to: *id001
This is perfectly valid YAML and fields given
and family
are reused in ship-to
block. You can reuse a scalar node the same way but there's no way you can change what's inside and add that last part of a path to it from inside YAML.
If repetition bother you that much I suggest to make your application aware of root
property and add it to every path that looks relative not absolute.
Yes, using custom tags. Example in Python, making the !join
tag join strings in an array:
import yaml
## define custom tag handler
def join(loader, node):
seq = loader.construct_sequence(node)
return ''.join([str(i) for i in seq])
## register the tag handler
yaml.add_constructor('!join', join)
## using your sample data
yaml.load("""
paths:
root: &BASE /path/to/root/
patha: !join [*BASE, a]
pathb: !join [*BASE, b]
pathc: !join [*BASE, c]
""")
Which results in:
{
'paths': {
'patha': '/path/to/root/a',
'pathb': '/path/to/root/b',
'pathc': '/path/to/root/c',
'root': '/path/to/root/'
}
}
The array of arguments to !join
can have any number of elements of any data type, as long as they can be converted to string, so !join [*a, "/", *b, "/", *c]
does what you would expect.
Another way to look at this is to simply use another field.
paths:
root_path: &root
val: /path/to/root/
patha: &a
root_path: *root
rel_path: a
pathb: &b
root_path: *root
rel_path: b
pathc: &c
root_path: *root
rel_path: c
I've create a library, available on Packagist, that performs this function: https://packagist.org/packages/grasmash/yaml-expander
Example YAML file:
type: book
book:
title: Dune
author: Frank Herbert
copyright: ${book.author} 1965
protaganist: ${characters.0.name}
media:
- hardcover
characters:
- name: Paul Atreides
occupation: Kwisatz Haderach
aliases:
- Usul
- Muad'Dib
- The Preacher
- name: Duncan Idaho
occupation: Swordmaster
summary: ${book.title} by ${book.author}
product-name: ${${type}.title}
Example logic:
// Parse a yaml string directly, expanding internal property references.
$yaml_string = file_get_contents("dune.yml");
$expanded = \Grasmash\YamlExpander\Expander::parse($yaml_string);
print_r($expanded);
Resultant array:
array (
'type' => 'book',
'book' =>
array (
'title' => 'Dune',
'author' => 'Frank Herbert',
'copyright' => 'Frank Herbert 1965',
'protaganist' => 'Paul Atreides',
'media' =>
array (
0 => 'hardcover',
),
),
'characters' =>
array (
0 =>
array (
'name' => 'Paul Atreides',
'occupation' => 'Kwisatz Haderach',
'aliases' =>
array (
0 => 'Usul',
1 => 'Muad\'Dib',
2 => 'The Preacher',
),
),
1 =>
array (
'name' => 'Duncan Idaho',
'occupation' => 'Swordmaster',
),
),
'summary' => 'Dune by Frank Herbert',
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With