Pro 版本
Form — 深入參考
本頁是 Pro Form 模組的深入參考,涵蓋 AcroForm 值擷取、XFDF 讀寫、資料綁定與 XFA 資料擷取。此模組會取用 Core form reader 產出的 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; readonly fields, boundFieldNames, unmatchedDataKeys, unboundFieldNames | 不可變的綁定診斷資訊 | 視方法而定 | — | isFullyBound 要求零個未匹配鍵與零個未綁定欄位。 |
XfdfData | hasField, getValue, count, isEmpty, getFieldNames, withField, withoutField, merge; readonly fields | 不可變的 name → value 容器 | 視方法而定 | — | with* 與 merge 會回傳新實例;merge 偏好採用引數的值。 |
XfaFormData | getField, hasField, count, fieldNames; readonly fields, templateXml, datasetsXml | 不可變的 XFA 剖析結果 | 視方法而定 | — | 攜帶原始的 template 與 datasets 封包 XML,供往返使用。 |
XfaFormField | readonly 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/)的 xfdf 根元素開頭,並帶有 xml:space="preserve"。非 null 的 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 元素,選項則來自 items 子元素。
XFA 支援以資料為導向。剖析器會將 template 與 datasets 封包結構化。它不會執行 XFA 計算指令稿、不會算繪動態 XFA 版面,也不會往返每一種封包類型。在倚賴它之前,請先以你自己的特定文件集驗證該剖析器。
邊界案例與失敗模式
標題為「邊界案例與失敗模式」的區段XfdfParser::parse('')會擲出InvalidArgumentException。超過 10 MiB 的輸入會擲出InvalidArgumentException並指明該上限。- 格式錯誤的 XML 會擲出
InvalidArgumentException,並攜帶所收集的 libxml 訊息。根元素非xfdf的格式良好文件會擲出例外,並指明實際的根元素。 - 不含
<fields>元素的 XFDF 文件會剖析成一個空的XfdfData;這並非錯誤。 - 不含
name屬性的欄位元素在 XFDF 與 XFA 剖析中都會被略過。不含<value>子元素的 XFDF 欄位不會產生任何項目。 XfaParser::parse('')會擲出InvalidArgumentException。不含/XFA標記的 PDF,或其 XFA XML 無法定位者,會回傳一個空的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 模式不會改變其行為。
一致性
標題為「一致性」的區段| 行為 | 參考 | 狀態 |
|---|---|---|
| 互動式表單/欄位 dictionary 模型 | 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,因此那些對齊陳述是以來源註記與測試為據(product-grounded),而非條款引用。這些陳述描述的是相對於所引用文件的能力。NextPDF 未持有任何一致性認證,對某條款的支援並非認證聲明。
開發備註
標題為「開發備註」的區段- 除了
XfaParser之外,每個進入點都是靜態的。XfaParser可被實例化且無狀態;單一實例可安全地跨文件重複使用。 - 預期的往返流程是:Core form reader 產出
FormField值;FormDataExtractor或XfdfWriter將其序列化;XfdfParser再將資料讀回;FormDataBinder將其套用到欄位清單上。階層式名稱會透過點記法在往返中保留下來。 - 在接受填入之前,可運用
FormDataBindResult的診斷資訊(isFullyBound、unmatchedDataKeys、unboundFieldNames)來偵測 XFDF 資料檔與修訂後 PDF template 之間的落差。 XfdfData是一個值物件:withField、withoutField與merge都會回傳新實例。發生鍵衝突時,merge偏好採用引數的值。XfaFormData會保留原始的 template 與 datasets 封包 XML(templateXml、datasetsXml),讓你能後處理欄位模型未涵蓋的封包。- 此模組本身並不會從 PDF 位元組剖析出 AcroForm dictionary;它取用的是 Core form reader 產出的欄位。只有
XfaParser會直接處理原始 PDF 內容。
出版邊界
標題為「出版邊界」的區段本頁僅記載對外可觀察的行為與受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表格、runbook 檔名與工單前綴皆不在範圍內。