Teknisk artikkel

Flating fra XFA til AcroForm i Delphi ved bruk av HotPDF

To skjemaer kan bære de samme feltene og oppføre seg helt forskjellig. Et AcroForm holder feltene sine som vanlige PDF-objekter oppå ekte sideinnhold, så enhver lovlydig leser tegner det. Et dynamisk XFA-skjema holder nesten ingenting som PDF: feltene, layouten, til og med sidegeometrien lever i en XML-pakke, og de synlige sidene produseres ved åpningstidspunktet av en layoutmotor bare Adobe noensinne har sendt ut i bred skala. Mat den filen til en nettviser, en arkivrendrer eller en tekstuttrekker, og du får ikke skjemaet. Du får én grå side som leser «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.» Alle som har tatt imot offentlig eller forsikringsrelatert papirarbeid, kjenner igjen den siden på flekken

Plassholderen er ingen korrupsjon. Det er nøyaktig det formatet spesifiserer skal skje når ingen XFA-prosessor er til stede, og per 2026 beskriver det nesten hver eneste viser utenfor desktop-Acrobat. Så det praktiske grepet er å konvertere det dynamiske skjemaet til et rent AcroForm før det når noe som helst nedstrøms. HotPDF, losLabs PDF-bibliotek for Delphi og C++Builder, gjør den konverteringen i kode, og bygger XML-skjemaet om til native felt på native sider

HotPDF: Side-om-side-sammenligning av et AcroForm, hvis sider, widgets og verdier alle lever i PDF-en, og et dynamisk XFA-skjema som viser en plassholderside uten en XFA-motor
AcroForm beholder sider, widgets og verdier inne i PDF-en slik at enhver leser tegner skjemaet, mens dynamisk XFA gjemmer dem bak Please-wait-plassholderen

Hvorfor de to modellene ikke kan sameksistere

AcroForm er definert i ISO 32000-1 §12.7. Hvert felt er et PDF-objekt med en widget-annotasjon og en appearance-strøm, siden er ekte PDF-innhold, og dataene rir oppå det. XFA snur dette på hodet: skjemaet er et XML-dokument, en XDP-pakke lagret i /XFA-oppføringen i AcroForm-dictionaryen, og et dynamisk skjemas PDF-sider holder kun «Please wait»-plassholderen og ingenting annet, fordi det virkelige innholdet aldri ble serialisert som PDF. En leser behandler en fil som den ene modellen eller den andre. Ignorer /XFA-oppføringen, og du ser det tomme skallet; respekter den uten en XFA-motor, og du ser advarselen. ISO 32000-2 avsluttet debatten ved å droppe XFA fra PDF 2.0, som er hovedgrunnen til at «konverter mens vi fortsatt kan» gikk fra å være et grensetilfelle til å bli rutinemessig inntakspolicy

Før du konverterer noe som helst, klassifiser det, fordi ikke hver eneste XFA-fil viser plassholderen. Statiske XFA-skjemaer sender med forhåndsrendrede PDF-sider ved siden av XML-en, så de vises overalt og oppfører seg bare feil når de fylles ut. Dynamiske skjemaer sender bare med plassholderen og er ubrukelige før de er konvertert. Det du skal stole på, er dokumentet, aldri filendelsen eller avsenderen. En fil som rendrer ekte innhold i en ikke-Adobe-viser, men likevel bærer en /XFA-oppføring, er statisk eller hybrid; en fil som viser advarselssiden, er dynamisk. Registrer hvilken bøtte hver inntaksfil havnet i. De to typene går i stykker på forskjellige måter senere, og en sak om et blankt arkivert skjema lukkes på sekunder når inntaksloggen allerede leser «dynamisk XFA, konvertert, 47 felt kartlagt, 2 advarsler»

Å konvertere et innlastet XFA-dokument til native felt

Konverteringen kjøres mot et dokument som allerede er i minnet. FlattenLoadedXFA parser XFA-malen og datapakkene dens, legger ut skjemaet, og bygger det om til AcroForm-felt på ekte PDF-sider:

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

Returverdien og advarselslisten er output, ikke feilsøkingsstøy, så behold begge. Konvertering mister informasjon av natur: XFA-scripting, beregnede felt og dynamisk delskjema-atferd har ingen AcroForm-motpart, og XFAFlattenWarnings navngir hvert malelement som ikke ble kartlagt. Arkiver den konverterte filen uten advarselslisten dens, og en dag vil du stirre på en tom sumboks i en arkivert kopi uten noen registrering av hvorfor. Editable-flagget styrer om de nye feltene forblir utfyllbare. Send True når folk fortsetter å jobbe med skjemaet etterpå, og lås verdiene når målet er en fastfrosset post

Å kontrollere en konvertering er delvis visuelt, delvis strukturelt, og du trenger begge halvdelene. Den strukturelle halvdelen er enkel: bekreft at feltantallet stemmer med MappedCount. Den visuelle halvdelen er den som fanger opp ekte skade. Åpne kildeskjemaet i desktop-Acrobat, fortsatt den eneste viseren som kjører XFA-motoren, ved siden av den konverterte filen i en ordinær leser, og sammenlign verdier og layout på minst ett utfylt eksemplar per mal. En dato XFA-motoren viste som 2026-06-11, kan havne i AcroForm-kopien som en rå, uformatert verdi, og bare øynene dine vil fange opp det

