Articol tehnic

Aplatizarea formularelor XFA în AcroForm în Delphi folosind HotPDF

Două formulare pot purta aceleași câmpuri și pot avea comportamente complet diferite. Un AcroForm își păstrează câmpurile ca obiecte PDF obișnuite, așezate deasupra conținutului real de pagină, așa că orice cititor conform îl desenează. Un formular XFA dinamic nu păstrează aproape nimic ca PDF: câmpurile, layout-ul, chiar și geometria paginii trăiesc într-un pachet XML, iar paginile vizibile sunt produse la momentul deschiderii de un motor de layout pe care doar Adobe l-a livrat vreodată pe scară largă. Dați acel fișier unui vizualizator web, unui randator de arhivă sau unui extractor de text și nu primiți formularul. Primiți o singură pagină gri care spune "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." Oricine a preluat documente guvernamentale sau de asigurări recunoaște acea pagină dintr-o privire

Placeholder-ul nu este corupție. Este exact ceea ce formatul specifică că ar trebui să se întâmple atunci când nu există niciun procesor XFA, iar din 2026 asta descrie aproape orice vizualizator în afara Acrobat desktop. Așa că mișcarea practică este să convertiți formularul dinamic într-un AcroForm simplu înainte ca acesta să ajungă la orice altceva în aval. HotPDF, biblioteca PDF losLab pentru Delphi și C++Builder, face acea conversie în cod, reconstruind formularul XML ca câmpuri native pe pagini native

HotPDF: comparație paralelă între un AcroForm, ale cărui pagini, widget-uri și valori trăiesc toate în PDF, și un formular XFA dinamic, care arată o pagină substituent fără un motor XFA
AcroForm păstrează paginile, widget-urile și valorile în interiorul PDF-ului, astfel încât orice cititor desenează formularul, în timp ce XFA dinamic le ascunde în spatele substitutului de așteptare

De ce cele două modele nu pot coexista

AcroForm este definit în ISO 32000-1 §12.7. Fiecare câmp este un obiect PDF cu o adnotare widget și un flux de aspect, pagina este conținut PDF autentic, iar datele călătoresc deasupra lui. XFA inversează asta: formularul este un document XML, un pachet XDP stocat în intrarea /XFA a dicționarului AcroForm, iar paginile PDF ale unui formular dinamic conțin doar placeholder-ul "Please wait" și nimic altceva, pentru că adevăratul conținut nu a fost niciodată serializat ca PDF. Un cititor procesează un fișier după un model sau celălalt. Ignorați intrarea /XFA și vedeți carcasa goală; respectați-o fără un motor XFA și vedeți avertismentul. ISO 32000-2 a încheiat disputa eliminând XFA din PDF 2.0, ceea ce este motivul principal pentru care "convertiți cât mai puteți" a trecut de la un caz limită la o politică de recepție de rutină

Înainte de a converti orice, clasificați-l, pentru că nu fiecare fișier XFA arată placeholder-ul. Formularele XFA statice livrează pagini PDF pre-randate alături de XML, așa că se afișează peste tot și se comportă greșit doar la completare. Formularele dinamice livrează doar placeholder-ul și sunt inutilizabile până la conversie. Lucrul de care trebuie să aveți încredere este documentul, niciodată extensia sau expeditorul. Un fișier care randează conținut real într-un vizualizator non-Adobe, dar tot poartă o intrare /XFA, este static sau hibrid; un fișier care arată pagina de avertisment este dinamic. Înregistrați în ce categorie a căzut fiecare fișier de recepție. Cele două tipuri se strică diferit mai târziu, iar un tichet despre un formular arhivat gol se închide în secunde atunci când jurnalul de recepție spune deja "XFA dinamic, convertit, 47 de câmpuri mapate, 2 avertismente"

Convertirea unui document XFA încărcat în câmpuri native

Conversia rulează pe un document deja aflat în memorie. FlattenLoadedXFA parsează șablonul XFA și pachetele sale de date, așază formularul în pagină și îl reconstruiește ca și câmpuri AcroForm pe pagini PDF reale:

var
  Pdf: THotPDF;
  MappedCount, I: Integer;
  Warnings: TStrings;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.LoadFromFile('dynamic_xfa.pdf');
    MappedCount := Pdf.FlattenLoadedXFA(True);   // True = câmpurile rămân editabile
    Warnings := Pdf.XFAFlattenWarnings;
    for I := 0 to Warnings.Count - 1 do
      Log('XFA flatten warning: ' + Warnings[I]); // elemente nemapate
    Pdf.SaveLoadedDocument('native_acroform.pdf');
    Log(Format('Mapped %d fields', [MappedCount]));
  finally
    Pdf.Free;
  end;
end;

Valoarea returnată și lista de avertismente sunt rezultat, nu zgomot de depanare, așa că păstrați-le pe amândouă. Conversia pierde informație prin însăși natura ei: scriptingul XFA, câmpurile calculate și comportamentul dinamic al subformularelor nu au niciun echivalent în AcroForm, iar XFAFlattenWarnings numește fiecare element de șablon care nu s-a mapat. Arhivați fișierul convertit fără lista sa de avertismente și cândva veți privi fix o casetă de total goală într-o copie arhivată, fără nicio înregistrare a motivului. Flagul Editable controlează dacă noile câmpuri rămân completabile. Transmiteți True atunci când oamenii continuă să lucreze cu formularul ulterior și blocați valorile atunci când scopul este o înregistrare înghețată

