Skip to content

fix(docx): create document.xml.rels when missing in comment.py - #1790

Open
TINGyu123644 wants to merge 2 commits into
anthropics:mainfrom
TINGyu123644:fix/docx-comment-relationships
Open

TINGyu123644 wants to merge 2 commits into
anthropics:mainfrom
TINGyu123644:fix/docx-comment-relationships

Conversation

@TINGyu123644

Copy link
Copy Markdown

What changed

skills/docx/scripts/comment.py now creates word/_rels/document.xml.rels when it is missing instead of skipping it, registering the four comment relationships (comments.xml, commentsExtended.xml, commentsIds.xml, commentsExtensible.xml) as rId1-rId4.

Why

Defect 2 in #1770: word/_rels/document.xml.rels is optional in a valid minimal DOCX. The old code returned early when it was absent, yet add_comment carried on and wrote comments.xml plus the satellite comment parts - so the comment part existed with nothing referencing it and Word could not resolve it.

How verified

  • Built a minimal unpacked DOCX with no word/_rels/document.xml.rels and ran add_comment against both the old and the fixed code.
  • Old: comments.xml written, relationships part never created (orphaned comments - the reported defect).
  • Fixed: document.xml.rels created with exactly the four comment relationships, each Id/Type/Target matching _COMMENT_RELS; comments.xml written; python -m py_compile clean.
  • The existing-document path (rels already present) is untouched.

add_comment skipped creating word/_rels/document.xml.rels when it was absent, then wrote comments.xml anyway, leaving the comment parts orphaned and unresolvable in Word. Now the relationships part is created with the four comment relationships (rId1-rId4) when missing. Addresses defect 2 in anthropics#1770.
@98zc5g5jyw-arch

Copy link
Copy Markdown

Reviewed at head ff947c15 (base 34040c9). Two-state check with a minimal unpacked DOCX that has no word/_rels/document.xml.rels, plus a variant whose rels part already exists (rId1 styles):

  • ✅ Base reproduces defect 2: the four comment parts are written, no relationships part is created.
  • ✅ Head creates word/_rels/document.xml.rels on first touch with exactly the four comment relationships rId1-rId4 (Id/Type/Target match _COMMENT_RELS); a rerun is byte-stable; the .docx round trip contains the part.
  • ✅ Existing-rels path is untouched: appends the four relationships after the highest existing rId, original preserved, and the result validates against the repo's OPC schema.
  • ✅ python -m py_compile clean; construction uses stdlib minidom while all parsing stays on defusedxml.

One change needed — the created part is missing the OPC namespace declaration. It serializes as:

<Relationships><Relationship Id="rId1" ... /></Relationships>

xml.dom.minidom keeps the namespace passed to createDocument() in the DOM but does not emit it when serializing — only explicitly-set attributes are written (same behaviour on CPython 3.9, 3.11 and 3.12). Against the repo's own office/schemas/ecma/fouth-edition/opc-relationships.xsd the part fails validation ("No matching global declaration available for the validation root", xmllint rc 3), and namespace-aware consumers ({http://schemas.openxmlformats.org/package/2006/relationships}Relationship) see zero relationships — i.e. defect 2 persists for anything that resolves namespaces.

Suggested:

  1. Set the declaration explicitly after root = dom.documentElement — one line:

    root.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")

    I applied exactly this line to a scratch copy: the part then validates (xmllint rc 0) and ElementTree resolves {...}Relationships with the four child relationships; the diff against the unpatched output is the xmlns attribute alone. Building the part from a template string (the COMMENT_XML style) works just as well — the serialized bytes just need to carry the declaration.

  2. Worth asserting the namespace in your verification step so this class of miss gets caught.

Everything else checks out; happy to re-review the updated head.

minidom keeps the namespace passed to createDocument() in the DOM but does not serialize it, so the created part lacked the xmlns declaration and failed OPC schema validation. Set xmlns explicitly on the root element.
@TINGyu123644

Copy link
Copy Markdown
Author

Fixed per review: the created part now carries the OPC namespace declaration. Added root.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships") after the root element.

Re-verified on the new head 903e013:

  • The serialized part contains xmlns="http://schemas.openxmlformats.org/package/2006/relationships";
  • Namespace-aware parse (ElementTree) resolves the root as {...}Relationships with exactly the four {...}Relationship children, Ids rId1-rId4;
  • Id/Type/Target still match _COMMENT_RELS; python -m py_compile clean;
  • Existing-rels path untouched (parse-and-append branch unchanged).

@98zc5g5jyw-arch

Copy link
Copy Markdown

Re-verified at head 903e013 — the created part now carries the declaration. Same two-state check as before, run against both heads locally:

  • ✅ Created-from-scratch: the part now serializes with xmlns="http://schemas.openxmlformats.org/package/2006/relationships"; xmllint --noout --schema office/schemas/ecma/fouth-edition/opc-relationships.xsd → rc 0. On the pre-fix head ff947c15 the same part comes out at 602 bytes without the declaration and fails with rc 3 ("No matching global declaration"), with ElementTree resolving Relationships un-namespaced and 0 child relationships — so the added line is load-bearing (671 vs 602 bytes = the attribute).
  • ✅ Namespace-aware parse: the root resolves as {…relationships}Relationships with exactly the four {…}Relationship children rId1–rId4.
  • ✅ Rerun is byte-stable; the existing-rels branch is untouched: appends after the existing rId1 styles relationship (rId2–rId5), original preserved, still validates.
  • ✅ python -m py_compile clean.

All good from my side — thanks for the quick turnaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants