2012-11-10 12 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からそれを使用することができれば他のライブラリはOKです。私はComposer.compose_nodeConstructor.construct_mappingにフックを追加することによって、それを作った

答えて

10

:さらにインスピレーションを得るため

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

、ここでは、このための私のコードです。これは、dict_node、list_node、unicode_nodeサブクラスをそれぞれ使用して、各dict/list/unicodeのstart_mark、end_markを使用して位置情報を報告するため、上記の情報よりも多くの情報を含んでいます。

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

3

あなたは(私は作者午前うち)> = 0.9 ruamel.yamlを使用して、そして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'のように、リストが順序付けされたマップの中にあれば、これを動作させる方法を見つけることができませんでした。 'key3'行番号です。 – zezollo

+0

@zezollo orderedmedmapは、デフォルトではCommentedMap構造体にロードされず、したがって 'lc'属性を持ちません。 !omapの読み込みをCommentedMapのサブクラスとして登録する必要があります。それは実行可能ですが、私はコメントで答えることができます。あなたがそれを行う方法を理解できなければ、新しい質問を投稿するべきです。 – Anthon

+0

確かに私はこれを理解できません。私は行番号を取得するための "汚い"回避策を見つけただけです。質問しました[ここ](https://stackoverflow.com/questions/45716281/parsing-yaml-get-line-numbers-even-in-ordered-maps)。 – zezollo