Skip to content

When there are empty references in a docx document, parsing will throw an error. #170

Description

@glorialucheng

问题

当docx文档里存在空的引用时,解析报错:

Traceback (most recent call last):
  File "D:\miniconda3\Lib\runpy.py", line 198, in _run_module_as_main
    return _run_code(code, main_globals, None,
                     "__main__", mod_spec)
  File "D:\miniconda3\Lib\runpy.py", line 88, in _run_code
    exec(code, run_globals)
    ~~~~^^^^^^^^^^^^^^^^^^^
  File "c:\Users\gloria\.vscode\extensions\ms-python.debugpy-2026.6.0-win32-x64\bundled\libs\debugpy\launcher/../..\debugpy\__main__.py", line 71, in <module>
    cli.main()
    ~~~~~~~~^^
  File "c:\Users\gloria\.vscode\extensions\ms-python.debugpy-2026.6.0-win32-x64\bundled\libs\debugpy\launcher/../..\debugpy/..\debugpy\server\cli.py", line 542, in main
    run()
    ~~~^^
  File "c:\Users\gloria\.vscode\extensions\ms-python.debugpy-2026.6.0-win32-x64\bundled\libs\debugpy\launcher/../..\debugpy/..\debugpy\server\cli.py", line 361, in run_file
    runpy.run_path(target, run_name="__main__")
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\gloria\.vscode\extensions\ms-python.debugpy-2026.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 310, in run_path
    return _run_module_code(code, init_globals, run_name, pkg_name=pkg_name, script_name=fname)
  File "c:\Users\gloria\.vscode\extensions\ms-python.debugpy-2026.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 127, in _run_module_code
    _run_code(code, mod_globals, init_globals, mod_name, mod_spec, pkg_name, script_name)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\gloria\.vscode\extensions\ms-python.debugpy-2026.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 118, in _run_code
    exec(code, run_globals)
    ~~~~^^^^^^^^^^^^^^^^^^^
  File "d:\projects\python-mammoth\test.py", line 5, in <module>
    result = mammoth.convert_to_html(docx_file)
  File "d:\projects\python-mammoth\mammoth\__init__.py", line 12, in convert_to_html
    return convert(*args, output_format="html", **kwargs)
  File "d:\projects\python-mammoth\mammoth\__init__.py", line 39, in convert
    return options.read_options(kwargs).bind(lambda convert_options:
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
        docx.read(fileobj, external_file_access=external_file_access).map(transform_document).bind(lambda document:
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<5 lines>...
        )
        ^
    )
    ^
  File "d:\projects\python-mammoth\mammoth\results.py", line 15, in bind
    result = func(self.value)
  File "d:\projects\python-mammoth\mammoth\__init__.py", line 40, in <lambda>
    docx.read(fileobj, external_file_access=external_file_access).map(transform_document).bind(lambda document:
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
        conversion.convert_document_element_to_html(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<3 lines>...
        )
        ^
    )
    ^
  File "d:\projects\python-mammoth\mammoth\results.py", line 15, in bind
    result = func(self.value)
  File "d:\projects\python-mammoth\mammoth\__init__.py", line 41, in <lambda>
    conversion.convert_document_element_to_html(
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        document,
        ^^^^^^^^^
        id_prefix=id_prefix,
        ^^^^^^^^^^^^^^^^^^^^
        **convert_options
        ^^^^^^^^^^^^^^^^^
    )
    ^
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 49, in convert_document_element_to_html
    nodes = converter.visit(element, context)
  File "<string>", line 5, in visit
  File "<string>", line 1, in _accept1
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 83, in visit_document
    nodes = self._visit_all(document.children, context)
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 323, in _visit_all
    for html_node in self.visit(element, context)
                     ~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "<string>", line 5, in visit
  File "<string>", line 1, in _accept1
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 106, in visit_paragraph
    return html_path.wrap(children)
           ~~~~~~~~~~~~~~^^^^^^^^^^
  File "d:\projects\python-mammoth\mammoth\html_paths.py", line 33, in wrap
    nodes = generate_nodes()
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 99, in children
    content = self._visit_all(paragraph.children, context)
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 323, in _visit_all
    for html_node in self.visit(element, context)
                     ~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "<string>", line 5, in visit
  File "<string>", line 1, in _accept1
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 137, in visit_run
    return nodes()
  File "d:\projects\python-mammoth\mammoth\html_paths.py", line 33, in wrap
    nodes = generate_nodes()
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 110, in <lambda>
    nodes = lambda: self._visit_all(run.children, context)
                    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 323, in _visit_all
    for html_node in self.visit(element, context)
                     ~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "<string>", line 5, in visit
  File "<string>", line 1, in _accept1
  File "d:\projects\python-mammoth\mammoth\conversion.py", line 77, in visit_image
    return self._convert_image(image)
           ~~~~~~~~~~~~~~~~~~~^^^^^^^
  File "d:\projects\python-mammoth\mammoth\images.py", line 12, in convert_image
    attributes.update(func(image))
                      ~~~~^^^^^^^
  File "d:\projects\python-mammoth\mammoth\images.py", line 24, in data_uri
    with image.open() as image_bytes:
         ~~~~~~~~~~^^
  File "d:\projects\python-mammoth\mammoth\docx\body_xml.py", line 593, in open_image
    image_file = docx_file.open(image_path)
  File "d:\projects\python-mammoth\mammoth\zips.py", line 23, in open
    return contextlib.closing(self._zip_file.open(name))
                              ~~~~~~~~~~~~~~~~~~~^^^^^^
  File "D:\miniconda3\Lib\zipfile\__init__.py", line 1652, in open
    zinfo = self.getinfo(name)
  File "D:\miniconda3\Lib\zipfile\__init__.py", line 1580, in getinfo
    raise KeyError(
        'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'word/../NULL' in the archive"

输入的文件由于涉及隐私,因此无法共享,该解压后的docx文件里的 path/to/.docx/word/_rels/document.xml.rels 的内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships
    xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="rId9" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer2.xml"/>
    <Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer1.xml"/>
    <Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header1.xml"/>
    <Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes" Target="endnotes.xml"/>
    <Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" Target="footnotes.xml"/>
    <Relationship Id="rId4" Type="http://schemas.microsoft.com/office/2011/relationships/commentsExtended" Target="commentsExtended.xml"/>
    <Relationship Id="rId37" Type="http://schemas.microsoft.com/office/2011/relationships/people" Target="people.xml"/>
    <Relationship Id="rId36" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
    <Relationship Id="rId35" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" Target="../customXml/item3.xml"/>
    <Relationship Id="rId34" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" Target="../customXml/item2.xml"/>
    <Relationship Id="rId33" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Target="numbering.xml"/>
    <Relationship Id="rId32" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" Target="../customXml/item1.xml"/>
    <Relationship Id="rId31" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image18.png"/>
    <Relationship Id="rId30" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image17.png"/>
    <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" Target="comments.xml"/>
    <Relationship Id="rId29" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image16.png"/>
    <Relationship Id="rId28" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image15.png"/>
    <Relationship Id="rId27" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image14.png"/>
    <Relationship Id="rId26" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image13.png"/>
    <Relationship Id="rId25" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image12.png"/>
    <Relationship Id="rId24" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image11.png"/>
    <Relationship Id="rId23" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image10.png"/>
    <Relationship Id="rId22" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image9.png"/>
    <Relationship Id="rId21" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image8.png"/>
    <Relationship Id="rId20" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image7.png"/>
    <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
    <Relationship Id="rId19" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image6.png"/>
    <Relationship Id="rId18" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image5.png"/>
    <Relationship Id="rId17" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image4.png"/>
    <Relationship Id="rId16" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../NULL"/>
    <Relationship Id="rId15" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image2.png"/>
    <Relationship Id="rId14" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png"/>
    <Relationship Id="rId13" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
    <Relationship Id="rId12" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer4.xml"/>
    <Relationship Id="rId11" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header2.xml"/>
    <Relationship Id="rId10" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer3.xml"/>
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
</Relationships>

上面的 <Relationship Id="rId16" ... Target="../NULL"/> 导致的bug。
python-docx也有类似的问题,参考:https://github.com/python-openxml/python-docx/issues/797 and https://github.com/python-openxml/python-docx/issues/1105#issuecomment-1298075246

修复建议

https://github.com/glorialucheng/python-mammoth/commit/9c7f73f5884f06084143ffab5470b403fc9e7ef1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions