Technický článek

Převod XFA na AcroForm v Delphi pomocí HotPDF

Dva formuláře mohou nést stejná pole a chovat se úplně jinak. AcroForm drží svá pole jako obyčejné objekty PDF sedící na vrcholu skutečného obsahu stránky, takže je nakreslí kterýkoli konformní čtenář. Dynamický formulář XFA nese jako PDF téměř nic: pole, rozvržení, dokonce i geometrie stránky žijí v balíčku XML, a viditelné stránky vznikají při otevření pomocí rozvrhovacího enginu, který kdy ve větší míře dodával jen Adobe. Nakrmte tímto souborem webový prohlížeč, archivní renderer nebo extraktor textu a formulář nedostanete. Dostanete jedinou šedou stránku s textem „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.". Každý, kdo kdy zpracovával státní nebo pojišťovací papírování, tuto stránku pozná na první pohled

Tento zástupný symbol není poškození. Je to přesně to, co formát předepisuje, když není přítomný žádný procesor XFA, a k roku 2026 to popisuje téměř každý prohlížeč mimo desktopový Acrobat. Praktický krok je tedy převést dynamický formulář na obyčejný AcroForm dřív, než se dostane k čemukoli po proudu. HotPDF, PDF knihovna od losLab pro Delphi a C++Builder, tento převod dělá v kódu a přestavuje formulář XML na nativní pole na nativních stránkách

HotPDF: Srovnání vedle sebe: AcroForm, jehož strany, widgety i hodnoty všechny žijí v PDF, a dynamický formulář XFA ukazující placeholder stranu bez enginu XFA
AcroForm drží stránky, widgety i hodnoty uvnitř PDF, takže formulář vykreslí každá čtečka, zatímco dynamické XFA je schovává za zástupný obrázek Please-wait

Proč tyto dva modely nemohou koexistovat

AcroForm je definovaný v ISO 32000-1 §12.7. Každé pole je objekt PDF s widgetovou anotací a appearance streamem, stránka je opravdový obsah PDF a data na ní jedou navrch. XFA to obrací naruby: formulář je dokument XML, balíček XDP uložený v položce /XFA slovníku AcroForm, a stránky PDF dynamického formuláře nesou zástupný symbol „Please wait" a nic víc, protože skutečný obsah nikdy nebyl serializovaný jako PDF. Čtečka zpracuje soubor buď podle jednoho modelu, nebo podle druhého. Ignorujte položku /XFA a uvidíte prázdnou skořápku; respektujte ji bez enginu XFA a uvidíte varování. ISO 32000-2 ukončilo debatu tím, že z PDF 2.0 XFA vypustilo, což je hlavní důvod, proč se „převeď, dokud to ještě jde" změnilo z okrajového případu na rutinní politiku příjmu

Než cokoli převedete, zařaďte to do kategorie, protože ne každý soubor XFA ukazuje zástupný symbol. Statické formuláře XFA dodávají předvykreslené stránky PDF vedle XML, takže se zobrazí všude a chovají se špatně jen při vyplňování. Dynamické formuláře dodávají jen zástupný symbol a jsou nepoužitelné, dokud se nepřevedou. Věc, které máte věřit, je dokument, nikdy přípona nebo odesílatel. Soubor, který v prohlížeči od jiné firmy než Adobe vykreslí skutečný obsah, a přesto nese položku /XFA, je statický nebo hybridní; soubor, který ukazuje varovnou stránku, je dynamický. Zaznamenávejte, do které kategorie každý příchozí soubor spadl. Oba druhy se později lámou různým způsobem, a tiket o prázdném archivovaném formuláři se zavře za pár sekund, když protokol příjmu už říká „dynamic XFA, converted, 47 fields mapped, 2 warnings"

Převod načteného dokumentu XFA na nativní pole

Převod běží proti dokumentu, který už je v paměti. FlattenLoadedXFA naparsuje šablonu XFA a její datové pakety, rozvrhne formulář a přestaví jej jako pole AcroForm na skutečných stránkách PDF:

var
  Pdf: THotPDF;
  MappedCount, I: Integer;
  Warnings: TStrings;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.LoadFromFile('dynamic_xfa.pdf');
    MappedCount := Pdf.FlattenLoadedXFA(True);   // True = pole zůstanou editovatelná
    Warnings := Pdf.XFAFlattenWarnings;
    for I := 0 to Warnings.Count - 1 do
      Log('XFA flatten warning: ' + Warnings[I]); // nenamapované prvky
    Pdf.SaveLoadedDocument('native_acroform.pdf');
    Log(Format('Mapped %d fields', [MappedCount]));
  finally
    Pdf.Free;
  end;
end;

Návratová hodnota a seznam varování jsou výstup, ne ladicí šum, takže si uchovejte oboje. Převod ze své podstaty ztrácí informace: skriptování XFA, počítaná pole a chování dynamických podformulářů nemají v AcroForm žádný protějšek, a XFAFlattenWarnings pojmenuje každý prvek šablony, který se nenamapoval. Archivujte převedený soubor bez jeho seznamu varování a jednou budete zírat na prázdný box se součtem v archivované kopii bez záznamu, proč tomu tak je. Příznak Editable řídí, zda nová pole zůstanou vyplnitelná. Předejte True, když s formulářem lidé dál pracují, a hodnoty uzamkněte, když je cílem zmrazený záznam

