diff options
| -rw-r--r-- | mammoth/docx/__init__.py | 39 | ||||
| -rw-r--r-- | tests/docx/docx_tests.py | 36 |
2 files changed, 69 insertions, 6 deletions
diff --git a/mammoth/docx/__init__.py b/mammoth/docx/__init__.py index 5b21e18..e98d4b6 100644 --- a/mammoth/docx/__init__.py +++ b/mammoth/docx/__init__.py @@ -50,9 +50,23 @@ def _find_part_paths(zip_file): package_relationships = _read_relationships(zip_file, "_rels/.rels") document_filename = _find_document_filename(zip_file, package_relationships) + document_relationships = _read_relationships( + zip_file, + _find_relationships_path_for(document_filename), + ) + + def find(name): + return _find_part_path( + zip_file=zip_file, + relationships=document_relationships, + relationship_type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/" + name, + fallback_path="word/{0}.xml".format(name), + base_path=zips.split_path(document_filename)[0], + ) + return _PartPaths( main_document=document_filename, - comments="word/comments.xml", + comments=find("comments"), endnotes="word/endnotes.xml", footnotes="word/footnotes.xml", numbering="word/numbering.xml", @@ -61,14 +75,27 @@ def _find_part_paths(zip_file): def _find_document_filename(zip_file, relationships): - office_document_type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" + path = _find_part_path( + zip_file, + relationships, + relationship_type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", + base_path="", + fallback_path="word/document.xml", + ) + if zip_file.exists(path): + return path + else: + raise IOError("Could not find main document part. Are you sure this is a valid .docx file?") + + +def _find_part_path(zip_file, relationships, relationship_type, base_path, fallback_path): targets = [ - target.lstrip("/") - for target in relationships.find_targets_by_type(office_document_type) - ] + ["word/document.xml"] + zips.join_path(base_path, target).lstrip("/") + for target in relationships.find_targets_by_type(relationship_type) + ] valid_targets = list(filter(lambda target: zip_file.exists(target), targets)) if len(valid_targets) == 0: - raise IOError("Could not find main document part. Are you sure this is a valid .docx file?") + return fallback_path else: return valid_targets[0] diff --git a/tests/docx/docx_tests.py b/tests/docx/docx_tests.py index a474b17..64a3b81 100644 --- a/tests/docx/docx_tests.py +++ b/tests/docx/docx_tests.py @@ -101,6 +101,42 @@ class TestPartPaths(object): part_paths = self._find_part_paths(fileobj) assert_equal("word/document.xml", part_paths.main_document) + @istest + def comments_part_is_found_using_main_document_relationships(self): + fileobj = _create_zip({ + "_rels/.rels": textwrap.dedent("""\ + <?xml version="1.0" encoding="utf-8"?> + <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> + <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document.xml" Id="rId1"/> + </Relationships> + """), + "word/document.xml": " ", + "word/_rels/document.xml.rels": textwrap.dedent("""\ + <?xml version="1.0" encoding="utf-8"?> + <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> + <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" Target="target-path.xml" Id="rId2"/> + </Relationships> + """), + "word/target-path.xml": " " + }) + part_paths = self._find_part_paths(fileobj) + assert_equal("word/target-path.xml", part_paths.comments) + + @istest + def when_relationship_for_comments_cannot_be_found_then_fallback_is_used(self): + fileobj = _create_zip({ + "_rels/.rels": textwrap.dedent("""\ + <?xml version="1.0" encoding="utf-8"?> + <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> + <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document.xml" Id="rId1"/> + </Relationships> + """), + "word/document.xml": " ", + }) + part_paths = self._find_part_paths(fileobj) + assert_equal("word/comments.xml", part_paths.comments) + + def _find_part_paths(self, fileobj): return docx._find_part_paths(zips.open_zip(fileobj, "r")) |
