YAML

功能

YAML的语法和其他高级语言类似，并且可以简单表达清单、散列表，标量等数据形态。它使用空白符号缩进和大量依赖外观的特色，特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲（例如：许多电子邮件标题格式和YAML非常接近）。尽管它比较适合用来表达层次结构式（hierarchical model）的数据结构，不过也有精致的语法可以表示关系性（relational model）的数据。由于YAML使用空白字符和分行来分隔数据，使得它特别适合用grep／Python／Perl／Ruby操作。其让人最容易上手的特色是巧妙避开各种封闭符号，如：引号、各种括号等，这些符号在嵌套结构时会变得复杂而难以辨认。

简单的文件

数据结构可以用类似大纲的缩进方式呈现
---receipt:     Oz-Ware Purchase Invoicedate:        2012-08-06customer:
    given:   Dorothy
    family:  Gale
   
items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      size:      8
      price:     133.7
      quantity:  1bill-to:  &id001
    street: | 
            123 Tornado Alley
            Suite 16
    city:   East Centerville
    state:  KSship-to:  *id001   

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain....
注意在YAML中，字符串不一定要用双引号标示。另外，在缩进中空白字符的数目并不是非常重要，只要相同层次结构的元素左侧对齐就可以了（不过不能使用TAB字符）。这个文件的顶层由七个键值组成：其中一个键值"items"，是两个元素构成的数组（或称清单），这清单中的两个元素同时也是包含了四个键值的散列表。文件中重复的部分用这个方法处理：使用锚点（&）和引用（*）标签将"bill-to"散列表的内容复制到"ship-to"散列表。也可以在文件中加入选择性的空行，以增加可读性。在一个文件中，可同时包含多个文件，并用"---"分隔。选择性的符号"..."可以用来表示文件结尾（在利用流的通信中，这非常有用，可以在不关闭流的情况下，发送结束信号）。

YAML的基本组件

YAML提供缩进／区块以及内置（inline）两种格式，来表示清单和散列表。以下展示几种YAML的基本原件。

清单（数组）

习惯上清单比较常用区块格式（block format）表示，也就是用短杠+空白字符作为起始。
 --- # 最喜愛的電影
 - Casablanca
 - North by Northwest
 - Notorious
另外还有一种内置格式（inline format）可以选择──用方括号围住，并用逗号+空白区隔（类似JSON的语法）。
 --- # 購物清單
 [milk, pumpkin pie, eggs, juice]

散列表

键值和数据由冒号及空白字符分开。区块形式（常使用与YAML数据文档中）使用缩进和换行符分隔key: value对。内置形式（常使用与YAML数据流中）在大括号中使用逗号+空白字符分隔key: value对。
 --- # 區塊形式
   name: John Smith
   age: 33 --- # 內置形式
 {name: John Smith, age: 33}

区块的字符

再次强调，字符串不需要包在引号之内。有两种方法书写多行文字（multi-line strings），一种可以保存新行（使用|字符），另一种可以折叠新行（使用>字符）。

保存新行(Newlines preserved)

data: |                                     # 譯者注：這是一首著名的五行民謠(limerick)
   There once was a man from Darjeeling     # 這裡曾有一個人來自大吉嶺
   Who got on a bus bound for Ealing        # 他搭上一班往伊靈的公車
       It said on the door                  # 門上這麼說的
       "Please don't spit on the floor"     # "請勿在地上吐痰"
   So he carefully spat on the ceiling      # 所以他小心翼翼的吐在天花板上
根据设置，前方的引领空白符号（leading white space）必须排成条状，以便和其他数据或是行为（如示例中的缩进）明显区分。

折叠新行(Newlines folded)

data: >
   Wrapped text         # 摺疊的文字
   will be folded       # 將會被收
   into a single        # 進單一一個
   paragraph            # 段落
   
   Blank lines denote   # 空白的行代表
   paragraph breaks     # 段落之間的區隔
和保存新行不同的是，换行字符会被转换成空白字符。而引领空白字符则会被自动消去。

于清单中使用散列表

- {name: John Smith, age: 33}- name: Mary Smith
  age: 27

于散列表中使用清单

men: [John Smith, Bill Jones]women:
  - Mary Smith
  - Susan Williams

YAML的高级组件

这部分算是一个后续的讨论，在比较各种数数据列语言时，YAML最常被提到的特色有两个：关系树和数据形态。

