Artikel Teknis

Pertukaran Data Formulir FDF, XFDF, dan XFA di Delphi

losLab PDF Library memindahkan data formulir masuk dan keluar dari PDF dengan tiga cara berbeda: FDF dan XFDF untuk nilai field AcroForm, kedua format yang sama untuk komentar anotasi, dan seluruh paket XDP XFA yang ditulis langsung ke dalam formulir. ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, dan SetXFAFromString adalah titik masuknya, dan masing-masing memiliki varian file dan varian string

Alasan mengapa ada begitu banyak metode adalah karena data formulir PDF bukanlah satu hal yang tunggal. AcroForm yang terisi memiliki nilai field, ia juga dapat membawa komentar tinjauan, dan formulir XFA warisan menyematkan seluruh deskripsi aplikasi XML yang tidak ada hubungannya dengan keduanya. losLab PDF Library sengaja memisahkan ketiga masalah tersebut pada API yang berbeda, karena menggabungkannya akan memaksakan model data yang salah pada setidaknya dua di antaranya. Memutuskan kelompok mana yang Anda butuhkan adalah pilihan desain pertama, dan biasanya diselesaikan saat Anda mengetahui apa yang sebenarnya dikonsumsi oleh sistem penerima di sisi lain

Apa perbedaan antara data formulir FDF, XFDF, dan XFA?

FDF dan XFDF membawa informasi yang sama dalam dua sintaks berbeda, dan XFA adalah dunia yang terpisah. FDF adalah dokumen sintaks PDF miniatur (ISO 32000-2 §12.7.8): sebuah array /Fields dari kamus-kamus << /T (name) /V (value) >>, dengan string yang di-escape persis seperti cara literal string di-escape di dalam PDF. XFDF is the XML form of the same data (ISO 19444), a tree that Acrobat and most form back ends read and write natively. XFA bukan keduanya: ini adalah templat XML Forms Architecture ditambah datanya, disimpan sebagai XML Data Package (XDP) yang direferensikan oleh PDF dari /AcroForm/XFA. Pilih FDF atau XFDF saat Anda beroperasi pada nilai field, dan gunakan XFA hanya saat Anda memelihara dokumen yang awalnya ditulis sebagai formulir XFA

Di dalam FDF dan XFDF, losLab PDF Library menarik garis kedua: nilai field versus komentar anotasi. Kelompok data formulir (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) membaca dan menulis subtree /Fields dan tidak menyentuh hal lain. Sebaliknya, kelompok anotasi (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) membaca dan menulis subtree /Annots, yang dimaksud Acrobat dengan Ekspor Komentar. Keduanya tidak pernah tumpang tindih, sehingga mengekspor nilai field tidak akan menyapu catatan tinjauan yang tersesat, dan mengimpor komentar tidak akan mengganggu nilai yang telah diketik oleh pengguna. Apa yang dilakukan oleh widget saat diklik atau dihitung ulang adalah masalah ketiga, yang dibahas dalam catatan pendamping tentang tindakan formulir interaktif dan JavaScript

Bagaimana cara mengisi formulir PDF dari FDF atau XFDF di Delphi?

Muat dokumen, panggil satu metode impor, lalu simpan. ImportFormDataFromXFDF dan ImportFormDataFromFDF masing-masing mengurai data formulir yang masuk, mencocokkan setiap entri dengan field AcroForm berdasarkan nama lengkapnya, menetapkan nilai, dan mengembalikan jumlah field yang benar-benar diperbarui. Kedua metode hanya memperbarui field yang sudah ada di PDF target; tidak ada yang membuat field baru untuk nama yang tidak ditentukan oleh formulir, yang mencegah file data asing atau berbahaya memperluas formulir Anda secara diam-diam

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;

Dua detail menentukan apakah data non-trivial bertahan dalam proses transfer. Pertama adalah escaping: FDF menyimpan nilai sebagai string literal PDF, sehingga nilai yang berisi tanda kurung, garis miring terbalik, atau byte yang tidak dapat dicetak akan tiba dalam bentuk octal escaping yang ditentukan dalam ISO 32000-2 §7.3.4.2, dan losLab PDF Library membalikkan escaping tersebut saat diimpor sehingga tanda kurung dan garis miring kembali sebagai karakter literal yang diketik oleh pengguna. Kedua adalah encoding: metode berbasis file menulis dan membaca XFDF and FDF sebagai UTF-8, yang merupakan apa yang dijanjikan oleh deklarasi XFDF dan apa yang dibutuhkan oleh nilai field non-ASCII apa pun (nama beraksen, simbol mata uang, alamat CJK) agar dapat berputar balik tanpa mengalami kerusakan. Jika Anda membuat XFDF sendiri, deklarasikan UTF-8 dan tulis UTF-8, dan impor akan berjalan lancar

Field hierarkis, pilihan multi-nilai, dan teks kaya

Nama field hierarkis adalah tempat pertama eksportir yang naif mengalami kegagalan. AcroForm mengatasi field bersarang dengan judul lengkap bertitik seperti Applicant.FullName, tetapi XFDF tidak menempatkan string bertitik itu dalam atribut nama tunggal; ISO 19444 menyarangkannya, seperti . losLab PDF Library membagi judul bertitik menjadi elemen bersarang saat diekspor dan merakit kembali elemen bersarang tersebut menjadi judul lengkap saat diimpor, sehingga kedua arah tetap simetris. Saat diekspor, ia juga melewatkan field induk non-terminal, karena node induk dalam AcroForm hanya membawa tingkat penamaan dan tidak memiliki nilainya sendiri; memancarkannya akan menghasilkan kosong yang tidak cocok dengan formulir asli. Kotak daftar multi-pilih adalah jebakan kedua: field pilihan dapat menampung beberapa nilai terpilih sekaligus, yang diekspresikan oleh XFDF sebagai elemen berulang dan diekspresikan oleh FDF sebagai array /V, dan losLab PDF Library hanya membagi field menjadi beberapa nilai ketika field tersebut benar-benar merupakan pilihan multi-pilih, sehingga field teks multi-baris biasa tetap mempertahankan hentian barisnya alih-alih pecah menjadi nilai-nilai palsu