Verificarea unei conversii este parțial vizuală, parțial structurală, și aveți nevoie de ambele jumătăți. Jumătatea structurală este ușoară: confirmați că numărul de câmpuri corespunde cu MappedCount. Jumătatea vizuală este cea care prinde stricăciunile reale. Deschideți formularul sursă în Acrobat desktop, încă singurul vizualizator care rulează motorul XFA, alături de fișierul convertit într-un cititor obișnuit, și comparați valorile și layout-ul pe cel puțin un eșantion completat per șablon. O dată pe care motorul XFA a afișat-o ca 2026-06-11 poate ajunge în copia AcroForm ca o valoare brută, neformatată, iar doar ochii dumneavoastră vor prinde asta

Flux de clasificare la primire pentru documentele XFA în Delphi: fișierele care renderează conținut real în afara Acrobat sunt statice sau hibride, în timp ce fișierele care arată pagina de așteptare sunt dinamice și trebuie convertite
Formularele hibride se dovedesc randând conținut real în cititoare non-Adobe, în timp ce formularele dinamice se dezvăluie doar prin pagina substitut

Când intrarea este un pachet XDP

Nu fiecare sarcină pornește de la un PDF populat. Uneori primiți pachetul XDP de unul singur, exportat dintr-un instrument de proiectare a formularelor sau predat de un sistem partener. ApplyXFAAsAcroForm elimină pasul de încărcare și aplică pachetul direct documentului curent:

Conductă HotPDF care aplatizează un document XFA dinamic încărcat în câmpuri AcroForm editabile în Delphi, expunând scripting-ul nemapat și câmpurile calculate prin XFAFlattenWarnings
FlattenLoadedXFA parsează și transmite pachetele XDP în câmpuri AcroForm editabile, iar XFAFlattenWarnings înregistrează fiecare element care nu a putut fi mapat
XDPBytes := TFile.ReadAllBytes('benefit-claim.xdp');
MappedCount := Pdf.ApplyXFAAsAcroForm(XDPBytes, True);

Același grup de apeluri rulează și în cealaltă direcție, pentru cazul mai rar în care trebuie să emiteți XFA în loc să îl consumați. AddXFAPacket atașează pachete individuale numite, precum 'xdp' sau 'config'. SetXFADocument instalează un payload complet, cu un singur flux, într-un singur apel. ClearXFAPackets șterge înregistrarea astfel încât să puteți reîncepe, iar AddXFASignaturePacket înglobează material XAdES pentru fluxuri de lucru care semnează direct datele de formular XML. Producerea de XFA în 2026 este o nevoie de nișă, aproape întotdeauna forțată de un singur consumator legacy care refuză orice altceva, dar atunci când un contract o cere, aceste apeluri o reduc la o alegere de configurare, nu la un instrument separat

Celălalt sens al termenului "flatten"

Cuvântul "flatten" încurcă multe conversații, pentru că numește o a doua operație complet diferită: arderea aspectelor câmpurilor AcroForm în fluxul de conținut al paginii, până când nu mai rămâne niciun obiect interactiv. HotPDF nu are niciun API pentru asta astăzi, iar e mai bine să aflați acest lucru acum decât la jumătatea unui proiect. Ceea ce vă oferă biblioteca în schimb este blocarea la nivel de câmp, în momentul creării câmpului, susținută de permisiunile documentului:

// Blochează valoarea la crearea câmpului: câmp de text doar-citire
Pdf.CurrentPage.AddTextField('CaseNumber', 'BC-2026-0117',
  Rect(50, 700, 220, 720), 0, [ffReadOnly]);

// Curea și bretele: restricționează completarea formularului la nivel de document
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.OwnerPassword := 'records-owner';
Pdf.ProtectOptions := [prPrint, prInformationCopy, prExtractContent];
// permisiunea de completare este reținută: prFillAnnotations lipsește din mulțime

Fiți clar cu privire la ce vă cumpără asta și ce nu vă cumpără. Un câmp doar-citire este tot un obiect de formular. Apare în panoul de câmpuri al vizualizatorului, valoarea sa este lizibilă prin API-ul de formular, iar un instrument care rescrie fișierul poate șterge din nou flagul de doar-citire. Flagurile de permisiune ridică ștacheta, dar depind de alegerea vizualizatorului de a le respecta, o limitare pe care ISO 32000-1 o afirmă clar. Când un organism de reglementare insistă ca o înregistrare arhivată să nu conțină deloc obiecte de formular, răspunsul cinstit cu HotPDF astăzi este să reconstruiți documentul: citiți valorile, apoi desenați-le ca și conținut TextOut obișnuit pe o pagină nouă, în loc să deghizați flagurile de doar-citire drept flattening. Un lucru de reținut pe calea permisiunilor este că CryptKeyLength trebuie setat înainte de BeginDoc; restul se găsește în articolul nostru despre criptarea AES-256 și permisiuni

Ce înseamnă XFA pentru conformitatea arhivistică

Atât PDF/A cât și PDF/X resping XFA direct. Un flux care alimentează o arhivă ISO 19005 trebuie deci să convertească mai întâi, iar ordinea nu este negociabilă: încarcă, FlattenLoadedXFA, salvează, apoi rulează generarea sau validarea arhivistică pe rezultatul AcroForm. Nu tratați conversia ca dovadă de conformitate. Ea repară modelul de formular și lasă fonturile, culoarea și metadatele exact cum erau, așa că validați rezultatul cu veraPDF înainte de a avea încredere în el. Odată ce formularul este pe partea AcroForm, comportamentul său primește propriul set de controale. Declanșatoarele JavaScript, acțiunile de submit și scripturile de validare sunt tratate în articolul HotPDF despre câmpurile AcroForm și acțiuni

API-urile de înregistrare XFA, conversie și formular prezentate aici vin incluse în HotPDF Delphi Component pentru Delphi și C++Builder, a cărui documentație urmărește setul de funcții XFA pe măsură ce a crescut de-a lungul versiunilor recente