Tehnički članak

Prevođenje XFA u AcroForm u Delphi-ju pomoću HotPDF-a

Dva obrasca mogu imati ista polja, a ponašati se potpuno različito. AcroForm čuva svoja polja kao obične PDF objekte koji se nalaze na vrhu stvarnog sadržaja stranice, tako da ih svaki usklađeni pregledač iscrtava. Dinamički XFA obrazac ne čuva skoro ništa kao PDF: polja, raspored, pa čak i geometrija stranice žive u XML paketu, a vidljive stranice se stvaraju u trenutku otvaranja pomoću layout mehanizma koji je samo Adobe ikada šire distribuirao. Ako pošaljete tu datoteku veb pregledaču, arhivskom rendereru ili ekstraktoru teksta, nećete dobiti obrazac. Dobićete jednu sivu stranicu na kojoj piše: "Please wait... If this message is not eventually replaced by the proper contents of the document, your PDF viewer may not be able to display this type of document." Svako ko je ikada obrađivao državnu ili dokumentaciju osiguranja prepoznaje ovu stranicu na prvi pogled

Ovaj privremeni tekst (placeholder) nije oštećenje datoteke. To je tačno ono što format propisuje da treba da se desi kada XFA procesor nije prisutan, a od 2026. godine to opisuje skoro svaki pregledač van desktop verzije Acrobat-a. Zato je praktičan korak konvertovati dinamički obrazac u običan AcroForm pre nego što stigne do bilo kog nizvodnog sistema. HotPDF, losLab PDF biblioteka za Delphi i C++Builder, vrši tu konverziju u kodu, ponovo gradeći XML obrazac kao izvorna polja na izvornim stranicama

Zašto ova dva modela ne mogu koegzistirati

AcroForm je definisan u standardu ISO 32000-1 §12.7. Svako polje je PDF objekat sa widget anotacijom i tokom izgleda (appearance stream), stranica je stvarni PDF sadržaj, a podaci se nalaze na vrhu. XFA to izvrće: obrazac je XML dokument, XDP paket sačuvan u unosu /XFA u AcroForm rečniku, a PDF stranice dinamičkog obrasca sadrže samo privremeni tekst "Please wait" i ništa drugo, jer stvarni sadržaj nikada nije bio serijalizovan kao PDF. Čitač obrađuje datoteku kao jedan ili drugi model. Ignorišite unos /XFA i videćete praznu ljušturu. Poštujte ga bez XFA mehanizma i videćete upozorenje. Standard ISO 32000-2 je okončao ovu debatu izbacivanjem XFA iz PDF-a 2.0, što je glavni razlog zašto se "konvertuj dok još možemo" pretvorilo iz izuzetnog slučaja u rutinsku praksu prijemne obrade dokumenata

Pre nego što bilo šta konvertujete, klasifikujte dokument, jer ne prikazuje svaka XFA datoteka privremenu stranicu upozorenja. Statički XFA obrasci se isporučuju sa unapred renderovanim PDF stranicama pored XML-a, tako da se prikazuju svuda i ponašaju se neispravno samo kada se popune. Dinamički obrasci šalju samo privremenu stranicu i neupotrebljivi su dok se ne konvertuju. Ono u šta treba verovati jeste dokument, a nikada ekstenzija ili pošiljalac. Datoteka koja renderuje stvarni sadržaj u pregledaču koji nije Adobe, a i dalje nosi unos /XFA, jeste statička ili hibridna. Datoteka koja prikazuje stranicu upozorenja je dinamička. Zabeležite u koju kategoriju je svaka datoteka svrstana. Ove dve vrste se kasnije kvare na različite načine, a žalba o praznom arhiviranom obrascu se zatvara za nekoliko sekundi ako u dnevniku prijemne obrade već piše: "dinamički XFA, konvertovano, 47 polja mapirano, 2 upozorenja"

Konvertovanje učitanog XFA dokumenta u izvorna polja

Konverzija se pokreće nad dokumentom koji je već učitan u memoriju. Metoda FlattenLoadedXFA parsira XFA šablon i njegove pakete podataka, raspoređuje obrazac i ponovo ga gradi kao AcroForm polja na stvarnim PDF stranicama:

var
  Pdf: THotPDF;
  MappedCount, I: Integer;
  Warnings: TStrings;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.LoadFromFile('dynamic_xfa.pdf');
    MappedCount := Pdf.FlattenLoadedXFA(True);   // True = fields stay editable
    Warnings := Pdf.XFAFlattenWarnings;
    for I := 0 to Warnings.Count - 1 do
      Log('XFA flatten warning: ' + Warnings[I]); // unmapped elements
    Pdf.SaveLoadedDocument('native_acroform.pdf');
    Log(Format('Mapped %d fields', [MappedCount]));
  finally
    Pdf.Free;
  end;
end;

Povratna vrednost i lista upozorenja predstavljaju izlazne podatke, a ne buku u otklanjanju grešaka (debug noise), tako da ih sačuvajte. Konverzija po svojoj prirodi gubi informacije: XFA skriptovanje, izračunata polja i dinamičko ponašanje podobrazaca nemaju ekvivalent u AcroForm-u, a XFAFlattenWarnings navodi svaki element šablona koji nije uspešno mapiran. Ako arhivirate konvertovanu datoteku bez njene liste upozorenja, jednog dana ćete gledati u prazno polje ukupnih vrednosti u arhiviranoj kopiji bez ikakvog zapisa o tome zašto je to tako. Zastavica Editable kontroliše da li nova polja ostaju popunljiva. Prosledite True ako ljudi nastavljaju da rade sa obrascem nakon toga, a zaključajte vrednosti kada je cilj kreiranje zamrznutog zapisa