Teks kaya adalah yang ketiga, dan merupakan hal yang paling sering salah dipahami orang. Field dengan pemformatan menyimpan markup-nya dalam entri RV sebagai subtree XHTML, dan XFDF membawanya dalam . losLab PDF Library menulis subtree tersebut sebagai fragmen XML langsung alih-alih meng-escape-nya, sehingga alat downstream membaca teks kaya asli dan bukan string tag yang terlihat; saat impor, ia mempertahankan subtree RV mentah dan tetap menerapkan biasa ke V. Jika suatu field menawarkan keduanya, nilai biasa menang untuk V dan teks kaya berjalan bersama di RV, yang merupakan aturan interoperabilitas yang mencegah impor teks kaya menulis ulang nilai yang telah ditetapkan oleh alat lain secara diam-diam. Ketika teks kaya Anda ada untuk menyampaikan struktur dokumen ke teknologi bantuan, perlakukan dengan cara yang sama seperti Anda memperlakukan urutan pembacaan yang dibahas dalam catatan tentang PDF bertag dan struktur aksesibilitas

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;

Bagaimana cara melakukan pertukaran komentar anotasi sebagai FDF or XFDF?

Komentar berjalan pada kelompok anotasi, dan subset yang didukung sengaja dibuat kecil. ExportAnnotationsToXFDF dan ImportAnnotationsFromXFDF, bersama dengan rekan FDF mereka, membawa markup gaya teks dengan field yang benar-benar ditransfer dengan bersih: subtipe anotasi, persegi panjangnya, indeks halaman berbasis 0, penulis di T, subjek di Subj, Contents biasa, dan warna, yang memetakan tiga kali lipat DeviceRGB /C PDF ke dan dari atribut XFDF #RRGGBB. Impor hanya menerima nama elemen yang dikenal dan melewatkan entri apa pun yang halamannya di luar jangkauan atau persegi panjangnya hilang, sehingga XFDF yang diedit secara manual atau asing tidak dapat memasukkan anotasi yang cacat ke dalam dokumen. Apa yang belum dibawa oleh subset ini perlu dinyatakan dengan jelas: konten teks kaya (RC), popup, quadpoint, daftar tinta, verteks, dan baked appearance stream berada di luar cakupan untuk saat ini, sehingga geometri sorotan dan tampilan stempel kustom tidak akan bertahan melalui jalur ini. Untuk mengonfirmasi apa yang sebenarnya masuk, telusuri anotasi halaman atau pohon elemen yang lebih luas yang dibahas dalam pencarian teks dan enumerasi elemen halaman

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;

Menulis paket XFA XDP lengkap dengan SetXFAFromString

XFA adalah pengecualian, dan SetXFAFromString adalah cara Anda menulis semuanya sekaligus. Metode ini mengambil XML Data Package lengkap, dokumen <xdp:xdp> dengan templat dan paket dataset-nya, dan menyimpannya sebagai stream yang direferensikan dari /AcroForm/XFA. losLab PDF Library membuat wadah AcroForm sesuai permintaan saat dokumen tidak memilikinya, sehingga Anda tidak perlu menambahkan field sementara hanya untuk memberikan tempat bagi XFA, dan ia membuang status XFA terurai yang disimpannya sehingga pembacaan di kemudian hari mencerminkan paket yang baru saja Anda tulis daripada cache yang usang. Karena paket XFA adalah XML dan tidak selalu UTF-8, pustaka mendeteksi tanda urutan byte (BOM) UTF-16 dan mendekode paket dengan benar sebelum mengurai, yang penting untuk paket yang dihasilkan oleh alat yang menggunakan UTF-16 secara bawaan

Setelah paket terpasang, GetXFAFormFieldValue dan SetXFAFormFieldValue menangani field individual melalui jalur Scripting Object Model mereka. losLab PDF Library menerima root SOM standar serta jalur relatif biasa, sehingga form1.FullName, $data.form1.FullName, dan xfa.datasets.data.form1.FullName semuanya mengarah ke node data yang sama, dan sisi templat menerima $template dan xfa.template dengan cara yang sama. Toleransi tersebut penting ketika jalur SOM dihasilkan oleh sistem lain yang selalu memancarkan formulir dengan nama lengkap

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;

Ringkasan jujurnya adalah bahwa nilai field ditransfer sepenuhnya melalui FDF dan XFDF, termasuk hierarki, multi-pilih, dan teks kaya; komentar anotasi ditransfer sebagai subset markup teks yang ditentukan dengan celah yang jelas; dan XFA ditulis dan dibaca sebagai satu paket utuh dengan akses SOM per-field di atasnya. Cocokkan format dengan konsumen, deklarasikan UTF-8 untuk apa pun yang Anda buat secara manual, dan ingat bahwa metode impor hanya menyentuh field dan anotasi yang sudah cocok dengan dokumen. Metode data formulir, anotasi, dan XFA yang dijelaskan di sini adalah bagian dari losLab PDF Library untuk Delphi dan C++Builder, yang referensinya memuat daftar parameter lengkap untuk setiap titik masuk ekspor dan impor