Excel always emits <dxfs>, <tableStyles>, and an <extLst> wrapping <x14:slicerStyles> on xl/styles.xml. python-xlsx currently drops all three when they are empty-or-only-defaults on load, which breaks slicer-style references and pivot default styles. This manifest rides a real Excel-authored workbook through load_workbook + wb.save and re-checks the three survivors.
Library verdicts: python-xlsx: — xlsxjs: —
| Feature id | xlsx/preserve-dxfs |
|---|---|
| Format | xlsx |
| Category | round-trip |
| Spec | ecma-376-5-part-1 § 18.8.15 dxfs |
| ID / part | Predicate | XPath | python-xlsx | xlsxjs |
|---|---|---|---|---|
dxfs-element-preservedxl/styles.xml | existThe <dxfs> element must survive the load/save round-trip even if count="0". | //x:styleSheet/x:dxfs | — | — |
tableStyles-element-preservedxl/styles.xml | existThe <tableStyles> element must survive. Its defaultTableStyle / defaultPivotStyle attributes are what Excel uses for newly-inserted tables and pivots. | //x:styleSheet/x:tableStyles | — | — |
slicerStyles-ext-preservedxl/styles.xml | existThe <extLst>/<ext>/<x14:slicerStyles> chain must survive. Dropping it detaches every existing slicer from its style. | //x:styleSheet/x:extLst/x:ext/x14:slicerStyles | — | — |
No render assertions declared.
{
"$schema": "../manifest.schema.json",
"id": "xlsx/preserve-dxfs",
"title": "Preserve <dxfs>, <tableStyles> and <extLst>/<slicerStyles> across round-trip",
"format": "xlsx",
"category": "round-trip",
"summary": "Excel always emits <dxfs>, <tableStyles>, and an <extLst> wrapping <x14:slicerStyles> on xl/styles.xml. python-xlsx currently drops all three when they are empty-or-only-defaults on load, which breaks slicer-style references and pivot default styles. This manifest rides a real Excel-authored workbook through load_workbook + wb.save and re-checks the three survivors.",
"roles": [
"authoring"
],
"spec": {
"source": "ecma-376-5-part-1",
"clause": "18.8.15",
"element": "dxfs",
"rnc_reference": "spec/ecma-376-5/part-1/rnc/SpreadsheetML.rnc",
"xsd_reference": "spec/ecma-376-5/part-1/xsd/sml.xsd",
"notes": "dxfs (differential formatting records) is the child-table that cell-level conditional formats, table styles, and pivot styles index into. Even empty (<dxfs count=\"0\"/>) Excel writes it because downstream readers treat it as a schema sentinel — removing it means the sibling <tableStyles defaultTableStyle=\"…\" defaultPivotStyle=\"…\"/> entry is re-evaluated at their own defaults on reopen. The <extLst>/x14:slicerStyles chain (defined by MS-OE376, namespace http://schemas.microsoft.com/office/spreadsheetml/2009/9/main) is likewise mandatory for workbooks that have ever carried a slicer. See ECMA-376 Part 1 clauses 18.8.15 (dxfs), 18.8.42 (tableStyles), 18.2.10 (extLst). Code: src/xlsx/styles/stylesheet.py::write_stylesheet — the writer skips the element when the in-memory list is empty, without checking whether the on-disk file had it."
},
"fixtures": {
"machine": "xlsx/preserve-dxfs"
},
"round_trip": {
"library": "python-xlsx",
"source_fixture": "xlsx/preserve-dxfs",
"notes": "Source is a copy of python-xlsx's own bundled book1.xlsx external-link test fixture — originally authored in Excel, shipped with the project's test suite as representative Excel output. Runner loads it, saves through python-xlsx, and evaluates the assertions against the re-saved bytes."
},
"assertions": [
{
"id": "dxfs-element-preserved",
"part": "xl/styles.xml",
"namespaces": {
"x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//x:styleSheet/x:dxfs",
"must": "exist",
"description": "The <dxfs> element must survive the load/save round-trip even if count=\"0\"."
},
{
"id": "tableStyles-element-preserved",
"part": "xl/styles.xml",
"namespaces": {
"x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//x:styleSheet/x:tableStyles",
"must": "exist",
"description": "The <tableStyles> element must survive. Its defaultTableStyle / defaultPivotStyle attributes are what Excel uses for newly-inserted tables and pivots."
},
{
"id": "slicerStyles-ext-preserved",
"part": "xl/styles.xml",
"namespaces": {
"x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
"x14": "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
},
"xpath": "//x:styleSheet/x:extLst/x:ext/x14:slicerStyles",
"must": "exist",
"description": "The <extLst>/<ext>/<x14:slicerStyles> chain must survive. Dropping it detaches every existing slicer from its style."
}
]
}
No rendered reference is available for this case.