2012-11-10 49 views
13

我從YAML數據製作一個文檔生成器,它將指定每個項目從哪個YAML文件生成。做這個的最好方式是什麼?因此,如果YAML文件是這樣的:解析YAML,用行號返回

- key1: item 1 
    key2: item 2 
- key1: another item 1 
    key2: another item 2 

我想是這樣的:

[ 
    {'__line__': 1, 'key1': 'item 1', 'key2': 'item 2'}, 
    {'__line__': 3, 'key1': 'another item 1', 'key2': 'another item 2'}, 
] 

我目前使用PyYAML,但是任何其他庫是確定的,如果我可以從Python中使用它。

回答

10

我已通過添加鉤去到Composer.compose_nodeConstructor.construct_mapping

import yaml 
from yaml.composer import Composer 
from yaml.constructor import Constructor 

def main(): 
    loader = yaml.Loader(open('data.yml').read()) 
    def compose_node(parent, index): 
     # the line number where the previous token has ended (plus empty lines) 
     line = loader.line 
     node = Composer.compose_node(loader, parent, index) 
     node.__line__ = line + 1 
     return node 
    def construct_mapping(node, deep=False): 
     mapping = Constructor.construct_mapping(loader, node, deep=deep) 
     mapping['__line__'] = node.__line__ 
     return mapping 
    loader.compose_node = compose_node 
    loader.construct_mapping = construct_mapping 
    data = loader.get_single_data() 
    print(data) 
+0

謝謝 - 這個工作完美,並且在錯誤報告方面非常有用。 –

2

對於更多的靈感,這是我此代碼。它包含比以上請求更多的信息,因爲它使用每個字典/列表/ unicode上的start_mark,end_mark(分別使用dict_node,list_node,unicode_node子類)報告位置信息。

https://gist.github.com/dagss/5008118

3

如果您正在使用ruamel.yaml> = 0.9(其中我的作者),並使用RoundTripLoader,你可以在藏品訪問屬性lc獲得的行和列,他們在開始源YAML:

def test_item_04(self): 
    data = load(""" 
    # testing line and column based on SO 
    # http://stackoverflow.com/questions/13319067/ 
    - key1: item 1 
     key2: item 2 
    - key3: another item 1 
     key4: another item 2 
     """) 
    assert data[0].lc.line == 2 
    assert data[0].lc.col == 2 
    assert data[1].lc.line == 4 
    assert data[1].lc.col == 2 

(行和列從0開始計數)。

This answer顯示如何在加載期間將lc屬性添加到字符串類型。

+0

如果列表位於有序地圖中,無法找到讓這項工作成功的方法,就像'key1:!! omap \ n - key4:item2 \ n - key3:item3'那樣,無法訪問'key4'和'key3'行號。 – zezollo

+0

@zezollo有序圖不會默認加載到一個CommentedMap結構中,因此不具有'lc'屬性。您將不得不將!omap加載註冊爲評論圖的子類。這是可行的,但我不能在評論中回答。如果你不知道如何去做,你應該發佈一個新的問題。 – Anthon

+0

的確我無法弄清楚這一點。我只找到了一個「髒」的解決方法來獲取行號。問[問]在這裏(https://stackoverflow.com/questions/45716281/parsing-yaml-get-line-numbers-even-in-ordered-maps)。 – zezollo