[Content_Types].xml must register the required Default entries for rels and xml extensions, plus an Override binding the main document part to the WordprocessingML document content type.
Library verdicts: python-docx: — docxjs: —
| Feature id | docx/content-type-registration |
|---|---|
| Format | docx |
| Category | opc-packaging |
| Spec | ecma-376-5-part-2 § 10.1 ct:Types |
| ID / part | Predicate | XPath | python-docx | docxjs |
|---|---|---|---|---|
default-rels-registered[Content_Types].xml | equal = application/vnd.openxmlformats-package.relationships+xmlThe `rels` extension Default must map to the OPC relationships content type. | //ct:Default[@Extension='rels']/@ContentType | — | — |
default-xml-registered[Content_Types].xml | equal = application/xmlThe `xml` extension Default must map to application/xml. | //ct:Default[@Extension='xml']/@ContentType | — | — |
override-document-main[Content_Types].xml | equal = application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xmlThe main document part must be explicitly bound to the WordprocessingML document content type via an Override. | //ct:Override[@PartName='/word/document.xml']/@ContentType | — | — |
override-styles-present[Content_Types].xml | equal = application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xmlThe styles part must be registered via Override (its URI shares the .xml Default extension but the part needs the WML-styles content type, so Override resolution takes precedence per OPC §10.1.2.4). | //ct:Override[@PartName='/word/styles.xml']/@ContentType | — | — |
override-core-properties-present[Content_Types].xml | equal = application/vnd.openxmlformats-package.core-properties+xmlThe OPC core-properties part must be registered via Override. | //ct:Override[@PartName='/docProps/core.xml']/@ContentType | — | — |
no-duplicate-overrides[Content_Types].xml | absentOPC §10.1.2.2 forbids two Override entries for the same PartName — catches a family of serialiser-duplication bugs. | //ct:Override[@PartName = following-sibling::ct:Override/@PartName] | — | — |
primary-document-rel-exists_rels/.rels | match = ^/?word/document\.xml$The package's /_rels/.rels must advertise exactly one officeDocument relationship whose Target is word/document.xml (leading slash optional per OPC §8.3). | //r:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument']/@Target | — | — |
No render assertions declared.
scripts/gen_content_type_registration.py
#!/usr/bin/env python3
"""Generate ``fixtures/docx/content-type-registration.docx``.
A minimal empty document. The manifest assertions target the structural
OPC plumbing (``[Content_Types].xml`` and ``_rels/.rels``) rather than any
specific WordprocessingML content, so the body can be empty.
Manifest: ``features/docx/content-type-registration.json``
"""
from __future__ import annotations
from pathlib import Path
from docx import Document
_REPO_ROOT = Path(__file__).resolve().parent.parent
_OUT = _REPO_ROOT / "fixtures" / "docx" / "content-type-registration.docx"
def main() -> int:
doc = Document()
# one paragraph so document.xml has at least one w:p — some validators
# flag an empty body, and this keeps the fixture opaque to unrelated
# future tightening of the corpus' sanity checks.
doc.add_paragraph("Content-type registration fixture.")
_OUT.parent.mkdir(parents=True, exist_ok=True)
doc.save(_OUT, reproducible=True)
print(_OUT)
return 0
if __name__ == "__main__":
raise SystemExit(main())
{
"$schema": "../manifest.schema.json",
"id": "docx/content-type-registration",
"title": "Content-type registration (Default + Override)",
"format": "docx",
"category": "opc-packaging",
"summary": "[Content_Types].xml must register the required Default entries for rels and xml extensions, plus an Override binding the main document part to the WordprocessingML document content type.",
"spec": {
"source": "ecma-376-5-part-2",
"clause": "10.1",
"element": "ct:Types",
"notes": "ECMA-376 Part 2 (OPC) §10.1 — every part's content type is discovered by matching the part URI against Override entries first, then falling back to Default entries keyed on the part's URI extension. Every well-formed OOXML package therefore needs Default entries for at least the `rels` and `xml` extensions (because _rels/.rels and metadata XML parts rely on them), plus one Override per non-default content type. This manifest asserts the Defaults are present and that /word/document.xml is registered as the WordprocessingML main document content type — a structural OPC invariant python-docx must always satisfy, independent of any document content."
},
"fixtures": {
"machine": "docx/content-type-registration"
},
"generator": {
"python": "scripts/gen_content_type_registration.py"
},
"assertions": [
{
"id": "default-rels-registered",
"part": "[Content_Types].xml",
"namespaces": {
"ct": "http://schemas.openxmlformats.org/package/2006/content-types"
},
"xpath": "//ct:Default[@Extension='rels']/@ContentType",
"must": "equal",
"value": "application/vnd.openxmlformats-package.relationships+xml",
"description": "The `rels` extension Default must map to the OPC relationships content type."
},
{
"id": "default-xml-registered",
"part": "[Content_Types].xml",
"namespaces": {
"ct": "http://schemas.openxmlformats.org/package/2006/content-types"
},
"xpath": "//ct:Default[@Extension='xml']/@ContentType",
"must": "equal",
"value": "application/xml",
"description": "The `xml` extension Default must map to application/xml."
},
{
"id": "override-document-main",
"part": "[Content_Types].xml",
"namespaces": {
"ct": "http://schemas.openxmlformats.org/package/2006/content-types"
},
"xpath": "//ct:Override[@PartName='/word/document.xml']/@ContentType",
"must": "equal",
"value": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
"description": "The main document part must be explicitly bound to the WordprocessingML document content type via an Override."
},
{
"id": "override-styles-present",
"part": "[Content_Types].xml",
"namespaces": {
"ct": "http://schemas.openxmlformats.org/package/2006/content-types"
},
"xpath": "//ct:Override[@PartName='/word/styles.xml']/@ContentType",
"must": "equal",
"value": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
"description": "The styles part must be registered via Override (its URI shares the .xml Default extension but the part needs the WML-styles content type, so Override resolution takes precedence per OPC §10.1.2.4)."
},
{
"id": "override-core-properties-present",
"part": "[Content_Types].xml",
"namespaces": {
"ct": "http://schemas.openxmlformats.org/package/2006/content-types"
},
"xpath": "//ct:Override[@PartName='/docProps/core.xml']/@ContentType",
"must": "equal",
"value": "application/vnd.openxmlformats-package.core-properties+xml",
"description": "The OPC core-properties part must be registered via Override."
},
{
"id": "no-duplicate-overrides",
"part": "[Content_Types].xml",
"namespaces": {
"ct": "http://schemas.openxmlformats.org/package/2006/content-types"
},
"xpath": "//ct:Override[@PartName = following-sibling::ct:Override/@PartName]",
"must": "absent",
"description": "OPC §10.1.2.2 forbids two Override entries for the same PartName — catches a family of serialiser-duplication bugs."
},
{
"id": "primary-document-rel-exists",
"part": "_rels/.rels",
"namespaces": {
"r": "http://schemas.openxmlformats.org/package/2006/relationships"
},
"xpath": "//r:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument']/@Target",
"must": "match",
"value": "^/?word/document\\.xml$",
"description": "The package's /_rels/.rels must advertise exactly one officeDocument relationship whose Target is word/document.xml (leading slash optional per OPC §8.3)."
}
]
}
No rendered reference is available for this case.