基本介紹
- 中文名:另一種標記語言
- 外文名:YAML Ain't Markup Language
- 中文縮寫:標言
- 外語縮寫:YAML
介紹,誕生,命名,功能,格式,多行縮進,單行縮寫,適用場景,腳本語言,序列化,配置檔案,語言比較,JSON,XML和SDL,縮排劃界,非階層式的資料模型,實際的考量,安全性,資料處理和呈現,函式庫,移植性,C語言,Perl,PHP,Python,Ruby,Java,R,JavaScript,.NET,OCaml,C++,Objective-C,Lua,Haskell,XML,Go,常見錯誤與使用細節,宿主語言,相關概念,討論,
介紹
誕生
Clark Evans在2001年5月在首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。
命名
YAML是"YAML Ain't a Markup Language"(YAML不是一種置標語言)的遞歸縮寫。
在開發的這種語言時,YAML 的意思其實是:"Yet Another Markup Language"(仍是一種置標語言),
功能
YAML的語法和其他高階語言類似,並且可以簡單表達清單、散列表,標量等資料形態、。
它使用空白符號縮排和大量依賴外觀的特色,特別適合用來表達或編輯數據結構、各種設定檔、傾印除錯內容、檔案大綱(例如:許多電子郵件標題格式和YAML非常接近)。
儘管它比較適合用來表達階層式(hierarchical model)的數據結構,不過也有精緻的語法可以表示關聯性(relational model)的資料。
由於YAML使用空白字元和分行來分隔資料,使得它他特別適合用grep、Python、Perl、Ruby操作。
其讓人最容易上手的特色是巧妙避開各種封閉符號,如:引號、各種括弧等,這些符號在嵌套結構中會變得複雜而難以辨認。
格式
多行縮進
數據結構可以用類似大綱的縮排方式呈現,結構通過縮進來表示,連續的項目通過減號“-”來表示,map結構裡面的key/value對用冒號“:”來分隔。樣例如下:
house: family: name: Doe parents: - John - Jane children: - Paul - Mark - Simone address: number: 34 street: Main Street city: Nowheretown zipcode: 12345
注意:
- 字串不一定要用雙引號標識;
- 在縮排中空白字元的數目並不是非常重要,只要相同階層的元素左側對齊就可以了(不過不能使用TAB字元);
- 允許在檔案中加入選擇性的空行,以增加可讀性;
- 在一個檔案中,可同時包含多個檔案,並用“——”分隔;
- 選擇性的符號“...”可以用來表示檔案結尾(在利用串流的通訊中,這非常有用,可以在不關閉串流的情況下,傳送結束訊號)。
單行縮寫
YAML也有用來描述好幾行相同結構的數據的縮寫語法,數組用'[]'包括起來,hash用'{}'來包括。因此,上面的這個YAML能夠縮寫成這樣:
house: family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] } address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }
適用場景
腳本語言
由於實現簡單,解析成本很低,YAML特別適合在腳本語言中使用。列一下現有的語言實現:Ruby,Java,Perl,Python,PHP,OCaml,JavaScript,Go 。除了Java 和 Go,其他都是腳本語言。
序列化
YAML比較適合做序列化。因為它是宿主語言數據類型直轉的。
配置檔案
YAML做配置檔案也不錯。寫YAML要比寫XML快得多(無需關註標簽或引號),並且比ini文檔功能更強。
比如Ruby on Rails的配置就選用的YAML。對ROR而言,這很自然,也很省事.
由於兼容性問題,不同語言間的數據流轉建議不要用YAML.
語言比較
雖然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。
相反的,要將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將縮排視為一個單一的空白,這可能會取得比其他標記語言更好的壓縮比。此外,極深的縮排可以完全避免的是:
- 使用“內置格式”(即簡稱類JSON格式)而無縮排;
- 使用關聯錨點展開階層以形成一個攤平的格式,使得YAML解析器能透明地重組成完整的數據結構。
安全性
YAML是純粹用來表達資料的語言,所以內部不會存代碼注入的可執行命令。這代表剖析器會相當(至少)安全的解析檔案,而不用擔心潛在與執行命令相關的安全漏洞。舉例來說,JSON是JavaScript的子集,使用JavaScript本身的剖析器是相當誘人的,不過也造成許多代碼注入的漏洞。雖然在所有資料序列語言中,安全解析本質上是可能的,但可執行性卻正是這樣一個惡名昭彰的缺陷;而YAML缺乏相關的命令語言,可能相對安全。
資料處理和呈現
XML和YAML規範提供非常不同的邏輯模型來進行資料結點的展現、處理及儲存。
函式庫
移植性
簡單的YAML檔案(例如:簡單的鍵值對)不需要完整的YAML剖析器,便可以被RegEx解析。許多常用的程式語言──純用某個語言,讓函式庫具有可攜性──都有的YAML的產生器和剖析器。當效能比較重要時,也有許多和C語言綁定的函式庫可使用。
C語言
- libYAML
2007-06時,這個YAML的函式庫漸趨穩定,並被YAML格式作者推薦使用[13]。
- SYCK
這個實現支持大部分1.0版的格式,並且被廣泛的使用。它使用高階interpreted languages進行最佳化。在2005之後,這個專案已經不再更新,不過仍可使用。
Perl
- YAML::
一個通用的接口,被數個YAML剖析器使用。
- YAML::Tiny
YAML簡化版的實現。擁有小巧輕快的優點──比完整功能的YAML實現快上許多──並用純Perl寫成。
- YAML::Syck
與SYCK函式庫綁定。提供快速,highly featured的YAML剖析器。
- YAML::XS
與LibYaml綁定。提供1.1版更好的相容性。
PHP
- Spyc
純PHP的實現。
- PHP-Syck
與SYCK函式庫綁定。
- sfYaml
為symfony項目重寫的Spyc, 可獨立使用, 可以產生和剖析YAML檔案。
Python
- PyYaml
純Python,或可選用LibYAML的函式庫。
- PySyck
與SYCK綁定。
Ruby
從1.8版開始,YAML剖析器成為標準函式庫之一。以SYCK為基礎。
- Ya2YAML
with full UTF-8 support
Java
- jvyaml
以Syck為基礎,and patterned off ruby-yaml
- JYaml
純Java的實現。
R
- CRAN YAML
以SYCK為基礎。
JavaScript
原生的JavaScript即可產生YAML,但不能剖析。
- YAML JavaScript
產生和剖析。
.NET
待補充。
OCaml
- OCaml-Syck
C++
用C++將libYaml包裝。
Objective-C
- Cocoa-Syck
Lua
- Lua-Syck
Haskell
- Haskell Reference wrappers
XML
- YAXML
currently draft only。
Go
- Go-yaml
常見錯誤與使用細節
- 編輯器
建議使用能將跳格字元自動轉換成空白字元的編輯器,並且使用定寬度的字型。
編輯器要能正確的處理UTF-8和UTF16編碼(或是使用純ASCII編碼──它同時是UTF-8的子集)。
- 字串
YAML的字串不需使用引號,這可以避免使用複雜的轉義字元,以增加可讀性。然而,這有時也會導致錯誤,例如,字串本身是一個曖昧的字眼(像數字或布爾值);或在短句中意外的出現YAML的結構符號(常見的例子是由驚嘆號起始的句子,或是包含冒號-空白的句子:"!Caca de vaca!"、"Caution: lions ahead")。這在發布YAML檔案時並不造成困擾,但在製作小型指令碼和人工編輯檔案時,這問題還蠻常出現的。比較好的方法是善用區塊符號("|" or ">")而不要使用單行字串,來避免這種曖昧的表達方式。
- 預期實做的特性
宿主語言
相關概念
YAML沒有自己的數據類型的定義,而是使用實現語言的數據類型。
例如,上面的那個YAML配置,在不同語言中解析後得到的數據類型並不相同。
- PHP
$house = array('family' => array('name' => 'Doe','parents' => array('John', 'Jane'),'children' => array('Paul', 'Mark', 'Simone')),'address' => array('number' => 34,'street' => 'Main Street','city' => 'Nowheretown','zipcode' => '12345'));
- PYTHON
house = {family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] },address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }}
討論
這一點, 有可能是出奇制勝的地方,也可能是一個敗筆。如果兼容性保證的不好的話,YAML數據在不同語言間流轉會有問題。如果兼容性好的話,YAML就會成為不同語言間數據流通的橋樑。建議YAML官方設立兼容認證機制,每個語言的實現必須通過認證。
假如兼容性沒問題的話,YAML就太完美了。輕巧,敏捷,高效,簡便,通用。這才是理想中的數據模型。當然就現在而言,這還只是個理想。