Provera konverzije je delom vizuelna, a delom strukturna, i potrebne su vam obe polovine. Slikovni, strukturni deo je lak: potvrdite da broj polja odgovara MappedCount-u. Vizuelni deo je onaj koji otkriva stvarna oštećenja. Otvorite izvorni obrazac u desktop verziji programa Acrobat, koji je i dalje jedini pregledač koji pokreće XFA mehanizam, pored konvertovane datoteke u običnom čitaču, i uporedite vrednosti i raspored na najmanje jednom popunjenom uzorku po šablonu. Datum koji je XFA mehanizam prikazao kao 2026-06-11 može završiti u AcroForm kopiji kao sirova, neformatirana vrednost, i to jedino ljudsko oko može primetiti

Kada je ulaz XDP paket

Ne počinje svaki posao sa popunjenim PDF dokumentom. Ponekad dobijate XDP paket samostalno, izvezen iz alata za dizajn obrazaca ili predat od strane partnerskog sistema. Metoda ApplyXFAAsAcroForm preskače korak učitavanja i primenjuje paket direktno na trenutni dokument:

XDPBytes := TFile.ReadAllBytes('benefit-claim.xdp');
MappedCount := Pdf.ApplyXFAAsAcroForm(XDPBytes, True);

Ista grupa poziva radi i u suprotnom smeru, za ređe slučajeve kada morate da emitujete XFA umesto da ga konzumirate. Metoda AddXFAPacket prilaže pojedinačne imenovane pakete kao što su 'xdp' ili 'config'. Metoda SetXFADocument instalira kompletan payload sa jednim tokom u jednom pozivu. Metoda ClearXFAPackets briše registraciju kako biste mogli da počnete iznova, a AddXFASignaturePacket ugrađuje XAdES materijal za radne tokove koji direktno potpisuju XML podatke obrasca. Generisanje XFA u 2026. godini je specifična potreba, skoro uvek nametnuta od strane nekog nasleđenog (legacy) sistema koji odbija bilo šta drugo, ali kada ugovor to zahteva, ovi pozivi to svode na izbor konfiguracije umesto na korišćenje zasebnog alata

Drugo značenje reči "flatten" (poravnavanje)

Reč "flatten" (poravnavanje) unosi dosta zabune u razgovore jer imenuje sasvim drugu operaciju: trajno utiskivanje izgleda AcroForm polja u tok sadržaja stranice dok ne nestanu svi interaktivni objekti. HotPDF danas nema API za to, i to je dobro znati odmah, a ne na pola projekta. Ono što vam biblioteka nudi umesto toga jeste zaključavanje na nivou polja prilikom njegovog kreiranja, podržano dozvolama dokumenta:

// Lock the value at field creation: read-only text field
Pdf.CurrentPage.AddTextField('CaseNumber', 'BC-2026-0117',
  Rect(50, 700, 220, 720), 0, [ffReadOnly]);

// Belt and suspenders: restrict form filling document-wide
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.OwnerPassword := 'records-owner';
Pdf.ProtectOptions := [prPrint, prInformationCopy, prExtractContent];
// fill permission withheld: prFillAnnotations is absent from the set

Budite načisto sa tim šta time dobijate, a šta ne. Polje koje je samo za čitanje (read-only) je i dalje objekat obrasca. Ono se prikazuje na panelu polja u pregledaču, njegova vrednost se može pročitati preko API-ja obrasca, a alat koji ponovo upisuje datoteku može ponovo obrisati read-only zastavicu. Zastavice dozvola podižu prepreku, ali zavise od toga da li čitač bira da ih poštuje, što je ograničenje koje standard ISO 32000-1 jasno navodi. Kada regulator zahteva da arhivirani zapis ne sadrži nikakve objekte obrasca, iskren odgovor sa HotPDF-om danas je rekonstrukcija dokumenta: pročitajte vrednosti i iscrtajte ih kao običan sadržaj pomoću TextOut na novoj stranici, umesto da maskirate read-only zastavice kao poravnavanje. Jedna stvar koju treba zapamtiti kod postavljanja dozvola jeste da se CryptKeyLength mora postaviti pre poziva BeginDoc. Ostatak je opisan u našem članku o AES-256 enkripciji i dozvolama

Šta XFA znači za arhivsku usklađenost

Standardi PDF/A i PDF/X u potpunosti odbijaju XFA. Proces koji puni ISO 19005 arhivu stoga mora prvo da izvrši konverziju, i taj redosled se ne može menjati: učitajte, pozovite FlattenLoadedXFA, sačuvajte, a zatim pokrenite arhivsku generaciju ili validaciju nad AcroForm rezultatom. Nemojte tretirati konverziju kao dokaz usklađenosti sa standardom. Ona ispravlja model obrasca, ali ostavlja fontove, boje i metapodatke tačno onakvim kakvi su i bili, pa pre nego što mu poverujete, validirajte izlaz pomoću alata veraPDF. Kada obrazac pređe na AcroForm stranu, njegovo ponašanje dobija sopstveni skup kontrola. JavaScript okidači, akcije slanja i skripte za validaciju pokriveni su u članku o HotPDF AcroForm poljima i akcijama

API-ji za XFA registraciju, konverziju i obrasce prikazani ovde isporučuju se uz HotPDF komponentu za Delphi i C++Builder, čija dokumentacija prati razvoj XFA funkcionalnosti kroz nedavna izdanja