数据合并和参考

为了维持文件的简洁，并避免数据输入的错误，YAML提供了结点参考（*）和散列合并（<<）参考到其他结点标签的锚点标记（&）。参考会将树状结构加入锚点标记的内容，并可以在所有数据结构中运作（可以参考上面"ship-to"的示例）合并只有散列表可以使用，可以将键值自锚点标记复制到指定的散列表中。
当数据被instantiate合并和参考会被剖析器自动展开。
#眼部雷射手術之標準程序---- step:  &id001                  # 定義錨點標籤&id001
    instrument:      Lasik 2000
    pulseEnergy:     5.4
    pulseDuration:   12
    repetition:      1000
    spotSize:        1mm- step:
     <<: *id001                  # 合併鍵值：使用在錨點標籤定義的內容
     spotSize:       2mm         # 覆寫"spotSize"鍵值- step:
     <<: *id001                  # 合併鍵值：使用在錨點標籤定義的內容
     pulseEnergy:    500.0       # 覆寫鍵值
     alert: >                    # 加入其他鍵值
           warn patient of 
           audible pop

数据形态

由于自动判定数据形态的功能，严格类型（也就是用户有宣告的数据形态）很难在大部分的YAML文件中看到。数据类型可以被区分成三大类：原码（core），定义（defined），用户定义（user-defined）。原码可以自动被解析器分析（例如：浮点数，整数，字符串，清单，映射，...）。有一些高级的数据形态──例如比特数据──在YAML中有被“定义”，但不是每一种解析器都有支持。最后，YAML支持用户自定的区域变量，包括：自定义的类别，结构或基本类型（例如：四倍精度的浮点数）。

强制转型

YAML的自动判定数据形态是哪一种实体。但有时用户会想要将数据强制转型成自定的某种类型。最常见的状况是字符串，有时候可能看起来像数字或布尔值，这种时候可以使用双引号，或是使用严格类型标签。
---a: 123                     # 整數b: "123"                   # 字串（使用雙括號）c: 123.0                   # 浮點數d: !!float 123             # 浮點數，使用!!表達的嚴格型態e: !!str 123               # 字串，使用嚴格型態f: !!str Yes               # 字串，使用嚴格型態g: Yes                     # 布林值"真"h: Yes we have No bananas  # 字串（包含"Yes"和"No"）

其他特殊数据形态

除了一般的数据形态之外，用户也可以使用一些较为高级的类型，但不保证可被每种解析器分析。使用时和强制转型类似，要在形态名称之前加上两个惊叹号（!!）。有几种重要的形态在本篇没有讨论，包括集合（sets），有序映照（ordered maps），时间戳记（timestamps）以及十六进制数据（hexadecimal）。下面这个示例则是比特数据（binary）
---picture: !!binary |
 R0lGODlhDAAMAIQAAP//9/X
 17unp5WZmZgAAAOfn515eXv
 Pz7Y6OjuDg4J+fn5OTk6enp
 56enmleECcgggoBADs=mZmE

用户自行扩展的数据形态

许多YAML的实现允许用户自定义数据形态。在将一个对象序列化时，这个方法还颇方便的。某些区域数据形态可能不存在默认的数据形态中，不过这种类型在特定的YAML应用程序中是有定义的。这种区域数据形态用惊叹号（ ! ）表示。 
---myObject:  !myClass { name: Joe, age: 15}

与其他数据序列化格式比较

虽然YAML是参考JSON，XML和SDL等语言，不过跟这些语言比起来，YAML仍有自己的特色。

JSON

JSON的语法是YAML1.2版的子集,，同时非常接近 YAML1.0与1.1版的子集，因此大部分的JSON文件都可以被YAML的剖析器剖析。这是因为JSON的语法结构和YAML的内置格式相同。虽然大范围的分层也可以使用类似JSON的内置格式，不过YAML标准并不建议这样使用，除非这样编写能让文件可读性增加。YAML的许多扩展在JSON是找不到的，如：高级数据形态、关系锚点、字符串不需要双引号、映射数据形态会存储键值的顺序。

XML和SDL

