Appendix C - 2. Office Models ({Slides,Docs,Sheets}Model)
The Structure of Office Models ({Slides,Docs,Sheets}Model) — its shape at a glance:
Three formats, one pattern. Each format's call sites route through its typed model; the models share a common layer. Two ban-lints guard the raw edges — one on the raw SDK, one on regexing the serialized XML.
flowchart LR
S[Slides sites] --> SM[Slides model]
D[Docs sites] --> DM[Docs model]
X[Sheets sites] --> XM[Sheets model]
SM --> Common["Shared common layer"]
DM --> Common
XM --> Common
Common --> Raw[(Raw office SDK)]
L{{Two ban-lints}} -. raw SDK + raw-XML regex .-> Raw
Accessible description: three format-specific call sites route through three typed models into a shared common layer, which is the only path to the raw office SDK. Two ban-lints guard the raw edges — one bans the raw SDK, one bans regexing the serialized XML — so no site skips the models.
Projected from the catalogue entry canonical-models-and-seams / Office Models ({Slides,Docs,Sheets}Model).
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — Route all remediation of a format family through one typed model, with raw library access (and raw string-matching into the serialized form) banned by lint. The same construction+ban-lint pattern as pdf-model, on a second object model (our instance: {Slides,Docs,Sheets}Model over DocumentFormat.OpenXml).
Motivation
Raw OpenXML SDK access, and the sneakier path of regexing into the XML, are the Office equivalent of the raw-PDF-library minefield: brittle, corruption-prone, and with no single point to enforce structural invariants. Left ad hoc, the same raw-library corruption class recurs across three separate document formats.
Applicability
- A typed model per Office format plus a shared common layer for cross-format primitives.
- Two ban-lints: one on the raw SDK, one on raw-XML string-matching (the sneaky path).
- Call-site migration across all three formats.
Structure
The Structure diagram appears at the top of this page.
Sample Code
The pattern is the same sole-seam-plus-ban-lint as any typed model, applied once per format over a shared base. What is worth showing is the second lint: the raw-SDK ban alone leaves a hole, because the serialized document is text and a caller can regex into it behind the model's back. The string-match ban closes that path.
import ast, sys
RAW_SDK_ROOT = "office_sdk" # the raw library the models wrap
SEAM_MODULES = {"slides_model", "docs_model", "sheets_model", "office_common"}
def lint(path: str, mod: str, source: str) -> list[str]:
if mod in SEAM_MODULES:
return [] # the models + common layer may touch the raw SDK
findings = []
for node in ast.walk(ast.parse(source)):
# ban 1: importing the raw SDK anywhere but the seam
if isinstance(node, ast.ImportFrom) and (node.module or "").startswith(RAW_SDK_ROOT):
findings.append(f"{path}:{node.lineno}: raw office SDK import — route through a typed model")
# ban 2: the sneaky path — a regex reaching into the serialized XML
if isinstance(node, ast.Attribute) and node.attr in {"search", "match", "findall"}:
findings.append(f"{path}:{node.lineno}: regex over serialized XML — walk the typed model instead")
return findings
if __name__ == "__main__":
hits = [f for p in sys.argv[1:] for f in lint(p, p.rsplit("/", 1)[-1][:-3], open(p).read())]
print("\n".join(hits)); sys.exit(1 if hits else 0)
Consequences
- Three models plus a shared layer to maintain — more surface than the single PdfModel.
- Coverage gaps per format force a
noqaor a model extension, same as PdfModel. - The string-match ban can false-positive on a legitimate string operation over document text, needing an escape.
Example use within DocAble
SlidesModel/DocsModel/SheetsModel+OpenXmlCommon;RuleWalkers/for the checking path.openxml-direct-access+no-raw-xml-string-matchban-lints.
Related Patterns
- See also (sibling) — pdf-model: the PDF half of the unified "typed model + ban-lint" pattern; together they consolidate the raw-library corruption defect class across all four formats.
- Counterpart — the
openxml-direct-access+no-raw-xml-string-matchlints (hard) hold these construction-mode seams in place. - See also — canonical-walkers: traversal over the Office models' trees.