docs(docx): clarify safe OOXML serialization

This commit is contained in:
Sylvester Kaczmarek 2026-08-14 17:50:42 +01:00
parent f6656c1256
commit d939a8760e
1 changed files with 9 additions and 0 deletions

View File

@ -58,6 +58,15 @@ python scripts/office/validate.py out.docx --original doc.docx # XSD checks; -
# redlining? add --author "<the name you redlined under>" to check every edit is tracked
```
When editing OOXML with `xml.dom.minidom` or `defusedxml.minidom`, preserve the existing XML formatting. Serialize with `toxml()`, not `toprettyxml()`:
```python
with open(xml_path, "wb") as f:
f.write(doc.toxml(encoding="utf-8"))
```
`toprettyxml()` inserts indentation and newline text into the package XML and can make the resulting document unreadable in Word or LibreOffice. Do not pretty-print OOXML after editing it.
Word splits text across many `<w:r>` runs (revision ids, spell-check markers), so a phrase you can see in the document often doesn't exist as a contiguous string in the XML. `merge_runs.py` merges adjacent identically-formatted runs in `word/document.xml` without changing content or rendering; it also accepts a `.docx` directly (`python scripts/merge_runs.py doc.docx -o merged.docx`).
**Tracked changes:** when redlining, validate with `--author "<the name you redlined under>"` (needs `--original`) — it reports any text you changed without a `<w:ins>`/`<w:del>` around it, which is easy to do by accident and invisible in the accepted view. Wrap runs in `<w:ins>`/`<w:del>` with `w:id`, `w:author`, `w:date` attributes. Inside `<w:del>`, the text element is `<w:delText>`, not `<w:t>`. A deleted paragraph mark (`<w:pPr><w:rPr><w:del w:id=".." w:author=".." w:date=".."/></w:rPr></w:pPr>`) means "merge this paragraph into the next" — so deleting a paragraph outright is that plus a `<w:del>` around every run. The `<w:del/>` must come before the rPr's other children; their order is schema-enforced.