动态 XFA 实例呈现

单元:HPDFXFAPresentation

TXFAInstancePresentation 持有一个独立的 TXFAWidgetRuntime,为带单个 datasets 记录的 XDP 包文档添加有界的实例呈现 profile

用 SetPresence('row[1]', 'hidden') 把某个出现从流中移除,用 invisible 保留其空间但隐藏其控件,用 visible 恢复;索引是数据出现中的从零位置,包括隐藏的出现

布局解析器对每个出现单独测量,压缩存活的垂直偏移,并在放置后续内容前预留完整的重复范围;固定高度、内容推导高度与表格行都参与重排

稳定身份与持久化

控件 ID 组合不透明的模板与 datasets 身份,在前面行被隐藏或移除、保存后重载以及存活字段保持焦点或挂起编辑时保持稳定

辅助器把带命名空间限定的身份属性与实例覆盖存储在表单包内的外部命名空间扩展中,使用 urn:hotpdf:xfa:instance-presentation:1;新加的行获得全新身份与模板默认值,被移除的行无法把挂起编辑转移给替换行

SaveToBytes 返回完整 XDP,包括更新后的 datasets、身份与呈现状态;用 THotPDF.SetXFADocument 把它持久化进 PDF,写动态表单时设置 XFANeedsRendering := True

PDF 重载后,用 THotPDF.CreateLoadedXFAWidgetRuntime.SaveToBytes 获取完整 XDP,再从那些字节构造 TXFAInstancePresentation 以恢复本 profile

该命名空间扩展由本辅助器解释;原生 HPDFXFAFlatten、默认已加载运行时工厂与外部 XFA 阅读器不会自动应用其逐实例覆盖,因此持久化存储本 profile 不代表在其他阅读器中呈现一致

显式绑定与实例操作

重复 subform 可以用 <bind match="dataRef" ref="$record.lines.entry[*]"/> 绑定到不同名称的 dataset 组;绝对 $record 与 $data 根以及相对路径支持未索引的父组与最终的重复组

每个出现内的字段使用原生绑定值解析器,包括 ref="label" 这样的显式相对字段绑定

AddInstance 与 RemoveInstance 更新选定的数据组,强制 occur 最小与最大值,应用创建限制,并在发布前重排;新行从模板获得字段值,而不是复制前一行的输入值

选择器使用唯一的模板名加可选的出现索引,如 row[1];重复模板名、缺失组、无效索引以及在歧义重复父级之下的变更都会拒绝事务

SetAccess 支持 open、readOnly、protected 与 nonInteractive;实例限制由后代继承,并通过持有的运行时阻止编辑

条件事件

DispatchConditionalEvent 定位带 JavaScript 内容类型的匹配字段事件并直接解析有界 profile;Execute 对既有控件 ID 运行显式脚本

if(this.rawValue=="hide"){
  row[1].presence="hidden";
}else{
  row[1].presence="visible";
}
row.instanceManager.addInstance();
row.instanceManager.removeInstance(0);

条件接受 this.rawValue 与未转义带引号字面值之间的相等或不相等;嵌套花括号 if 与可选 else 块受 MaxDepth 限制

赋值支持 presence 与 access;所有分支都做语法检查,包括不会执行的分支,不受支持的操作拒绝整批

this.rawValue 读取已提交的控件值;在派发需要观察挂起编辑的事件之前,先通过 Runtime.CommitEdit 提交它们

原始 Runtime.DispatchEvent 保留其受限的字面值操作行为并拒绝条件与索引实例语法;本辅助器不提供通用 JavaScript 或 FormCalc 解释器、浏览器 API、网络访问或自动 XFA 生命周期派发

事务与预算

变更通过 TXFAWidgetRuntime.UpdateDocument 执行,连同原生计算与有界的稳定重排;失败时恢复序列化 XDP、焦点、挂起编辑、验证状态、计算与重排计数器以及警告计数

焦点、layout 与控件失效 callback 只在成功后发布;回滚解析会抑制耗尽的辅助器工作与取消检查,同时保留原生 layout 与控件边界,使取消无法阻止恢复

用 Default 初始化 TXFAPresentationOptions;默认值为 200,000 次操作、4,096 个呈现状态、每组 10,000 个创建实例、32 MiB 输入与文档包络、65,536 字节脚本、32 层条件嵌套与 5,000 毫秒

MaxInputBytes 还在每轮 layout 与发布之前约束一个保守的转义 XML 包络,包括身份属性、命名空间声明、文本与 datasets 变更;有效 XML 可能在其序列化字节数达到同一值之前先触及这个保守限制

Cancelled 是可选的对象方法 callback,在有界工作期间检查;内嵌 Runtime 选项继续约束控件、值、计算、layout、重排与原生脚本工作

宿主绘制与无障碍

Accessibility 返回可见控件记录,含稳定 ID、role、caption 或字段名、tooltip 描述、已提交值、页面与边界、焦点、有效性、只读与必填状态以及 choice 标签;密码值被省略

PaintPage 把可见控件快照与对应的无障碍记录交付给 TXFAHostWidgetPainter;自定义宿主可以实现自己的控件或 Render surface

TXFACanvasWidgetPainter 为控件边框、文本、密码掩码、checkbox 与 radio 标记、choice 指示器、按钮与焦点提供真实的 VCL 与 LCL canvas 绘制,支持正缩放与可选偏移;它裁剪每个控件并恢复 canvas 样式

canvas 适配器只绘制控件,不绘制完整的静态 XFA 图形树;宿主自行提供页面背景、静态图形、事件路由、选择呈现以及面向其平台的无障碍桥

运行时与辅助器是单线程对象;callback 必须遵循宿主的线程所有权,并避免在活跃事务期间递归变更

C++Builder 调用方必须提供全部 canvas painter 构造参数,如 new TXFACanvasWidgetPainter(canvas, 1, 0, 0);生成的头文件不保留这些浮点默认参数

验证

验收覆盖每个架构 106 个 Delphi 用例、两个 Windows 架构上的全新 FPC 编译、Win32 与 Win64x 上的 C++Builder 公共头编译,以及真实 PDF/XDP 输出的独立验证

Tests/Fixtures/XFAInstancePresentation/explicit-invoice.xdp 包含独立数据名、三条重复发票行、一个条件事件、无障碍元数据与后续页脚

Run-XFAInstancePresentationTests.ps1 运行辅助器检查与既有的 XFA 事件、运行时、脚本、SOM、DOM 与解析回归 fixture,无 GUI 与外部 PDF 阅读器

独立的 verify_saved_invoice.py 用 pypdf 读取生成的 PDF,检查真实 XDP 数据行、唯一持久身份、隐藏出现状态、初始化默认值与重载身份

powershell -File Tests/Delphi/Run-XFAInstancePresentationTests.ps1 -Platform Win32 -CheckCppHeaders
powershell -File Tests/Delphi/Run-XFAInstancePresentationTests.ps1 -Platform Win64 -CheckCppHeaders
python Tests/Fixtures/XFAInstancePresentation/verify_saved_invoice.py

兼容的基础运行时与原生编辑契约见 交互式 XFA 控件运行时