losLab PDF Library di chuyển dữ liệu biểu mẫu vào và ra khỏi tệp PDF theo ba cách khác nhau: FDF và XFDF cho các giá trị trường AcroForm, cùng hai định dạng đó cho các bình luận chú thích, và toàn bộ một gói XFA XDP được ghi trực tiếp vào biểu mẫu. ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF và SetXFAFromString là các điểm truy cập, và mỗi phương thức trong số đó đều có phiên bản tệp và phiên bản chuỗi
Lý do có nhiều phương thức như vậy là vì dữ liệu biểu mẫu PDF không phải chỉ là một loại duy nhất. Một AcroForm đã điền đầy đủ chứa các giá trị trường, nó cũng có thể mang theo các bình luận đánh giá, và một biểu mẫu XFA cũ nhúng toàn bộ một mô tả ứng dụng XML vốn không liên quan gì đến cả hai loại trên. losLab PDF Library chủ ý giữ ba vấn đề này trên các API riêng biệt, bởi vì việc hợp nhất chúng sẽ buộc phải áp dụng mô hình dữ liệu sai cho ít nhất hai trong số chúng. Quyết định xem bạn cần nhóm phương thức nào là lựa chọn thiết kế đầu tiên, và điều này thường được giải quyết ngay khi bạn biết hệ thống tiếp nhận ở phía bên kia thực sự tiêu thụ dữ liệu gì
Sự khác biệt giữa dữ liệu biểu mẫu FDF, XFDF và XFA là gì?
FDF và XFDF truyền tải cùng một thông tin bằng hai cú pháp khác nhau, còn XFA là một thế giới riêng biệt. FDF là một tài liệu cú pháp PDF thu nhỏ (ISO 32000-2 §12.7.8): một mảng /Fields gồm các từ điển << /T (name) /V (value) >>, với các chuỗi được thoát ký tự (escape) chính xác theo cách các chuỗi ký tự được thoát bên trong tệp PDF. XFDF is là dạng XML của cùng dữ liệu đó (ISO 19444), một cây <fields> mà Acrobat và hầu hết các hệ thống phụ trợ biểu mẫu đọc và ghi một cách tự nhiên. XFA không thuộc cả hai loại trên: nó là một mẫu XML Forms Architecture cộng với dữ liệu của nó, được lưu trữ dưới dạng một XML Data Package (XDP) mà tệp PDF tham chiếu từ /AcroForm/XFA. Hãy chọn FDF hoặc XFDF khi bạn tương tác trên các giá trị trường, và chỉ tìm đến XFA khi bạn đang bảo trì một tài liệu vốn ban đầu được soạn thảo dưới dạng biểu mẫu XFA
Bên trong FDF và XFDF, losLab PDF Library vẽ ra một ranh giới thứ hai: giá trị trường so với bình luận chú thích. Nhóm dữ liệu biểu mẫu (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) đọc và ghi cây con /Fields và không chạm vào bất kỳ thứ gì khác. Nhóm chú thích (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) đọc và ghi cây con /Annots, đây là điều Acrobat ám chỉ qua việc Xuất Bình luận. Cả hai không bao giờ chồng chéo lên nhau, do đó việc xuất giá trị trường sẽ không quét theo các ghi chú đánh giá đi lạc, và việc nhập bình luận sẽ không làm ảnh hưởng đến các giá trị mà người dùng đã nhập. Việc một tiện ích (widget) làm gì khi nó được nhấp vào hoặc tính toán lại là một vấn đề thứ ba khác, được đề cập trong bài viết đi kèm về hành động biểu mẫu tương tác và JavaScript
Làm thế nào để điền dữ liệu vào biểu mẫu PDF từ FDF hoặc XFDF trong Delphi?
Tải tài liệu, gọi một phương thức nhập, và lưu lại. ImportFormDataFromXFDF và ImportFormDataFromFDF mỗi phương thức sẽ phân tích cú pháp dữ liệu biểu mẫu đầu vào, khớp từng mục với một trường AcroForm theo tên đầy đủ (fully qualified name) của nó, thiết lập giá trị, và trả về số lượng trường thực tế được cập nhật. Cả hai phương thức chỉ cập nhật các trường đã tồn tại sẵn trong tệp PDF đích; không phương thức nào tự tạo ra một trường cho một cái tên mà biểu mẫu không định nghĩa, điều này giúp ngăn chặn một tệp dữ liệu đi lạc hoặc độc hại âm thầm làm phình to biểu mẫu của bạn
var
Lib: TPDFlib;
FieldsSet: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('application-blank.pdf', '');
// XFDF produced by a case-management system, already UTF-8 on disk
FieldsSet := Lib.ImportFormDataFromXFDF('applicant-1042.xfdf');
if FieldsSet > 0 then
Lib.SaveToFile('application-filled.pdf');
finally
Lib.Free;
end;
end;
Hai chi tiết quyết định liệu dữ liệu phức tạp có tồn tại sau hành trình hay không. Chi tiết thứ nhất là thoát ký tự (escaping): FDF lưu trữ các giá trị dưới dạng các chuỗi ký tự PDF, do đó một giá trị chứa dấu ngoặc đơn, dấu gạch chéo ngược hoặc một byte không thể in được sẽ được bọc trong định dạng thoát ký tự bát phân được định nghĩa trong ISO 32000-2 §7.3.4.2, và losLab PDF Library đảo ngược quá trình thoát ký tự đó khi nhập để các dấu ngoặc đơn và dấu gạch chéo trở lại thành các ký tự thực tế mà người dùng đã nhập. Chi tiết thứ hai là mã hóa (encoding): các phương thức dựa trên tệp ghi và đọc XFDF và FDF dưới dạng UTF-8, đây là điều mà khai báo XFDF cam kết và là những gì bất kỳ giá trị trường phi ASCII nào (tên có dấu, ký hiệu tiền tệ, địa chỉ CJK) cần có để hoàn thành quy trình mà không bị lỗi. Nếu bạn tự xây dựng XFDF, hãy khai báo UTF-8 và ghi UTF-8, và quá trình nhập sẽ tương thích với bạn
Trường phân cấp, lựa chọn đa giá trị và văn bản định dạng
Tên trường phân cấp là nơi đầu tiên mà một bộ xuất dữ liệu sơ sài sẽ gặp lỗi. AcroForm xác định một trường lồng nhau bằng tiêu đề đầy đủ dạng dấu chấm như Applicant.FullName, nhưng XFDF không đặt chuỗi dấu chấm đó trong một thuộc tính tên duy nhất; ISO 19444 lồng nó lại, thành <field name="Applicant"><field name="FullName">. losLab PDF Library chia tách tiêu đề dạng dấu chấm thành các phần tử <field> lồng nhau khi xuất và lắp ráp lại các phần tử lồng nhau đó thành tiêu đề đầy đủ khi nhập, nhờ đó hai chiều xử lý luôn đối xứng. Khi xuất, nó cũng bỏ qua các trường cha không phải là điểm cuối (non-terminal), bởi vì một nút cha trong một AcroForm chỉ mang cấp độ đặt tên và tự nó không có giá trị; việc phát ra nó sẽ tạo ra một phần tử <value></value> trống không khớp với biểu mẫu thực tế. Hộp danh sách đa lựa chọn (multi-select list box) là cái bẫy thứ hai: một trường lựa chọn có thể giữ nhiều giá trị được chọn cùng một lúc, điều mà XFDF thể hiện dưới dạng các phần tử <value> lặp lại và FDF thể hiện dưới dạng mảng /V, và losLab PDF Library chỉ chia một trường thành nhiều giá trị khi nó thực sự là một lựa chọn đa chọn, nhờ đó một trường văn bản nhiều dòng thông thường vẫn giữ nguyên các ngắt dòng của nó thay vị bị chia cắt thành các giá trị giả mạo
Văn bản định dạng (rich text) là điểm thứ ba, và là điểm mà mọi người thường làm sai nhất. Một trường có định dạng sẽ lưu trữ đánh dấu của nó trong mục RV dưới dạng một cây con XHTML, và XFDF truyền tải nó trong <value-richtext>. losLab PDF Library ghi cây con đó dưới dạng một phân đoạn XML động thay vì thoát ký tự nó, nhờ đó một công cụ hạ nguồn sẽ đọc văn bản định dạng thực tế thay vì một chuỗi các thẻ hiển thị; khi nhập, nó bảo toàn cây con RV gốc và vẫn áp dụng <value> dạng thuần túy cho V. Khi một trường cung cấp cả hai, giá trị thuần túy sẽ thắng cho V và văn bản định dạng sẽ đi kèm trong RV, đây là quy tắc tương tác ngăn việc nhập văn bản định dạng âm thầm ghi đè lên một giá trị mà một công cụ khác đã thiết lập. Khi văn bản định dạng của bạn tồn tại để truyền tải cấu trúc tài liệu đến công nghệ hỗ trợ, hãy xử lý nó theo cách tương tự như cách bạn xử lý thứ tự đọc được thảo luận trong ghi chú về PDF được gắn thẻ và cấu trúc hỗ trợ tiếp cận
var
Lib: TPDFlib;
const
XFDF =
'<?xml version="1.0" encoding="UTF-8"?>' +
'<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">' +
'<fields>' +
' <field name="Applicant">' +
' <field name="FullName"><value>Alice Example</value></field>' +
' </field>' +
' <field name="Skills">' +
' <value>Delphi</value><value>PDF</value>' +
' </field>' +
' <field name="Notes">' +
' <value>See attachment</value>' +
' <value-richtext><body><p>See <b>attachment</b></p></body></value-richtext>' +
' </field>' +
'</fields></xfdf>';
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('intake.pdf', '');
// Applicant.FullName reassembles; Skills fills the /V + /I arrays;
// Notes gets V from <value> and RV from <value-richtext>
Lib.ImportFormDataFromXFDFString(XFDF);
Lib.SaveToFile('intake-filled.pdf');
finally
Lib.Free;
end;
end;
Làm thế nào để truyền nhận hai chiều bình luận chú thích dưới dạng FDF hoặc XFDF?
Các bình luận di chuyển trên nhóm chú thích, và tập hợp con được hỗ trợ được chủ ý giới hạn ở mức nhỏ. ExportAnnotationsToXFDF và ImportAnnotationsFromXFDF, cùng với các bản đối chiếu FDF của chúng, mang theo các đánh dấu kiểu văn bản cùng với các trường thực sự truyền nhận sạch sẽ: loại phụ (subtype) chú thích, hình chữ nhật của nó, chỉ mục trang bắt đầu từ 0, tác giả trong T, chủ đề trong Subj, phần Contents dạng thuần túy, và màu sắc, công cụ ánh xạ bộ ba DeviceRGB /C của PDF sang và từ thuộc tính #RRGGBB của XFDF. Việc nhập chỉ chấp nhận các tên phần tử đã biết và bỏ qua bất kỳ mục nào có trang nằm ngoài phạm vi hoặc thiếu hình chữ nhật, nhờ đó một XFDF được chỉnh sửa thủ công hoặc từ nguồn bên ngoài không thể thả một chú thích bị lỗi định dạng vào tài liệu. Những gì tập hợp con này chưa mang theo là điều đáng được nêu rõ: nội dung văn bản định dạng (RC), cửa sổ bật lên (popup), quadpoints, ink lists, các đỉnh (vertex) và luồng xuất hiện được nhúng sẵn (baked appearance stream) hiện nằm ngoài phạm vi hỗ trợ, vì vậy hình học nổi bật và giao diện con dấu tùy chỉnh sẽ không tồn tại qua con đường này. Để xác nhận những gì thực sự đã được tải, hãy duyệt qua các chú thích trang hoặc cây phần tử rộng hơn được đề cập trong tìm kiếm văn bản và liệt kê phần tử trang
var
Src, Dest: TPDFlib;
Xfdf: WideString;
begin
Src := TPDFlib.Create;
Dest := TPDFlib.Create;
try
Src.LoadFromFile('reviewed.pdf', '');
Xfdf := Src.ExportAnnotationsToXFDFString; // <annots> subset only
Dest.LoadFromFile('clean-copy.pdf', ''); // pages must line up by index
Dest.ImportAnnotationsFromXFDFString(Xfdf);
Dest.SaveToFile('clean-copy-commented.pdf');
finally
Dest.Free;
Src.Free;
end;
end;
Ghi một gói XFA XDP đầy đủ bằng SetXFAFromString
XFA là trường hợp đặc biệt, và SetXFAFromString là cách bạn ghi toàn bộ gói dữ liệu cùng một lúc. Phương thức này nhận một XML Data Package hoàn chỉnh, tài liệu <xdp:xdp> với các gói mẫu (template) và tập dữ liệu (datasets) của nó, và lưu trữ nó dưới dạng luồng dữ liệu được tham chiếu từ /AcroForm/XFA. losLab PDF Library tạo bộ chứa AcroForm theo yêu cầu khi tài liệu chưa có sẵn, vì vậy bạn không cần phải thêm một trường bỏ đi chỉ để có chỗ treo XFA, và nó hủy bỏ bất kỳ trạng thái XFA đã phân tích nào mà nó đang giữ để lần đọc sau phản ánh đúng gói dữ liệu bạn vừa ghi chứ không phải bộ nhớ đệm cũ kỹ. Do một gói XFA là XML và không nhất thiết là UTF-8, thư viện sẽ phát hiện dấu thứ tự byte (BOM) UTF-16 và giải mã gói dữ liệu một cách chính xác trước khi phân tích cú pháp, điều này rất quan trọng đối với các gói dữ liệu được tạo ra bởi các công cụ mặc định dùng UTF-16
Sau khi gói dữ liệu đã sẵn sàng, GetXFAFormFieldValue và SetXFAFormFieldValue sẽ xác định các trường riêng lẻ thông qua đường dẫn Scripting Object Model của chúng. losLab PDF Library chấp nhận các gốc SOM tiêu chuẩn cũng như các đường dẫn tương đối trần, do đó form1.FullName, $data.form1.FullName and xfa.datasets.data.form1.FullName đều trỏ đến cùng một nút dữ liệu, và phía mẫu chấp nhận $template cũng như xfa.template theo cách tương tự. Sự dung sai đó rất quan trọng khi các đường dẫn SOM được tạo ra bởi một hệ thống khác luôn phát ra dạng biểu mẫu đầy đủ
var
Lib: TPDFlib;
const
Xdp =
'<?xml version="1.0" encoding="UTF-8"?>' +
'<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">' +
' <template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">' +
' <subform name="form1">' +
' <field name="FullName"><ui><textEdit/></ui></field>' +
' </subform>' +
' </template>' +
' <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">' +
' <xfa:data><form1><FullName>Alice Example</FullName></form1></xfa:data>' +
' </xfa:datasets>' +
'</xdp:xdp>';
begin
Lib := TPDFlib.Create;
try
Lib.SetXFAFromString(Xdp, 0); // creates the AcroForm container if none exists
// read back through the data DOM with an SOM path
if Lib.GetXFAFormFieldValue('form1.FullName') = 'Alice Example' then
Lib.SetXFAFormFieldValue('form1.FullName', 'Bob Example');
Lib.SaveToFile('xfa-packet.pdf');
finally
Lib.Free;
end;
end;
Tóm tắt trung thực là các giá trị trường truyền nhận đầy đủ qua FDF và XFDF, bao gồm cả phân cấp, đa lựa chọn và văn bản định dạng; các bình luận chú thích truyền nhận dưới dạng một tập hợp con đánh dấu văn bản được xác định với các khoảng trống rõ ràng; và XFA được ghi và đọc dưới dạng toàn bộ gói dữ liệu với quyền truy cập SOM trên từng trường ở phía trên. Hãy khớp định dạng với đối tượng tiêu thụ, khai báo UTF-8 cho bất kỳ thứ gì bạn xây dựng thủ công, và lưu ý rằng các phương thức nhập chỉ tác động lên các trường và chú thích vốn đã phù hợp với tài liệu. Các phương thức dữ liệu biểu mẫu, chú thích và XFA được mô tả ở đây là một phần của losLab PDF Library dành cho Delphi và C++Builder, tài liệu tham khảo của nó mang danh sách tham số đầy đủ cho mỗi điểm truy cập xuất và nhập