跳到正文

ADR-0042:XML 模板多级十进制编号 ​

  • 日期:2026-10-16
  • 状态:已实施,阶段三十五本地验收通过
  • 范围:版本 1 XML 的 numbered 静态层级声明

背景 ​

既有 NumberedItem 模型接受 1..9 级,组件语义降级与 DOCX 导出已实现父级计数、同级继续、显式重启和祖先回退。XML 已解析 numbered 的 level,却只接受 1,导致同一文档结构必须改用 Java 编写才能声明多级列表。

多级编号依赖实际展开顺序。条件可能隐藏父项,循环可能执行零次,片段又有独立的限定 list-id。编译器需要检查所有原型的静态属性,但不能把一种未选中的控制流序列当作最终文档,或者在绑定阶段新增第二套编号器。

决策 ​

将 XML numbered 的静态 level 扩为 1..9,省略仍为 1。仍使用现有整数解析器;不是数据表达式。0、10、整数溢出、非整数和插值均以 TemplateException.Code.INVALID_VALUE 拒绝,保留 numbered 叶的一基行列和已有可选片段名。未知属性、非法块位置和名单边界维持原规则。

编译继续遍历 then/else 全部分支与 each 原型,即使绑定时不选择分支或循环执行零次,非法静态层级仍会失败。合法 level 2 原型可以通过编译;是否存在父级计数,只能根据实际展开后的文档判断。

DocumentTemplate.render 保留 NumberedItem 的 listId、level、restartAt、完整格式和富文本运行。它不检查整份文档的父级完整性。后续 DocumentEngine 通过既有 SemanticBlocks 降级为编号段落并检查父级,DOCX 导出通过现有原生编号路径检查父级;不在 XML、绑定器或核心 DocumentLayouter 新增编号计数。

计数、复制与引用 ​

同 list-id 使用九级独立计数,跨页/跨节不隐式重启。restart="0" 或省略表示当前级继续,正整数重设当前级;每次更新均清空更深级。父级不存在时,子级的正 restart 也不能补造父项。继续计数保留 Math.addExact,超过 int 上限明确失败,不绕回负数。

例如 (level,restart) 为 (1,3),(2,2),(3,0),(2,0),(1,0),(2,0),完整编号是 3,3.2,3.2.1,3.3,4,4.1。绘制前缀追加 . ;编号引用只返回完整编号,不附加该前缀后缀。

each 继续给块 ID 添加 @i 并重定位同副本的静态字段目标,不给 list-id 添加迭代后缀。不同迭代共享原列表,父项与显式 restart 决定是否重置。include 继续按静态 prefix 限定 list-id,独立片段实例不能从主模板或另一实例借父计数;派生 list-id owner 碰撞仍在编译阶段拒绝。

XML 编号正文仍只接受现有纯文字与 span 富文本,编号内 link、字段、图像和块内容继续拒绝。Java NumberedItem.rich 自身支持的外链不等于 XML 开放该语法。number-reference 仍位于合法段落/单元格的固定宽度框中,并指向明确编号块;静态外链可以放在这些段落中。字段放不下完整编号时失败,不改为最末级数字或自动缩字。

既有排版与 DOCX 边界 ​

组件编号缩进继续按 (level-1) × fontSize × 1.5 增加首行与续行缩进,前缀使用段落默认样式,原文运行和链接独立保留。高层级在窄区无法容纳时明确失败。本项不改变字体策略、塑形、分页或链接坐标算法。

DOCX 继续写零基 w:ilvl、完整十进制 w:lvlText 和各级有效 startOverride。当前每条项目分配独立 numId,不保证连续项目共享 native numId;验证应解析有效编号定义和值,并保留本项目 od:listId/od:restart 来源提示。原生编号引用继续使用 REF ... \w \h。

本项目生成文件可按已有严格语义子集往返。外部 Word 文档的任意起点、覆盖和定制标签仍按 STRICT 拒绝或 ALLOW_LOSS 返回诊断;不扩为通用编号恢复,不保证 Word 与 PDF 分页一致或任意阅读器字段更新。

预算与失败阶段 ​

XML 输入、源/展开元素与文字、硬深度、绑定节点/块/行/文字、布局行/页/指令及 DOCX 包字节预算保持。语义 level 不增加 XML 树嵌套深度。九级正 int 完整编号最多 98 字符,绘制前缀最多 100 字符;生成段落仍受既有布局码点预算控制。

静态属性错误属于带 XML 位置的编译失败。动态父项缺失、编号溢出、布局宽度和固定引用框不足属于展开后的既有处理阶段,不声称它们带原 XML 行列。现有语义降级在核心预算验证前生成前缀,本项没有新增提前计费、流式布局或恶意输入隔离。

验证要求与范围 ​

行为验证覆盖九级边界、全部分支静态错误、合法动态父项/隐藏父项/空循环、缺级、祖先回退清零、同级重启、不同列表、跨页/跨节、include 隔离、each 当前副本完整引用、编号富文本及普通段落外链保留、int 溢出、宽度/预算及取消恢复。完整 Java 模型对照与现有编号行为共同证明扩展复用原契约。

有限页数 XML→PDF/DOCX 样例及隔离 Maven 调用方独立检查最终完整编号、原文、固定字段框、物理链接坐标、native ilvl/lvlText/有效各级覆盖,并严格回读完整模型。只有确认的默认单运行表示可精确归一;不能仅比较块 ID。全部新增 PDF 页面双渲染并逐页检查后,再登记验收。

没有新模块、模型、依赖、编号器、字体或第三方实现复制。不扩展 bullet 层级、格内块白名单、Markdown、动态 level、任意编号格式或通用 Word 编号能力。