A Delphire és Lazarusra készült PDFium komponens az űrlapadatokat és megjegyzéseket az XFDF-en keresztül cseréli ki, amely az ISO 19444-1 által meghatározott XML adatcsere-formátum. A TPdf.ExportXFDF a betöltött dokumentumban lévő összes űrlapmező-értéket és minden támogatott megjegyzést szerializál egy XFDF fájlba vagy TStream-be; a TPdf.ImportXFDF visszaolvassa az XFDF dokumentumot, újra létrehozza a megjegyzéseket a megfelelő oldalaikon, és alkalmazza a mezőértékeket. Ez az egyetlen oda-vissza út két olyan munkafolyamatot fed le, amelyre előbb-utóbb minden dokumentum-alkalmazásnak szüksége van: egy felülvizsgáló megjelöl egy PDF-et Acrobatban, és elküldi Önnek a megjegyzéseket összevonásra, vagy egy megfelelőségi szabály kimondja, hogy az űrlapadatoknak egy különálló, diff-elhető és auditálható fájlban kell élniük, ahelyett hogy magába a PDF-be lennének égetve.
Támogatja a PDFium az XFDF importálását és exportálását?
Maga a PDFium könyvtár nem támogatja. A natív C API-nak egyáltalán nincsenek XFDF vagy FDF függvényei — a nyilvános fejléceiben semmi sem olvassa vagy írja egyik formátumot sem, így semmilyen burkolás (wrapping) nem vezet célra. A PDFium komponens ezért a teljes XFDF motort Pascalban valósítja meg, egy dedikált egységben (unit), amely az XML-t közvetlenül a meglévő TPdf megjegyzés- és űrlapmező-adatmodellre építi fel és elemzi. Az író kézzel bocsátja ki az XML-t, az olvasó pedig egy kézzel írt állapotgép-elemző, így a funkció nem vezet be függőséget a Delphi XMLDoc-tól vagy az FPC DOM egységeitől, és teljesen azonosan viselkedik Delphiben és Lazarusban.
Ez a tervezési döntés fontos, amikor az alternatívákat értékeli. Ha korábban nyers FPDF_* függvényeket hívott meg Pascalból, az XFDF egy fal: ez a képesség egyszerűen nincs benne a DLL-ben. A komponens ezt a falat úgy lépi át, hogy az XFDF-et tiszta szerializációs problémaként kezeli — összegyűjti az űrlapmezők értékeit és a megjegyzés-rekordokat, amelyeket a burkoló (wrapper) már tud olvasni, kiírja őket szabványos XML-ként, és az importáláskor megfordítja a folyamatot.
Mit tartalmaz egy XFDF fájl?
Az ISO 19444-1 az XFDF-et az FDF XML reprezentációjaként határozza meg, és a hasznos terhelése két felső szintű blokkra oszlik. A <fields> elem hordozza a hierarchikus űrlapmezőneveket és azok értékeit — mindent, amit a felhasználó begépelt, kiválasztott vagy bejelölt egy AcroForm-ban. A <annots> elem hordozza a megjegyzéseket: a TPdf.ExportXFDF 18 altípust bocsát ki — text, highlight, underline, strikeout, squiggly, line, circle, square, caret, polygon, polyline, stamp, ink, freetext, fileattachment, sound, link és redact. A widget-megjegyzések szándékosan hiányoznak a <annots> elemből, mert azok adatai a <fields>-ben utaznak, a megjelenítő-belső altípusok, mint például a Popup, pedig nem részei az XFDF szókincsnek.
Az oda-vissza út pontosságának biztosítása érdekében a TPdfAnnotation rekordot kiterjesztettük az XFDF által elvárt metaadatokkal: Name (az NM egyedi azonosító), Subject, ModificationDate, CreationDate, Icon, Opacity, vonal végpontok, sokszög és törtvonal csúcspontok, valamint tollvonás (ink) gesztusútvonalak. Minden új mezőhöz tartozik egy Has* logikai őrszem (sentinel), így a korábbi verziókra épülő megjegyzés-kódok továbbra is lefordulnak, és ugyanazokat a szótárakat állítják elő — a beállítatlan mezőket a program soha nem írja ki. Ha már programozottan hoz létre jelöléseket, ugyanaz a rekord, amelyet a szövegjelölési megjegyzésekhez quad pontokkal használ, most már mindent tartalmaz, amire az XFDF-nek szüksége van.
Hogyan exportálhatunk űrlapadatokat és megjegyzéseket XFDF-be?
Egyetlen hívás elvégzi a teljes dokumentumot. Töltse be a PDF-et engedélyezett űrlapkitöltéssel, hívja meg az ExportXFDF-et, és a komponens végigjár minden oldalt, összegyűjti a mezőértékeket és megjegyzéseket, majd megírja az XML-t. A visszatérési érték a leírt UTF-8 bájtok száma, ami hasznos ellenőrzésként szolgál a naplókban.
var
Pdf: TPdf;
Bytes: Integer;
begin
Pdf := TPdf.Create(Self);
Pdf.FormFill := True; // szükséges, hogy a mezőértékek élők legyenek
Pdf.FileName := 'expense-report.pdf';
Pdf.Active := True;
Bytes := Pdf.ExportXFDF('expense-report.xfdf');
ShowMessage(Format('%d bytes of XFDF written', [Bytes]));
end;
Mindkét iránynak van TStream túlterhelése (overload), így semmi sem kényszerít ideiglenes fájlokat a lemezre. A TMemoryStream-be történő exportálás a kézenfekvő forma, ha az XFDF egy HTTP válaszba, egy adatbázis blobba vagy egy aláírt archívumi bejegyzésbe tart.
var
Buffer: TMemoryStream;
begin
Buffer := TMemoryStream.Create;
try
Pdf.ExportXFDF(Buffer); // ugyanaz az XML, nem érintett fájl
Buffer.Position := 0;
// adja át a folyamot egy webes válasznak, blob oszlopnak vagy zip bejegyzésnek
finally
Buffer.Free;
end;
end;
Hogyan vonja össze az ImportXFDF a megjegyzéseket a dokumentummal?
Az importálási oldal az, ahol a felülvizsgálói munkafolyamat lezárul. Egy kolléga megjelöli a szerződést Acrobatban, exportálja a megjegyzéseket XFDF-ként, and sends you a few kilobytes of XML instead of a second copy of the PDF. A TPdf.ImportXFDF elemzi ezt a fájlt, létrehozza az egyes megjegyzéseket azon az oldalon, amelyet a page attribútum megnevez, és beírja a mezőértékeket a megfelelő widget-megjegyzésekbe. A függvény visszaadja az alkalmazott mezők és megjegyzések összesített számát, így a felhasználói felület pontosan meg tudja erősíteni, hogy mennyi adat érkezett meg.
Miért számítanak a tizedes elválasztók az XFDF esetében?
Az XFDF-ben minden megjegyzést koordináta-karakterláncok pozicionálnak — rect="70.5,540,200,560" és társaik —, és az ISO 19444-1 a pontot írja elő tizedes elválasztóként. A Delphi alapértelmezett lebegőpontos formázása a Windows területi beállításait követi, így egy német vagy francia rendszeren egy naiv FloatToStr a 70.5-öt 70,5-re változtatja, ami egy vesszővel elválasztott koordinátalistát olyan szemétté ront le, amelyet más feldolgozók elutasítanak vagy félreértenek. A PDFium komponens minden leírt számot normalizál: a területi tizedes elválasztót pontra írja át, és a záró nullákat levágja, így az exportált fájl bájtra megegyezik, függetlenül attól, hogy en-US vagy de-DE gépen készült. Ha valaha is hibakeresett olyan PDF eszközt, amely működött az irodában, de megbukott egy európai ügyfél helyszínén, akkor találkozott már ezzel a pontos hibatípussal — jó tudni, hogy a komponens kezeli ezt Ön helyett.
Mik az oda-vissza út korlátai?
Két határt érdemes nyíltan kimondani. Először is, az XFDF a megjegyzésadatokat szállítja, nem a renderelt megjelenést — a megjelenési folyamok (appearance streams) nem részei a formátumnak, így a fogadó megjelenítő az egyes megjegyzések kinézetét a tulajdonságaiból generálja újra. A kiemelés vagy a négyzet mindenhol megfelelően fog renderelődni; a saját megjelenéssel rendelkező bélyegző pedig arra fog visszaállni, amit a célmegjelenítő rajzol az adott bélyegzőnévhez. Másodszor, a mögöttes PDFium API tartalmaz írókat (setters) a karakterláncokhoz, de a megjegyzésszámokhoz vagy az útvonalgeometriához nem, így az Opacity, a vonalvégpontok, a csúcspontok és az tollvonás-gesztusok csak exportálásra szolgálnak: a komponens híven megőrzi őket az XFDF írásakor, de nem tudja visszahárítani őket a PDF-be importáláskor. A mezőértékek, a tartalom, a színek, a téglalapok (rects), a quad pontok, a dátumok és az identitás metaadatok mindkét irányban teljesen oda-vissza bejárhatók.
A gyakorlati kezdéshez az XfdfLab minta megtalálható a Delphi, C++Builder és Lazarus bemutatókészletekben, és mindkét hívást gombokhoz köti a megnyitott PDF-ek felett. Az XFDF támogatás megtalálható a PDFium komponens jelenlegi kiadásában, a megjegyzés és űrlap API-k mellett, amelyekre épül.