Pro 版本
Form — 深度参考
本页是 Pro Form 模块的深度参考。它涵盖 AcroForm 值提取、XFDF 读写、数据绑定与 XFA 数据提取。该模块消费由 Core 表单读取器产生的 NextPDF\Form\FormField 值,并在其之上添加序列化、解析与绑定。XFA 支持是面向数据的:解析器会结构化 template 与 datasets 数据包。它不会执行 XFA 计算脚本,也不会渲染动态 XFA 布局。
可用性与授权
标题为“可用性与授权”的章节此能力随 NextPDF Pro(nextpdf/pro)提供,并通过 Pro 层级的许可证信封激活。没有该授权的部署不会加载此能力的类。比较版本并获取授权。
不存在逐功能的许可证标记。这是一项 Pro 版本能力。
公共 API 接口面
标题为“公共 API 接口面”的章节| 符号 | 参数 | 默认行为 | 返回 | 抛出或失败于 | 备注 |
|---|---|---|---|---|---|
FormDataExtractor::extract | list<FormField> $fields | 读取每个字段的名称与值 | XfdfData | — | 包含值为空的字段。 |
FormDataExtractor::toArray | list<FormField> $fields | 构建 name → value 的字符串映射 | array<string, string> | — | 后出现的重名会覆盖先前的。 |
FormDataExtractor::toXfdf | list<FormField> $fields, ?string $pdfHref = null | 委托给 XfdfWriter::fromFields | string(XFDF XML) | — | 一次调用即可导出的便捷路径。 |
FormDataExtractor::extractNonEmpty | list<FormField> $fields | 跳过值为空字符串的字段 | XfdfData | — | — |
FormDataExtractor::getEmptyFieldNames | list<FormField> $fields | 列出未设置值的字段名称 | list<string> | — | extractNonEmpty 的补集。 |
XfdfWriter::fromFields | list<FormField> $fields, ?string $pdfHref = null | 收集 name → value 对,委托给 fromArray | string(XFDF XML) | — | — |
XfdfWriter::fromArray | array<string, string> $data, ?string $pdfHref = null | 将映射包装进 XfdfData 后委托 | string(XFDF XML) | — | — |
XfdfWriter::fromXfdfData | XfdfData $data, ?string $pdfHref = null | 序列化为 XFDF;点分表示法的名称会嵌套为分层的 <field> 元素 | string(XFDF XML) | — | 会剥除 XML 1.0 非法的控制字符;参见行为契约。 |
XfdfParser::parse | string $xfdfXml | 以 XXE-safe 方式加载 XML,并将字段扁平化为点分表示法 | XfdfData | InvalidArgumentException | 10 MiB 输入上限;接受带命名空间与不带命名空间的根元素。 |
XfdfParser::parseFile | string $filePath | 解析路径、读取文件,委托给 parse | XfdfData | InvalidArgumentException | 路径缺失、非文件或不可读时抛出。 |
XfaParser::parse | string $pdfData | 标记检查、XML 提取、数据包解析 | XfaFormData | InvalidArgumentException, XfaParseException | 没有 /XFA 标记时返回空结果,而非错误。 |
XfaParser::hasXfa | string $pdfData | 在字节中扫描 /XFA 标记 | bool | — | 字节标记扫描;该标记的任何一次出现都会匹配。 |
XfaParser::extractXfaXml | string $pdfData | 扫描流以查找 XFA 标记,然后直接搜索 <xdp:xdp> | string(XFA XML 或 '') | RuntimeException(已声明) | 最多扫描输入的前 50 MiB。 |
XfaParser::parseXml | string $xml | 提取 template 与 datasets 数据包,解析 <field> 元素 | XfaFormData | XfaParseException | 10 MiB XML 上限,在 DOM 加载前强制执行。 |
FormDataBinder::bind | list<FormField> $fields, XfdfData $data | 创建带有绑定值的新 FormField 实例 | FormDataBindResult | — | 原始实例永不被修改;复选框归一化为 Yes/Off。 |
FormDataBinder::fromXfdf | list<FormField> $fields, string $xfdfXml | 先解析 XFDF,然后绑定 | FormDataBindResult | InvalidArgumentException | 失败模式与 XfdfParser::parse 相同。 |
FormDataBinder::fromArray | list<FormField> $fields, array<string, string> $data | 将映射包装进 XfdfData,然后绑定 | FormDataBindResult | — | — |
FormDataBindResult | isFullyBound, hasNoUnmatchedKeys, boundCount, fieldCount;只读 fields, boundFieldNames, unmatchedDataKeys, unboundFieldNames | 不可变的绑定诊断信息 | 视方法而定 | — | isFullyBound 要求未匹配键为零且未绑定字段为零。 |
XfdfData | hasField, getValue, count, isEmpty, getFieldNames, withField, withoutField, merge;只读 fields | 不可变的 name → value 容器 | 视方法而定 | — | with* 与 merge 返回新实例;merge 优先采用参数的值。 |
XfaFormData | getField, hasField, count, fieldNames;只读 fields, templateXml, datasetsXml | 不可变的 XFA 解析结果 | 视方法而定 | — | 携带原始的 template 与 datasets 数据包 XML 以便往返。 |
XfaFormField | 只读 name, type, value, required, caption, options | 不可变的单字段记录 | — | — | type 为 text、numeric、date、choice、button、signature 之一。 |
XfaPacket | 枚举成员 Template, Datasets, Config, LocaleSet, ConnectionSet, Form;xmlNamespace() | 字符串支持的数据包枚举 | xmlNamespace() 返回 string | — | 命名空间 URI 遵循 XFA Specification 3.3。 |
public static function extract(array $fields): XfdfDatapublic static function toArray(array $fields): arraypublic static function toXfdf(array $fields, ?string $pdfHref = null): stringpublic static function extractNonEmpty(array $fields): XfdfDatapublic static function getEmptyFieldNames(array $fields): arraypublic static function fromFields(array $fields, ?string $pdfHref = null): stringpublic static function fromArray(array $data, ?string $pdfHref = null): stringpublic static function fromXfdfData(XfdfData $data, ?string $pdfHref = null): stringpublic static function parse(string $xfdfXml): XfdfDatapublic static function parseFile(string $filePath): XfdfDatapublic function parse(string $pdfData): XfaFormDatapublic function hasXfa(string $pdfData): boolpublic function extractXfaXml(string $pdfData): stringpublic function parseXml(string $xml): XfaFormDatapublic static function bind(array $fields, XfdfData $data): FormDataBindResultpublic static function fromXfdf(array $fields, string $xfdfXml): FormDataBindResultpublic static function fromArray(array $fields, array $data): FormDataBindResultNextPDF\Pro\Form\Exception\XfaParseException继承RuntimeException——XFA 载荷无法被解析为XfaFormData。这种子类化是刻意为之:现有的catch (RuntimeException $e)调用点仍可正常工作。- SPL
InvalidArgumentException——传给XfdfParser的输入为空、超限、格式错误或非 XFDF;传给XfaParser::parse的 PDF 输入为空;XfdfParser::parseFile中路径不可读。
行为契约
标题为“行为契约”的章节AcroForm 提取。 FormDataExtractor 会遍历你传入的字段列表,并读取每个字段的名称与值。extract 返回一个 XfdfData;toArray 返回一个纯粹的 name → value 字符串映射。extractNonEmpty 会丢弃值为空字符串的字段;getEmptyFieldNames 返回互补的名称列表。提取过程永不修改输入字段。
XFDF 写入。 XfdfWriter 会生成符合 ISO 19444-1:2019 结构的文档。输出以 XFDF XML 声明开头,随后是位于 Adobe XFDF 命名空间(http://ns.adobe.com/xfdf/)中、带 xml:space="preserve" 的 xfdf 根元素。非空的 pdfHref 会发出一个指回源 PDF 的 <f href="..."/> 引用。点分表示法的字段名(例如 address.city)会嵌套为分层的 <field> 元素树。值与属性会转义五个 XML 元字符。字段名、值以及 pdfHref 还会额外进行良构性归一化:XML 1.0 禁止的 C0 控制字符会被剥除,而 TAB、LF 与 CR 会被保留。这种归一化在设计上是有损的,因此无论调用方提供何种字节,写入器始终产出良构、可重新解析的 XFDF。
XFDF 读取。 XfdfParser 同时接受带命名空间与不带命名空间的 xfdf 根元素,并以大小写不敏感的方式匹配根元素名称,因为某些生产者会发出大写的根元素。分层的 <field> 树会扁平化回点分表示法的名称,因此写入与读取可以往返。所有 XML 加载都会禁用网络访问与外部实体解析。parseFile 在同一解析之前额外增加路径解析与可读性检查。
数据绑定。 FormDataBinder::bind 会将数据键与字段名进行匹配。由于 FormField 是不可变的,绑定会创建带有更新值的新实例;原始实例永不被修改。结果会报告三组诊断信息:已绑定的字段名、没有匹配字段的数据键,以及未收到数据的字段。复选框的值会归一化为 ISO 32000-2:2020, 12.7.5.2.3 的开/关状态模型:大小写不敏感的 yes、true、1 与 on 映射为 Yes;其他任何值都映射为 Off。
XFA 数据提取。 XfaParser::parse 接受原始 PDF 字节。它首先扫描 /XFA 标记;缺少该标记时返回一个空的 XfaFormData。随后提取会尝试两种策略:扫描 stream…endstream 块以查找 XFA XML 指示符,然后直接搜索 <xdp:xdp> 文档。单个 xdp:xdp 片段会原样返回;多个片段会被拼接进一个合成的 xdp:xdp 信封。parseXml 会提取 template 与 datasets 数据包,并将每个 template <field> 元素解析为一个 XfaFormField:name 属性是必需的,type 派生自字段的 UI 子元素,required 标志派生自 nullTest 设为 error 的 validate 元素,choice 选项来自 items 子元素。
XFA 支持是面向数据的。解析器会结构化 template 与 datasets 数据包。它不会执行 XFA 计算脚本、不会渲染动态 XFA 布局,也不会往返每种数据包类型。在依赖它之前,请针对你的特定文档集校验该解析器。
边界情形与失败模式
标题为“边界情形与失败模式”的章节XfdfParser::parse('')会抛出InvalidArgumentException。超过 10 MiB 的输入会抛出InvalidArgumentException并指明该上限。- 格式错误的 XML 会抛出携带所收集 libxml 消息的
InvalidArgumentException。根元素不是xfdf的良构文档会抛出并指明实际的根元素。 - 不含
<fields>元素的 XFDF 文档会解析为一个空的XfdfData;这不是错误。 - 没有
name属性的字段元素在 XFDF 与 XFA 解析中都会被跳过。不含<value>子元素的 XFDF 字段不会贡献任何条目。 XfaParser::parse('')会抛出InvalidArgumentException。没有/XFA标记的 PDF,或其 XFA XML 无法定位的 PDF,会返回一个空的XfaFormData而不是抛出。hasXfa是一次字节标记扫描:文件中任何/XFA标记都会匹配,包括位于未使用对象中的标记。后续的提取步骤才会决定是否存在可用的 XML。- XFA 提取最多检查 PDF 字节串的前 50 MiB;超出该界限的内容不会被扫描。
- 超过 10 MiB 的 XFA XML 会在任何 DOM 树被物化之前抛出
XfaParseException。格式错误的 XFA XML 会抛出带 libxml 消息的XfaParseException。 - 复选框归一化永不放行无法识别的值;任何不在被接受的开态形式之列的值都会映射为
Off。 - 写入器的控制字符剥除是有损的:名称、值或
pdfHref中 XML 1.0 非法的 C0 字节会被丢弃,从而使输出保持良构。TAB、LF 与 CR 会被保留。 - 所有 XML 解析都会禁用外部实体解析与网络访问(XXE-safe)。
- 本模块不执行任何密码学操作;FIPS 模式不会改变其行为。
一致性
标题为“一致性”的章节| 行为 | 参考 | 状态 |
|---|---|---|
| 交互式表单/字段字典模型 | ISO 32000-2:2020, 12.7 | 一致(基于产品) |
复选框开/关状态归一化(Yes/Off) | ISO 32000-2:2020, 12.7.5.2.3 | 一致;该条款已在本页的引用记录中标注 |
| XFDF 数据交换结构 | ISO 19444-1:2019 | 一致(基于产品) |
| XFA 数据包名称与命名空间 URI | XFA Specification 3.3 | 一致(基于产品) |
撰写时可用的 RAG 语料库不包含 ISO 19444-1:2019、XFA Specification 或 W3C XML 1.0,因此那些一致性陈述是基于源码注解与测试的产品依据,而非条款引用。这些陈述描述的是针对所引用文档的能力。NextPDF 不持有任何一致性认证,对某条款的支持并非认证声明。
开发说明
标题为“开发说明”的章节- 除
XfaParser外,每个入口点都是静态的。XfaParser可实例化且无状态;单个实例可以安全地跨文档重用。 - 预期的往返流程是:Core 表单读取器产生
FormField值;FormDataExtractor或XfdfWriter将其序列化;XfdfParser将数据读回;FormDataBinder将其应用到字段列表。分层名称通过点分表示法在往返中得以保留。 - 使用
FormDataBindResult诊断信息(isFullyBound、unmatchedDataKeys、unboundFieldNames)在接受填充之前,检测 XFDF 数据文件与修订后的 PDF 模板之间的偏差。 XfdfData是一个值对象:withField、withoutField与merge会返回新实例。发生键冲突时,merge优先采用参数的值。XfaFormData保留原始的 template 与 datasets 数据包 XML(templateXml、datasetsXml),以便你对字段模型未涵盖的数据包进行后处理。- 本模块本身不会从 PDF 字节中解析 AcroForm 字典;它消费由 Core 表单读取器产生的字段。只有
XfaParser作用于原始 PDF 内容。
发布边界
标题为“发布边界”的章节本页仅记录外部可观察的行为与受支持的公共 API 接口面。内部命名空间路径、辅助类、机制表、运行手册文件名与工单前缀不在范围之内。