2012-07-03 9 views
3

У меня есть форматированная dhstx строка, из которой я хотел бы извлечь различные части (param, return, type, rtype и т. Д.) Для дальнейшей обработки. Как я могу это достичь?Parse sphinx like documentation

+0

Эти два ответа помогут вам начать работу: http://stackoverflow.com/a/11117575/623518 и http://stackoverflow.com/a/10782270/623518 – Chris

ответ

8

Вы можете использовать docutils, на котором построен Сфинкс. В this other answer Я использую docutils.core.publish_doctree, чтобы получить представление XML документа reStructuredText (фактически строку текста), а затем извлечь списки полей из этого XML с помощью методов xml.minidom. Альтернативным методом является использование xml.etree.ElementTree, которое, на мой взгляд, гораздо проще использовать.

Во-первых, тем не менее, каждый раз, когда Docutils встречает блок ReStructuredText как

:param x: Some parameter 

полученное представление XML (я знаю, это довольно многословен):

<field_list> 
    <field> 
     <field_name> 
      param x 
     </field_name> 
     <field_body> 
      <paragraph> 
       Some parameter 
      </paragraph> 
     </field_body> 
    </field> 
</field_list> 

Следующий код будет возьмите все field_list элементов в документе и поместите текст с field/field_name и field/field_body/paragraph в виде 2-х кортежей в списке. Затем вы можете манипулировать этим, как вы хотите для последующей обработки.

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

source = """Some help text 

:param x: some parameter 
:type x: and it's type 

:return: Some text 
:rtype: Return type 

Some trailing text. I have no idea if the above is valid Sphinx 
documentation! 
""" 

doctree = publish_doctree(source).asdom() 

# Convert to etree.ElementTree since this is easier to work with than 
# xml.minidom 
doctree = etree.fromstring(doctree.toxml()) 

# Get all field lists in the document. 
field_lists = doctree.findall('field_list') 

fields = [f for field_list in field_lists \ 
    for f in field_list.findall('field')] 

field_names = [name.text for field in fields \ 
    for name in field.findall('field_name')] 

field_text = [etree.tostring(element) for field in fields \ 
    for element in field.findall('field_body')] 

print zip(field_names, field_text) 

Это дает список:

[('param x', '<field_body><paragraph>some parameter</paragraph></field_body>'), 
('type x', "<field_body><paragraph>and it's type</paragraph></field_body>"), 
('return', '<field_body><paragraph>Some text</paragraph></field_body>'), 
('rtype', '<field_body><paragraph>Return type</paragraph></field_body>')] 

Таким образом, первый элемент в каждом кортеже является элементом списка поля (т.е. :return:, :param x: и т.д.), а второй элементом является соответствующим текстом. Очевидно, что этот текст не самый чистый вывод, но этот код довольно легко изменить, поэтому я оставляю его до OP, чтобы получить точный результат, который они хотят.

 Смежные вопросы

  • Нет связанных вопросов^_^