YAML 1.2 メモ (10) エイリアス

ノードに標識をつけるのがアンカー・プロパティで、標識のついたノードを再利用するのがエイリアスです。

標識はアンカー名と呼ばれます。アンカー名に利用できる文字の制限は緩く、名前に使えない文字はスペース、タブ、改行、フロー・インジケータだけです。仕様に明記されていませんけど、アンカー名では大文字・小文字を区別しているのではないかと思われます。

アンカー名はドキュメントとエイリアスを除いて、構文上の制約がない限りすべてのノードにつけることができます。それから、一つのノードにつき、アンカー名は一つしか付けることができません。アンカー名だけのノードも許されており、その場合は空スカラーを省略したものと解釈します。構文上、プロパティをつけることができないのは、ブロック・コンパクト・シーケンス、同マッピング、フロー・ペア等の簡略記法です。他には、アンカーが付けられそうで付けられないものに、マッピングのキーと値のペアがあります。キーと値それぞれにはアンカーを付けることは可能ですが、ペアに付けることはできません。

# アンカー・プロパティは & インジケータの後ろにアンカー名をくっつけたものです。
'k0': &アンカー 'v0'
# アンカー名に使えない文字は "\n"等の改行文字, " ", "\t", ",", "[", "]", "{", "}" です。
# 他は使い放題なので、目を疑うようなアンカー名も仕様上では利用できることになっています。
'k1': &#?-: 'v1'
# ですが実装が仕様通りに作ってあるとは限らないので、
# 無難に ASCII 英数字を使っておいた方が確実です。
'k2': &A 'v2'
'k3': &0 'k3'
---
&0 # マッピング自身へのアンカー
{
  &1 'k0': &2 [&3 'v0-1', &4 'v0-2', &5 'v0-3'],
  # キーへのアンカーと値へのアンカー、値の各要素へのアンカー
  &6 : &7, # &6 !!null "" : &7 !!null "", と同じ
}
--- &A # シーケンス自身へのアンカー
- &B 'e-0'
- &C
  ? &D 'k-1-0'
  : &E 'v-1-0'
  &F 'k-1-1' : &G 'v-1-1'
- &H |
  アンカー&Hがついたリテラル
- &I >
  アンカー&Iがついたフォールデッド
...
# 暗黙キー・エントリの場合。構文では正しいが、解釈してくれない解析器が多い。
--- &0 # マッピング自身へのアンカー
&1 k : &2 v # 最初のキーへのアンカーと値へのアンカー
...
# コンパクト形式にはプロパティが付けられないため、アンカーも付けられない。
- &0 - entry        # エラー
- &1 ? key          # エラー
     : value
- &3 key : value    # エラー
  ? &2 - entry      # エラー
  : &3 - entry      # エラー
  ? &4 key : value  # エラー
...
# フロー・ペアにアンカーをつけたつもりでも、キーのアンカー扱いになります。
- [a, &0 b : c, d]      # ['a', { ? &0 'b' : 'c' }, 'd']
- [a, &1 { b : c }, d]  # ['a', &1 { ? 'b' : 'c' }, 'd']

エイリアスはアンカー名がついたノードへの参照をおこないます。このとき、エイリアスに指定されているアンカー名は、YAML ストリームの字面上でアンカー・プロパティが記述済みでなければならないとの縛りがあります。YAML のノードは木構造をしており、字面ではルートから枝へ向かって記述していくので、枝からノードへ向けての循環参照を作ることができます。もちろん、枝から他の枝への参照も作れます。また、同一ドキュメント内で、アンカー名は何度でも再利用可能で、重複していても良い約束になっています。重複している場合は、エイリアスは字面上で最も最近記述さらたアンカー・プロパティのついているノードを参照します。

--- &0
- 
  k0: v0
  k1: *1        # エラー &1 はまだ定義されていない
  k3: &1
    - k3-0
    - *0        # ルートへの循環参照
- *1            # [k3-0, *0] への参照
- &1
  k4: v4
  k5: v5
- *1            # {k4: v4, k5: v5} への参照
- *1            # 同上
- *1            # 同上
- *1 : 'v6'     # 暗黙キーにエイリアスを使うこともできる
- ? *1          # 明示キーに使うこともできる
  : 'v7'

エイリアスにはプロパティをつけることができません。なので、エイリアスにアンカーをつけることもできませんし、タグ・プロパティで参照先のタグを上書きすることもできません。

---
- &0 !!str '1'
- &1 *1         # エラー
- !!int *1      # エラー