Как преобразовать дерево документов docutils в строку HTML?

Я пытаюсь использовать пакет docutils для преобразования ReST в HTML. В этом ответе кратко используются удобные функции docutils publish_* для достижения этого за один шаг. Документы ReST, которые я хочу преобразовать, имеют несколько разделов, которые я хочу разделить в результирующем HTML. Таким образом, я хочу разбить этот процесс:

  1. Разберите ReST в дереве узлов.
  2. Разделите узлы соответствующим образом.
  3. Преобразуйте узлы, которые я хочу, в HTML.

Это третий шаг, с которым я борюсь. Вот как я делаю шаги один и два:

from docutils import utils
from docutils.frontend import OptionParser
from docutils.parsers.rst import Parser

# preamble
rst = '*NB:* just an example.'   # will actually have many sections
path = 'some.url.com'
settings = OptionParser(components=(Parser,)).get_default_values()

# step 1
document = utils.new_document(path, settings)
Parser().parse(rst, document)

# step 2
for node in document:
   do_something_with(node)

# step 3: Help!
for node in filtered(document):
   print(convert_to_html(node))

Я нашел класс HTMLTranslator и класс Publisher. Они кажутся актуальными, но я изо всех сил пытаюсь найти хорошую документацию. Как мне реализовать функцию convert_to_html?


person dsclose    schedule 23.08.2015    source источник


Ответы (1)


Моя проблема заключалась в том, что я пытался использовать пакет docutils на слишком низком уровне. Они предоставляют интерфейс для такого рода вещей:

from docutils.core import publish_doctree, publish_from_doctree

rst = '*NB:* just an example.'

# step 1
tree = publish_doctree(rst)

# step 2
# do something with the tree

# step 3
html = publish_from_doctree(tree, writer_name='html').decode()
print(html)

Шаг первый теперь намного проще. Тем не менее, я все еще немного недоволен результатом; Я понимаю, что мне действительно нужна функция publish_node. Если вы знаете лучший способ, пожалуйста, опубликуйте его.

Я также должен отметить, что мне не удалось заставить это работать с Python 3.

Настоящий урок

Что я на самом деле пытался сделать, так это извлечь все элементы боковой панели из дерева документов, чтобы их можно было обрабатывать отдельно от основной части статьи. Это не тот вариант использования, для решения которого предназначался docutils. Следовательно, нет функции publish_node.

Как только я понял это, правильный подход был достаточно прост:

  1. Сгенерируйте HTML, используя docutils.
  2. Извлеките элементы боковой панели, используя BeautifulSoup.

Вот код, который выполнил работу:

from docutils.core import publish_parts
from bs4 import BeautifulSoup

rst = get_rst_string_from_somewhere()

# get just the body of an HTML document 
html = publish_parts(rst, writer_name='html')['html_body']
soup = BeautifulSoup(html, 'html.parser')

# docutils wraps the body in a div with the .document class
# we can just dispose of that div altogether
wrapper = soup.select('.document')[0]
wrapper.unwrap()

# knowing that docutils gives all sidebar elements the
# .sidebar class makes extracting those elements easy
sidebar = ''.join(tag.extract().prettify() for tag in soup.select('.sidebar'))

# leaving the non-sidebar elements as the document body
body = soup.prettify()
person dsclose    schedule 23.08.2015