XML和SDL标签概念，在YAML中是找不到的。对于数据结构序列（尽管这是有争议的），标签属性的特色就是可以将数据及复杂数据附加信息分离，并将各种原生数据结构（如：散列表、数组）用同一种语言表示。YAML则以数据的可扩展性作为替代。（包括为了模拟对象的类别类型）在YAML本身的规范中，并没有类似XML的语言定义文件刚要（language-defined document schema descriptors）──例如验证自己本身的结构是否正确的文件。不过，YAML纲要描述语言（YAML schema descriptor language）是存在的。另外还有YAXML──用XML描述YAML的结构──可以让XML Schema与XSLT转换程序应用在YAML之上。况且，在一般使用的情况下，YAML丰富的定义类型之语法已经提供了足够的方式，来辨认YAML文件是否正确。

缩进划界

由于YAML的运作主要依赖大纲式的缩进来决定结构，这有效解决了界定符冲突（Delimiter collision）的问题。YAML的数据形态不依赖引号之特点，使的YAML文件可以利用区块，轻易的插入各种其他类型文件，如：XML、SDL、JSON，甚至插入另一篇YAML。
---example: >
        HTML goes into YAML without modificationmessage: |

        <blockquote style="font: italic 12pt Times">
        <p>"Three is always greater than two,
           even for large values of two"</p>
        <p>--Author Unknown</p>
        </blockquote>
相反的，要将YAML置入XML或SDL中时，需要将所有空白字符和位势符号（potential sigils，如：<,>和&）转换成实体语法；要将YAML置入JSON中，需要用引号框住，并转换内部的所有引号。

非层次结构式的数据模型

跟SDL、JSON等，每个子结点只能有单一一个父节点的层次结构是模型不同，YAML提供了一个简单的关系体制，可以从树状结构的其他地方，重复相同的数据，而不必显示那些冗余的结构。这点和XML中的IDRef类似YAML剖析器在将YAML转换成对象时，会自动将那些参考资料的结构展开，所以程序在使用时并不会查觉到哪些数据是解码自这种结构。XML则不会将这种结构展开。这种表示法可以增加程序的可读性，并且，在那种‘大部分参数维持和上次相同，只有少数改变’的配置文件及通信协议中，可以减少数据输入错误。一个例子是：‘送货地点’和‘购买地点’在发票的纪录中几乎都是相同的数据。

实际的考量

YAML是“行导向的”，因此，就算想由现有程序的混乱输出，转换成YAML格式，并保留大部分的原始文件之外观，也非常简单。因为他不需要平衡封闭的标签、括弧及引号，可以从很简单的利用程序，从报表产生YAML。同样，空格分隔可让使用行导向的命令如：grep、Awk、perl、ruby，和Python，来应急性的过滤YAML文件时更加方便。
特别是与标记语言不同的，连续的YAML区块导向往往是格式良好的YAML文件本身。这使得很容易撰写那种“在开始提取的具体记录之前，不需要'读取全部文件内容'”的解析器（通常需要平衡起始和关闭标签、查找引号和转义字符）。当处理一个单一静态的，整个存在存储器中的数据结构将很大，或为提取一个项目来重建的整个结构，代价相当昂贵的记录档，这种特性是相当方便的。
值得讨论的是，尽管它的缩进方式似乎复杂化了深度很大的嵌套层次， YAML将缩进视为一个单一的空白，这可能会获取比其他标记语言更好的压缩比。此外，极深的缩进可以完全避免的是： (1)使用“内置格式”（即简称类JSON格式）而无缩进；或 (2)使用关系锚点展开层次结构以形成一个摊平的格式，使得YAML解析器能透明地重组成完整的数据结构。

安全性

YAML是纯粹用来表达数据的语言，所以内部不会存代码注射的可执行命令。这代表剖析器会相当（至少）安全的解析文件，而不用担心潜在与运行命令相关的安全漏洞。举例来说，JSON是JavaScript的子集，因此可能有人想使用JavaScript本身的剖析器直接eval，不过这样一来就造成许多代码注射的漏洞。虽然在所有数据序列语言中，安全解析本质上是可能的，但可执行性却正是这样一个恶名昭彰的缺陷；而YAML缺乏相关的命令语言，可能是一个相对安全的利益。

数据处理和呈现

XML和YAML规范提供非常不同的逻辑模型来进行数据结点的展现、处理及存储。

移植性

简单的YAML文件（例如：简单的键值对）不需要完整的YAML剖析器，便可以被正则表达式解析。许多常用的编程语言──纯用某个语言，让库具有可携性──都有的YAML的产生器和剖析器。当性能比较重要时，也有许多和C语言绑定的库可使用。