Kontrola převodu je zčásti vizuální, zčásti strukturální, a potřebujete obě poloviny. Strukturální polovina je snadná: potvrďte, že počet polí odpovídá MappedCount. Vizuální polovina je ta, která odhalí skutečné škody. Otevřete zdrojový formulář v desktopovém Acrobatu, pořád jediném prohlížeči, který spouští engine XFA, vedle převedeného souboru v běžné čtečce, a porovnejte hodnoty a rozvržení na alespoň jednom vyplněném vzorku na šablonu. Datum, které engine XFA zobrazil jako 2026-06-11, může v kopii AcroForm přistát jako syrová, neformátovaná hodnota, a to zachytí jen vaše oči

Tok příjmové klasifikace dokumentů XFA v Delphi: soubory vykreslující skutečný obsah mimo Acrobat jsou statické nebo hybridní, zatímco soubory ukazující stranu Please-wait jsou dynamické a musí se převést
Hybridní formuláře se prokážou vykreslením skutečného obsahu v čtečkách mimo Adobe, zatímco dynamické formuláře se prozradí samotnou zástupnou stránkou

Když je vstupem balíček XDP

Ne každá úloha začíná od vyplněného PDF. Někdy dostanete balíček XDP samostatně, exportovaný z nástroje pro návrh formulářů nebo předaný partnerským systémem. ApplyXFAAsAcroForm vynechá krok načtení a aplikuje balíček přímo na aktuální dokument:

Pipeline HotPDF sláčející načtený dynamický dokument XFA do upravitelných polí AcroForm v Delphi, s nemapovanými skripty a počítanými poli vynášenými přes XFAFlattenWarnings
FlattenLoadedXFA parsuje a převádí pakety XDP do upravitelných polí AcroForm a XFAFlattenWarnings zaznamenává každý prvek, který se nepodařilo namapovat
XDPBytes := TFile.ReadAllBytes('benefit-claim.xdp');
MappedCount := Pdf.ApplyXFAAsAcroForm(XDPBytes, True);

Stejná skupina volání funguje i opačným směrem, pro vzácnější případ, kdy XFA musíte vyprodukovat, ne zkonzumovat. AddXFAPacket připojuje jednotlivé pojmenované pakety jako 'xdp' nebo 'config'. SetXFADocument jedním voláním nainstaluje kompletní payload v jednom streamu. ClearXFAPackets smaže registraci, abyste mohli začít znovu, a AddXFASignaturePacket vloží materiál XAdES pro workflow, které podepisují přímo data formuláře XML. Produkovat XFA v roce 2026 je okrajová potřeba, téměř vždy vynucená jedním legacy příjemcem, který odmítá cokoli jiného, ale když ji jmenuje smlouva, tato volání ji drží na úrovni konfigurační volby místo samostatného nástroje

Druhý význam slova „flatten"

Slovo „flatten" plete hodně konverzací, protože pojmenovává úplně jinou operaci: vypálit vzhledy polí AcroForm do content streamu stránky, dokud nezbydou žádné interaktivní objekty. HotPDF pro to dnes nemá žádné API, a je lepší to vědět teď, ne v polovině projektu. Co vám knihovna dává místo toho, je zamykání na úrovni pole ve chvíli jeho vytvoření, podepřené oprávněními dokumentu:

// Zamkne hodnotu při vytvoření pole: textové pole jen pro čtení
Pdf.CurrentPage.AddTextField('CaseNumber', 'BC-2026-0117',
  Rect(50, 700, 220, 720), 0, [ffReadOnly]);

// Pro jistotu dvakrát: omezí vyplňování formuláře v celém dokumentu
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.OwnerPassword := 'records-owner';
Pdf.ProtectOptions := [prPrint, prInformationCopy, prExtractContent];
// oprávnění k vyplňování odepřeno: prFillAnnotations v množině chybí

Buďte si jasní v tom, co vám to koupí a co ne. Pole jen pro čtení je pořád objekt formuláře. Objevuje se v panelu polí prohlížeče, jeho hodnota je čitelná přes API formuláře a nástroj, který soubor přepíše, může příznak jen pro čtení zase vymazat. Příznaky oprávnění zvedají laťku, ale závisí na tom, že se je prohlížeč rozhodne respektovat, což je omezení, které ISO 32000-1 přímo uvádí. Když regulátor trvá na tom, že archivovaný záznam nesmí obsahovat žádné objekty formuláře vůbec, čestná odpověď s HotPDF dnes je dokument přestavět: přečíst hodnoty ven a pak je nakreslit jako obyčejný obsah TextOut na čerstvou stránku, místo přestrojování příznaků jen pro čtení za flattening. Jedna věc, kterou si na cestě přes oprávnění pamatovat, je, že CryptKeyLength musí být nastavené před BeginDoc; zbytek je v našem článku o šifrování AES-256 a oprávněních

Co XFA znamená pro archivní shodu

PDF/A i PDF/X oba XFA rovnou odmítají. Pipeline, která krmí archiv podle ISO 19005, tedy musí nejdřív převést, a pořadí není k diskuzi: načíst, FlattenLoadedXFA, uložit, a teprve pak spustit archivní generování nebo validaci na výsledku AcroForm. Nezacházejte s převodem jako s důkazem shody. Opraví model formuláře a fonty, barvy a metadata nechá přesně tak, jak byly, takže výstup ověřte pomocí veraPDF, než mu budete věřit. Jakmile je formulář na straně AcroForm, jeho chování dostává vlastní sadu ovládacích prvků. Spouštěče JavaScriptu, akce submit a validační skripty jsou probrané v článku HotPDF o polích a akcích AcroForm

API pro registraci, převod a práci s formuláři XFA ukázaná zde jsou součástí HotPDF Delphi Component pro Delphi a C++Builder, jehož dokumentace sleduje sadu funkcí XFA, jak rostla napříč nedávnými vydáními