Поскольку в вашем отображении есть дубликат ключа, который не допускается
в YAML 1.2 (и должен хотя бы выдавать предупреждение в YAML 1.1) это
не собираюсь работать, но даже если вы исправите это, вы не сможете этого сделать
только с якорями и псевдонимами.
Единственной заменой, подобной замене, которая доступна в YAML, является «Независимый от языка слияния тип ключа» . На него косвенно ссылаются в спецификации YAML, и он не включен в него, но доступен в большинстве анализаторов.
Единственное, что позволяет это сделать, - это "обновить" отображение парами значений ключа одного или нескольких других отображений, , если ключ еще не существует в отображении. Для этого вы используете специальный ключ <<
, который принимает псевдоним или список псевдонимов.
Не существует средства, указанного в спецификации YAML , для разыменования частичных ключей.
В некоторых системах используются шаблоны, генерирующие YAML, но здесь есть две основные проблемы:
сами языки шаблонов часто конфликтуют с индикаторами в синтаксисе YAML,
делает шаблон недействительным YAML
, даже если шаблон может быть загружен как действительный YAML, а извлеченные значения необходимы для
обновить другие части шаблона, вам нужно будет проанализировать ввод дважды (один раз, чтобы получить
значения для обновления шаблона, а затем для анализа обновленного шаблона). Учитывая потенциал
сложность YAML и относительная медленная скорость его синтаксических анализаторов, это может быть непомерно большим
Что вы можете сделать, это создать какой-нибудь тег (например, !lookup
) и заставить его конструктор интерпретировать этот узел.
Поскольку узел снова должен быть действительным YAML, вам нужно решить, использовать ли последовательность или отображение.
Вы должны будете включить некоторый специальный синтаксис для значений в обоих случаях, а также для ключа
(например, <<
, используемый в слияниях) в случае отображений.
В примерах я исключил ложные одинарные кавычки, в зависимости от
ваши реальные ценности, они вам, конечно, могут понадобиться.
Пример использования последовательности:
.map_values: &my_map
a: D
b: E
c: F
section: !Lookup
- *my_map
- stage: <b>
Пример использования сопоставления:
.map_values: &my_map
a: D
b: E
c: F
section: !Lookup
>>: *my_map
stage: <b>
Оба могут быть сделаны для построения данных на лету (т. Е. Без прошлого
необходима обработка загрузки вашей структуры данных). Например. используя Python и
последовательность "стиль" в input.yaml
:
import sys
import ruamel.yaml
from pathlib import Path
input = Path('input.yaml')
yaml = ruamel.yaml.YAML(typ='safe')
yaml.default_flow_style = False
@yaml.register_class
class Lookup:
@classmethod
def from_yaml(cls, constructor, node):
"""
this expects a two entry sequence, in which the first is a mapping X, typically using
an alias
the second entry should be an mapping, for which the values which have the form <key>
are looked up in X
non-existing keys will throw an error during loading.
"""
X, res = constructor.construct_sequence(node, deep=True)
yield res
for key, value in res.items():
try:
if value.startswith('<') and value.endswith('>'):
res[key] = X[value[1:-1]]
except AttributeError:
pass
return res
data = yaml.load(input)
yaml.dump(data, sys.stdout)
что дает:
.map_values:
a: D
b: E
c: F
section:
stage: E
Следует отметить несколько вещей:
- использование
<...>
является произвольным, вам не нужны ни начало, ни
маркер конца Я рекомендую использовать некоторые символы, которые не имеют
особое значение в YAML, поэтому вам не нужно указывать свои значения. Вы можете, например, использовать некоторые
хорошо распознаваемая точка Unicode, но они, как правило, труднее набирать в редакторе.
- когда вызывается
from_yaml
, якорь еще не полностью построен. Так что X
это пустой диктат
это заполняется позже. Конструкция с yield
реализует двухэтапный процесс: сначала мы
верните res
"как есть" обратно конструктору, а затем обновите его. Этап конструктора
загрузчик знает, как обрабатывать это автоматически, когда он получает генератор вместо «нормального» значения.
-
try
.. except
предназначен для обработки значений сопоставления, которые не являются строками (то есть числа, даты, логические значения).
- вы также можете делать замены в ключах, просто убедитесь, что вы удалили старый ключ
Поскольку теги являются стандартными YAML, вышеприведенное должно быть так или иначе выполнено в любом
Парсер YAML, независимый от языка.