2012-05-26 3 views
6

から抽出フィールドリストは、私は次のreST入力を持って言う:私はで終わるしたい何reStructuredTextの

Some text ... 

:foo: bar 

Some text ... 

は、このような辞書です:

{"foo": "bar"} 

私はこれを使用しようとしました:

tree = docutils.core.publish_parts(text) 

それは、フィールドリストを解析し、私はtree["whole"]?にいくつかの擬似XMLで終わる:

<document source="<string>"> 
    <docinfo> 
     <field> 
      <field_name> 
       foo 
      <field_body> 
       <paragraph> 
        bar 

tree dictのは、他の有用な情報が含まれておらず、それは単なる文字列であるので、私は、REST文書からフィールドリストを解析する方法がわからないです。どうすればいい?

答えて

7

次のコードのようなものを使用できます。 publish_partsメソッドを使用するのではなく、publish_doctreeを使用して、ドキュメントの疑似XML表現を取得しました。私はその後、すべてのfield要素を抽出するためにXML DOMに変換しました。次に、field要素の最初のfield_namefield_body要素を取得します。

from docutils.core import publish_doctree 

source = """Some text ... 

:foo: bar 

Some text ... 
""" 

# Parse reStructuredText input, returning the Docutils doctree as 
# an `xml.dom.minidom.Document` instance. 
doctree = publish_doctree(source).asdom() 

# Get all field lists in the document. 
fields = doctree.getElementsByTagName('field') 

d = {} 

for field in fields: 
    # I am assuming that `getElementsByTagName` only returns one element. 
    field_name = field.getElementsByTagName('field_name')[0] 
    field_body = field.getElementsByTagName('field_body')[0] 

    d[field_name.firstChild.nodeValue] = \ 
     " ".join(c.firstChild.nodeValue for c in field_body.childNodes) 

print d # Prints {u'foo': u'bar'} 

xml.domモジュールを作成すると処理が最も簡単ではありません(なぜ私が.firstChild.nodeValueではなく、例えば、単に.nodeValueを使用する必要があります)あなたは、私は非常に簡単に見つけるxml.etree.ElementTreeモジュールを、使用することを望むかもしれないので、一緒に働くlxmlを使用する場合は、XPATH表記法を使用してfield,field_nameおよびfield_body要素のすべてを見つけることもできます。

+0

ありがとうございます、それは私が探しているようです! –

0

私には負担が少ないが、おそらくより脆い代替ソリューションがあります。ノードクラスhttps://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/docutils/nodes.pyの実装を見直した後、データの2つの異なるxml表現を作成せずに、必要なデータを引き出すのに使用できるwalkメソッドをサポートしていることがわかります。ここに私のprotoypeコードで、私が今使っているものです:

https://github.com/h4ck3rm1k3/gcc-introspector/blob/master/peewee_adaptor.py#L33

、その後

def walk_docstring(prop): 
    doc = prop.__doc__ 
    doctree = publish_doctree(doc) 
    class Walker: 
     def __init__(self, doc): 
      self.document = doc 
      self.fields = {} 
     def dispatch_visit(self,x): 
      if isinstance(x, docutils.nodes.field): 
       field_name = x.children[0].rawsource 
       field_value = x.children[1].rawsource 
       self.fields[field_name]=field_value 
    w = Walker(doctree) 
    doctree.walk(w) 
    # the collected fields I wanted 
    pprint.pprint(w.fields) 
0

は、ここに私のElementTree実装です:

from docutils.core import publish_doctree 
from xml.etree.ElementTree import fromstring 

source = """Some text ... 

:foo: bar 

Some text ... 
""" 


def gen_fields(source): 
    dom = publish_doctree(source).asdom() 
    tree = fromstring(dom.toxml()) 

    for field in tree.iter(tag='field'): 
     name = next(field.iter(tag='field_name')) 
     body = next(field.iter(tag='field_body')) 
     yield {name.text: ''.join(body.itertext())} 

使用

>>> next(gen_fields(source)) 
{'foo': 'bar'} 
関連する問題