Inntaksklassifiseringsflyt for XFA-dokumenter i Delphi: filer som rendere ekte innhold utenfor Acrobat er statiske eller hybride, mens filer som viser Vennligst-vent-siden er dynamiske og må konverteres
Hybride skjemaer beviser seg ved å rendere ekte innhold i ikke-Adobe-fremvisere, mens dynamiske skjemaer avslører seg gjennom plassholdersiden alene

Når inndataen er en XDP-pakke

Ikke hver jobb starter fra en utfylt PDF. Noen ganger mottar du XDP-pakken alene, eksportert fra et skjemadesignverktøy eller overlevert av et partnersystem. ApplyXFAAsAcroForm dropper innlastingssteget og påfører pakken rett på det gjeldende dokumentet:

HotPDF-rørledning som flater ut et lastet dynamisk XFA-dokument til redigerbare AcroForm-felt i Delphi, og bringer umappede skript og beregnede felt opp gjennom XFAFlattenWarnings
FlattenLoadedXFA parser og viderefører XDP-pakkene inn i redigerbare AcroForm-felt, og XFAFlattenWarnings registrerer hvert element som ikke kunne mappes
XDPBytes := TFile.ReadAllBytes('benefit-claim.xdp');
MappedCount := Pdf.ApplyXFAAsAcroForm(XDPBytes, True);

Den samme gruppen kall kjører også den andre veien, for det sjeldnere tilfellet der du må sende ut XFA i stedet for å konsumere det. AddXFAPacket fester individuelle navngitte pakker som 'xdp' eller 'config'. SetXFADocument installerer en komplett enkelt-strøm-nyttelast i ett kall. ClearXFAPackets visker ut registreringen, slik at du kan starte på nytt, og AddXFASignaturePacket bygger inn XAdES-materiale for arbeidsflyter som signerer XML-skjemadataene direkte. Å produsere XFA i 2026 er et nisjebehov, nesten alltid tvunget frem av én gammel forbruker som avviser alt annet, men når en kontrakt navngir det, holder disse kallene det nede på et konfigurasjonsvalg i stedet for et separat verktøy

Den andre betydningen av «flatten»

Ordet «flatten» snubler mange samtaler, fordi det navngir en helt annen operasjon: å brenne AcroForm-feltenes appearance inn i sideinnholdsstrømmen til ingen interaktive objekter er igjen. HotPDF har ikke noe API for det i dag, og du vil vite det nå, ikke halvveis inn i et prosjekt. Det biblioteket gir deg i stedet, er låsing på feltnivå når feltet opprettes, støttet av dokumenttillatelser:

// Lås verdien ved feltopprettelse: skrivebeskyttet tekstfelt
Pdf.CurrentPage.AddTextField('CaseNumber', 'BC-2026-0117',
  Rect(50, 700, 220, 720), 0, [ffReadOnly]);

// Belte og bukseseler: begrens skjemautfylling dokumentbredt
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.OwnerPassword := 'records-owner';
Pdf.ProtectOptions := [prPrint, prInformationCopy, prExtractContent];
// utfyllingstillatelse tilbakeholdt: prFillAnnotations mangler fra settet

Vær tydelig på hva det gir deg, og hva det ikke gir deg. Et skrivebeskyttet felt er fortsatt et skjemaobjekt. Det dukker opp i viserens feltpanel, verdien er lesbar gjennom skjema-API-et, og et verktøy som skriver om filen, kan fjerne skrivebeskyttelsesflagget igjen. Tillatelsesflagg hever terskelen, men avhenger av at viseren velger å respektere dem, en begrensning ISO 32000-1 sier rett ut. Når en tilsynsmyndighet insisterer på at en arkivert post ikke skal inneholde noen skjemaobjekter i det hele tatt, er det ærlige svaret med HotPDF i dag å bygge dokumentet om: lese ut verdiene, tegne dem deretter som vanlig TextOut-innhold på en fersk side, i stedet for å pynte på skrivebeskyttelsesflagg som om det var flattening. Én ting å huske på tillatelsesveien er at CryptKeyLength må settes før BeginDoc; resten står i artikkelen vår om AES-256-kryptering og tillatelser

Hva XFA betyr for arkivsamsvar

PDF/A og PDF/X avviser begge XFA rett ut. En pipeline som mater et ISO 19005-arkiv, må derfor konvertere først, og rekkefølgen er ikke omforhandlingsbar: last inn, FlattenLoadedXFA, lagre, og kjør deretter arkivgenerering eller -validering på AcroForm-resultatet. Ikke behandle konvertering som bevis på samsvar. Den fikser skjemamodellen og lar skrifter, farge og metadata stå akkurat som de var, så valider outputen med veraPDF før du stoler på den. Når skjemaet først er på AcroForm-siden, får atferden sin egen kontrollmengde. JavaScript-utløsere, innsendingshandlinger og valideringsskript dekkes i artikkelen om HotPDF AcroForm-felt og -handlinger

XFA-registrerings-, konverterings- og skjema-API-ene vist her, følger med HotPDF Delphi Component for Delphi og C++Builder, hvis dokumentasjon sporer XFA-funksjonssettet slik det har vokst gjennom nylige utgivelser