如何在 Python 中将 Markdown 字符串转换为 DocX?

Onu*_*ule 7 html python markdown docx jinja2

我从 API 中获取 Markdown 文本,如下所示:

{
    name:'Onur',
    surname:'Gule',
    biography:'## Computers
    I like **computers** so much.
    I wanna *be* a computer.',
    membership:1
}
Run Code Online (Sandbox Code Playgroud)

传记列包括像上面这样的 Markdown 字符串。

## Computers
I like **computers** so much.
I wanna *be* a computer.
Run Code Online (Sandbox Code Playgroud)

我想将此 Markdown 文本转换为 docx 字符串以用于我的报告。

在我的 docx 模板中:

{{markdownText|mark2html}}

{{simpleText}}
Run Code Online (Sandbox Code Playgroud)

我正在使用 python3 docxtpl包来创建 docx,它适用于简单的文本。

  • 我尝试使用 BeautifulSoup 将 markdown 转换为 docx 文本,但它不适用于样式(粗体、斜体等)。
  • 我尝试了 pandoc 并且它有效,但它只是创建了一个 docx 文件,我想将渲染的 markdown 文本添加到现有的 docx(在创建时)。

我当前的代码:

## Computers
I like **computers** so much.
I wanna *be* a computer.
Run Code Online (Sandbox Code Playgroud)

那么,如何将渲染的 markdown 添加到现有的 docx 或创建时(也许使用 jinja2 过滤器)?

Onu*_*ule 9

我解决了,没有任何捷径。我使用 beautifulSoup 将 markdown 转换为 html,然后通过检查它们的标签名称来处理每个段落。

在我的Word模板中:

{% if markdownText != None %}
    {% for mt in markdownText|mark2html %} 
        {{mt}}
    {% endfor %}
{% endif %}
Run Code Online (Sandbox Code Playgroud)

我的模板标签:

def mark2html(value):
    if value == None:
        return '-'
    html = markdown.markdown(value)
    soup = BeautifulSoup(html, features='html.parser')
    paragraphs = []
    global doc
    for tag in soup.findAll(True):
        if tag.name in ('p','h1','h2','h3','h4','h5','h6'):
            paragraphs.extend(parseHtmlToDoc(tag))  
    return paragraphs
Run Code Online (Sandbox Code Playgroud)

我插入 docx 的代码:

def parseHtmlToDoc(org_tag):
    contents = org_tag.contents
    pars= []
    for con in contents:
        if str(type(con)) == "<class 'bs4.element.Tag'>":
            tag = con
            if tag.name in ('strong',"h1","h2","h3","h4","h5","h6"):
                source = RichText("")
                if len(pars) > 0 and str(type(pars[len(pars)-1])) == "<class 'docxtpl.richtext.RichText'>":
                    source = pars[len(pars)-1]
                    source.add(con.contents[0], bold=True)
                else:
                    source.add(con.contents[0], bold=True)
                    pars.append(source) 
            elif tag.name == 'img':
                source = tag['src']
                imagen = InlineImage(doc, settings.MEDIA_ROOT+source)
                pars.append(imagen)
            elif tag.name == 'em':
                source = RichText("")
                source.add(con.contents[0], italic=True)
                pars.append(source)
        else:
            source = RichText("")
            if len(pars) > 0 and str(type(pars[len(pars)-1])) == "<class 'docxtpl.richtext.RichText'>":
                    source = pars[len(pars)-1]
                    pars.add(con)
            else:
                if org_tag.name == 'h2':
                    source.add(con,bold=True,size=40)
                else:
                    source.add(con)
                pars.append(source) # her zaman append?
    return pars
Run Code Online (Sandbox Code Playgroud)

它处理 html 标签,如 b、i、img、标题。您可以添加更多标签来处理。我这样解决了,它不需要任何额外的文件转换,如 html2docx 等。

我在我的代码中使用了这个过程,如下所示:

report_context = {'reportVariables': report_variables}
template = DocxTemplate('report_format.docx')
jenv = jinja2.Environment()
jenv.filters["mark2html"] = mark2html
template.render(report_context,jenv)
template.save('exported_1.docx')
Run Code Online (Sandbox Code Playgroud)