Conversation
…pping them python-docx reads the w:p and w:tbl children of the body, a cell, a header or a footer, and the runs and hyperlinks directly in a paragraph. Content one level deeper was skipped by partition_docx(): - paragraphs, tables, rows and runs held in a content control (w:sdt), which forms, templates and Word's document-property fields use; - text inserted or moved with track changes on (w:ins, w:moveTo); - runs in custom XML, smart tags, simple fields and bidirectional spans. When the document is loaded, each of these wrappers in the main document, header and footer parts is replaced by its content, in one pass over the tree. Every reader then sees that content without further changes: tables, headers, footers, links, emphasis and page breaks. Deleted and moved-away text stays where python-docx skips it. The automatic table of contents stays unread, and a control still showing its placeholder text is dropped. Resolves Unstructured-IO#3553 and Unstructured-IO#1821.
…rols-and-revisions # Conflicts: # CHANGELOG.md # unstructured/__version__.py
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
partition_docx()reads a document through python-docx. python-docx looks only at thew:pandw:tblchildren of the body, a table cell, a header or a footer, and at the runs and hyperlinks directly inside a paragraph. Content one level deeper is skipped without a warning:w:sdt): the paragraphs, tables, table rows and runs held in them. Forms, templates and cover pages use them, and so do the document properties Word inserts through Quick Parts (feat/docx-content-control-fields #3553).w:ins,w:moveTo): text inserted or moved with track changes on and not yet accepted (docx: partitioner finds text nested in revision-marks #1821).w:customXml,w:smartTag,w:fldSimple,w:dir,w:bdo).I built a probe document with one marker in each place and ran it through
partition_docx(). A check means the marker is in the output:mainw:customXmlChange
DocxPartitionerOptions.documentnow runs_unwrap_nested_content()right after loading, on the main document part and on every header and footer part. The function replaces each of these wrappers with its content, in place. The rest of the partitioner then sees that content as ordinary paragraphs, rows, cells and runs, and needs no change of its own. That covers body and section iteration, tables andtext_as_html, headers and footers, hyperlinks, emphasis, rendered page breaks and pictures.This is the "accept all revisions before partitioning" step proposed in #1821, extended to the other wrappers:
w:insandw:moveToare unwrapped, so the inserted or moved-in text is read.w:delandw:moveFromstay where they are. python-docx skips them there, so deleted and moved-away text stays out. The result is the text Word shows after "Accept All Changes".w:sdtis replaced by the children of itsw:sdtContent, at whatever level it sits: in the body, in a table (a repeating-section row), in a row (a cell), or in a paragraph (inline).w:customXml,w:smartTag,w:fldSimple,w:dirandw:bdoare unwrapped.Two content controls keep today's behaviour:
w:docPartGallery= "Table of Contents") stays unread, as it is now.w:showingPlcHdr), such as "Click or tap here to enter text.", is dropped. That text only says what to type, so it is not document content.Where these elements can appear, the analysis #1821 asked for:
w:insandw:moveTo: at run level. There are also empty marks inw:rPr,w:trPrandw:numPrthat hold no content, so removing an empty one changes nothing that is read.w:dirandw:bdo: at run level.Performance. Each part gets one
iter()filtered by tag.partition_docx()Testing
There are three new tests in
test_unstructured/partition/test_docx.py. Each builds its document intmp_path, like the merged-cell tests:test_partition_docx_reads_content_nested_in_content_controls_and_revisionscovers:w:dirandw:bdo;w:insin paragraph-mark properties.test_partition_docx_reads_content_controls_in_tables_headers_and_footerscovers a control in a cell, a row wrapped in a control (checked intextand intext_as_html), and controls in the header and the footer.test_partition_docx_leaves_out_the_table_of_contents_and_placeholder_textchecks that the table-of-contents control and a placeholder stay out.Results:
main, the first two tests fail. The third passes, because it pins the current behaviour. With the change, all 88 tests intest_docx.pypass.ruff checkandruff format --checkfrom ruff 0.15.10, the locked version, are clean.test_unstructured/chunking(405 passed, 31 skipped),test_unstructured/common/test_html_table.py(51 passed) andtest_unstructured/documents/test_elements.py(64 passed).example-docs/contains any of these elements; I checked all 204word/*.xmlparts. So no fixture or ingest output changes.Not run here:
test_doc.pyneeds LibreOffice; without it, it fails the same 20 tests onmain.test_auto.pyneedspdf2image.scripts/version-sync.shneeds GNU sed.CHANGELOG.mdand__version__.pyboth read0.27.9-dev0.#2944 describes a document property that vanishes from the output. If that property was inserted through Quick Parts > Document Property, it is a content control and this PR fixes it. I could not confirm that without the file.