跳到正文

ADR-0033:语义跨行合并与标准 vMerge ​

背景 ​

列合并已保留真实内容锚点和物理列,但本行跨度和不能表达前行覆盖、全覆盖空行及纵向连通组。直接给单元格加一个数值会破坏来源、分页和 DOCX 归一化,不能把组件网格等同于语义表格。

决策 ​

TableCell 新增正整数 rowSpan,默认 1,保留旧构造器。TableRow 允许空锚点并提供 covered;只有完整 Table 验证全部物理槽被前行覆盖时才合法。本行 columnCount/cellAtColumn 只解释局部锚点,二维位置使用 Table.grid 的不可变 TableGrid。解析只保存 O(列数) 活动覆盖与 O(锚点数) 结果,不创建二维槽矩阵。新锚点按声明顺序放入下一个空槽,完整矩形不得越界、相交、留洞或跨表头边界。

布局入口先验证结构预算,再准备一次网格与每格文字。按真实锚点只计一次原文和图片,结构预算仍计覆盖槽。固定/比例列合并,内边距只扣一次;合并覆盖 Auto 明确拒绝。单行约束先决定基础行高;无单行锚点的行基础为 0。纵向约束按跨度、原始行、物理列排序,将正的剩余高度等分到覆盖行,最后一行补舍入差。真实格 bounds 使用覆盖行高之和。

任一纵向跨度跨越的行边界组成传递连通组。首批整体移页/移区,完整表头逐次重复,超高组立即失败;rowSpan 与 allowRowSplit 组合明确拒绝。完全覆盖行不产生虚假 IR 格或文字,其高度仍计入表格和真实合并矩形;所有实际格仍挂在原始锚点行。字段、链接、图片及诊断复用最终解析链路。

Java 静态绑定及 XML 静态 row-span 保留跨度。动态单行原型首批拒绝纵向跨度,避免循环实例隐式跨越相邻数据行。单向 StreamingTable 继续拒绝任意合并。

DOCX 输出标准 vMerge restart 及精确匹配 gridSpan 的空 continuation tc,序列化覆盖格不进入模型。导入按物理区间归一成一个真实锚点,严格检查孤立续接、区间宽度变化、重复属性、非法位置/值、覆盖和表头边界;两种损失策略都拒绝畸形几何与非空 continuation。单独 restart 可规范化为 rowSpan=1。未知样式、旧 hMerge 和递归格内容沿用原损失边界。

影响与验证 ​

record 组件数从 6 变为 7,解构/反射形状变化;旧构造器并不代表完全二进制兼容。空 TableRow 的合法性转移到完整 Table 上下文验证。本行位置查询不能解析前行覆盖,调用方应迁移至 TableGrid。

验收覆盖混合矩形、全覆盖行、incoming 中间空槽、行高约束顺序、传递连通组、短区纯跳过、超高与拆行拒绝、预算/取消、字段及图文链接唯一性。标准 OOXML 需要独立包检查及无私有元数据导入;Word 读取、字段更新、保存回读和 PDF 导出分别报告,环境阻塞不能转述为通过。全部新 PDF 页双渲染并逐页查看,新隔离调用方和历史验收保持。

跨页拆分纵向合并组、递归格内容、单向源合并和任意 Word 无损互转仍独立,不由本决策推定完成。不新增依赖。