Inject a Microsoft Word extension element (w14:checkbox) into a run's rPr. python-docx's object model has no proxy for checkbox — the only reason it can survive a round-trip is the xmlchemy descriptor contract that unknown children of known elements are preserved verbatim. This manifest pins that contract.
Library verdicts: python-docx: — docxjs: —
| Feature id | docx/round-trip-unknown-preservation |
|---|---|
| Format | docx |
| Category | round-trip |
| Spec | ecma-376-5-part-1 § annex-A.4 w14:checkbox |
| ID / part | Predicate | XPath | python-docx | docxjs |
|---|---|---|---|---|
w14-checkbox-preservedword/document.xml | existThe injected <w14:checkbox> element must survive round-trip as a child of the run's rPr. | //w:r[w:t[normalize-space()='Text with unknown extension']]/w:rPr/w14:checkbox | — | — |
w14-checked-val-preservedword/document.xml | equal = 1The nested <w14:checked w14:val='1'/> must survive with its attribute intact. | //w:r[w:t[normalize-space()='Text with unknown extension']]/w:rPr/w14:checkbox/w14:checked/@w14:val | — | — |
run-text-preservedword/document.xml | existSanity: the run text itself must survive. | //w:r/w:t[normalize-space()='Text with unknown extension'] | — | — |
No render assertions declared.
scripts/gen_round_trip_unknown_preservation.py
#!/usr/bin/env python3
"""Generate round-trip-unknown-preservation twin.
Critical round-trip check: author a document that contains a Microsoft
Word extension element the python-docx object model has no proxy for.
Round-trip it. Assert the unknown element survived.
Mechanism: we inject a `<w14:checkbox>` / `<w14:checked>` pair into a
run's `<w:rPr>` via raw lxml SubElement (bypassing xmlchemy). This is
EXACTLY the shape a Word-authored document would carry when a user
drops a content control into a paragraph. python-docx's descriptor
layer has no `checkbox` property on CT_RPr; the only reason the element
round-trips is the xmlchemy passthrough contract that says "unknown
children of a known element are preserved verbatim". If that contract
ever regresses, this fixture fails.
The twin is committed. The source is ephemeral scratch.
"""
from __future__ import annotations
import argparse
import sys
import tempfile
from pathlib import Path
from docx import Document
from lxml import etree
_REPO_ROOT = Path(__file__).resolve().parent.parent
W14_NS = "http://schemas.microsoft.com/office/word/2010/wordml"
def build_source(source_path: Path) -> None:
doc = Document()
p = doc.add_paragraph()
r = p.add_run("Text with unknown extension")
rPr = r._element.get_or_add_rPr() # type: ignore[attr-defined]
checkbox = etree.SubElement(rPr, f"{{{W14_NS}}}checkbox")
checked = etree.SubElement(checkbox, f"{{{W14_NS}}}checked")
checked.set(f"{{{W14_NS}}}val", "1")
source_path.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(source_path), reproducible=True)
def round_trip(source_path: Path, twin_path: Path) -> None:
doc = Document(str(source_path))
twin_path.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(twin_path), reproducible=True)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--out", required=True, help="Twin output path (repo-relative).")
ns = parser.parse_args(argv)
twin_path = _REPO_ROOT / ns.out
with tempfile.NamedTemporaryFile(suffix=".docx", delete=False) as tmp:
source_path = Path(tmp.name)
try:
build_source(source_path)
round_trip(source_path, twin_path)
finally:
source_path.unlink(missing_ok=True)
print(twin_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())
{
"$schema": "../manifest.schema.json",
"id": "docx/round-trip-unknown-preservation",
"title": "Round-trip unknown-element preservation (python-docx)",
"format": "docx",
"category": "round-trip",
"summary": "Inject a Microsoft Word extension element (w14:checkbox) into a run's rPr. python-docx's object model has no proxy for checkbox — the only reason it can survive a round-trip is the xmlchemy descriptor contract that unknown children of known elements are preserved verbatim. This manifest pins that contract.",
"spec": {
"source": "ecma-376-5-part-1",
"clause": "annex-A.4",
"element": "w14:checkbox",
"notes": "w14:checkbox is documented under [MS-DOCX] / [MS-OE376] Word 2010 extensions, not the ECMA-376 core. It is the inline content-control that Word renders as a clickable checkbox. python-docx doesn't model it, so a library that treats unknown rPr children as 'discard on read' would silently delete it. The xmlchemy ZeroOrMore / ZeroOrOne descriptors only remove *known* child types; anything else is left on the etree subtree and re-emitted on save. This manifest is the canary for that behaviour."
},
"fixtures": {
"machine": "docx/round-trip-unknown-preservation"
},
"round_trip": {
"library": "python-docx",
"source_fixture": "docx/round-trip-unknown-preservation",
"notes": "Mode B (generator-embedded). Source built inline with a raw lxml SubElement under the run's rPr; twin produced by a single python-docx load-save cycle."
},
"generator": {
"python": "scripts/gen_round_trip_unknown_preservation.py",
"arg_template": "--out fixtures/docx/round-trip-unknown-preservation.docx"
},
"assertions": [
{
"id": "w14-checkbox-preserved",
"part": "word/document.xml",
"namespaces": {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
"w14": "http://schemas.microsoft.com/office/word/2010/wordml"
},
"xpath": "//w:r[w:t[normalize-space()='Text with unknown extension']]/w:rPr/w14:checkbox",
"must": "exist",
"description": "The injected <w14:checkbox> element must survive round-trip as a child of the run's rPr."
},
{
"id": "w14-checked-val-preserved",
"part": "word/document.xml",
"namespaces": {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
"w14": "http://schemas.microsoft.com/office/word/2010/wordml"
},
"xpath": "//w:r[w:t[normalize-space()='Text with unknown extension']]/w:rPr/w14:checkbox/w14:checked/@w14:val",
"must": "equal",
"value": "1",
"description": "The nested <w14:checked w14:val='1'/> must survive with its attribute intact."
},
{
"id": "run-text-preserved",
"part": "word/document.xml",
"namespaces": {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
},
"xpath": "//w:r/w:t[normalize-space()='Text with unknown extension']",
"must": "exist",
"description": "Sanity: the run text itself must survive."
}
]
}
No rendered reference is available for this case.