【问题标题】:accessing bookmarks using python-docx使用 python-docx 访问书签
【发布时间】:2021-11-22 10:40:12
【问题描述】:

我正在使用 python-docx 模块来读取和编辑 .docm 文件, 该文件包含书签,如何访问已使用该模块存储的所有书签,文档对象中似乎没有任何方法。

【问题讨论】:

标签: python ms-word python-docx


【解决方案1】:

正如@D Malan 所评论的那样,现在在 2021 年至 11 月,它仍然是 python-docx 中的一个开放的issue

同时我们可以接受我们自己的实现。

请在可作为导入访问的文件夹中创建一个名为 docxbookmark.py 的文件:

from docx.document import Document as _innerdoclass
from docx import Document as _innerdocfn
from docx.oxml.shared import qn
from lxml.etree import Element as El

class Document(_innerdoclass):
    def _bookmark_elements(self, recursive=True):
        if recursive:
            startag = qn('w:start')
            bkms = []
            def _bookmark_elements_recursive(parent):
                if parent.tag == startag:
                    bkms.append(parent)
                for el in parent:
                    _bookmark_elements_recursive(el)
            _bookmark_elements_recursive(self._element)
            return bkms
        else:
            return self._element.xpath('//'+qn('w:bookmarkStart'))
    def bookmark_names(self):
        """
        Gets a list of bookmarks
        """
        return [v for bkmkels in self._bookmark_elements() for k,v in bkmkels.items() if k.endswith('}name')]
    def add_bookmark(self, bookmarkname):
        """
        Adds a bookmark with bookmark with name bookmarkname to the end of the file
        """
        el = [el for el in self._element[0] if el.tag.endswith('}p')][-1]
        el.append(El(qn('w:bookmarkStart'),{qn('w:id'):'0',qn('w:name'):bookmarkname}))
        el.append(El(qn('w:bookmarkEnd'),{qn('w:id'):'0'}))
    def __init__(self, innerDocInstance = None):
        super().__init__(Document, None)
        if innerDocInstance is not None and type(innerDocInstance) is _innerdoclass:
            self.__body = innerDocInstance.__body
            self._element = innerDocInstance._element
            self._part = innerDocInstance._part

def DocumentCreate(docx=None):
    """
    Return a |Document| object loaded from *docx*, where *docx* can be
    either a path to a ``.docx`` file (a string) or a file-like object. If
    *docx* is missing or ``None``, the built-in default document "template"
    is loaded.
    """
    return Document(_innerdocfn(docx))

现在我们可以像旧的一样使用我们的外观实现,以及那些新的add_bookmarkbookmark_names

要在新文件中添加书签,请导入我们的实现并在文档对象上使用add_bookmark

from docxbookmark import DocumentCreate as Document

doc = Document()
document.add_paragraph('First Paragraph')
document.add_bookmark('FirstBookmark')
document.add_paragraph('Second Paragraph')
document.save('docwithbookmarks.docx')

要查看文档中的书签,请导入我们的实现并在文档对象上使用bookmark_names

from docxbookmark import DocumentCreate as Document

doc = Document('docwithbookmarks.docx')
doc.bookmark_names()

返回的列表比其他对象更简单,它只显示字符串而不是对象。有一个内部 _bookmark_elements 将返回与 python-docx 对象不同的 lxml 节点。

仅进行了一些测试,在许多情况下可能无法正常工作。如果不起作用,请在 cmets 中告知。

【讨论】:

  • 感谢您的详尽回答。在赏金到期之前我没有时间尝试它,所以我还是继续并授予它。只问一个问题:有什么方法可以编辑答案以在 python-docx 中链接问题?
  • 好的,添加链接并感谢您的赏金
猜你喜欢
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 2020-04-24
  • 1970-01-01
  • 2020-12-27
  • 2020-01-02
相关资源
最近更新 更多