Technischer Artikel

XFA-zu-AcroForm-Flattening in Delphi mit HotPDF

„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.“ Wenn Ihre Dokumentpipeline jemals Behörden- oder Versicherungsformulare aufgenommen hat, kennen Sie diese Seite. Das ist keine Beschädigung, sondern der Platzhalter, den ein dynamisches XFA-Formular jedem Viewer zeigt, der keinen XFA-Prozessor besitzt, was heute nahezu jeden Viewer außer Desktop Acrobat betrifft. Archive, Webviewer und automatisierte Extraktion sehen alle nur eine nutzlose Seite. HotPDF, die PDF-Bibliothek von losLab für Delphi und C++Builder, adressiert das mit einem Konvertierungspfad, der XFA-Formulare in native AcroForm-Dokumente umwandelt, die jeder konforme Reader anzeigen kann.

Zwei Formularmodelle, die nur ähnlich aussehen

AcroForm, definiert in ISO 32000-1 §12.7, speichert jedes Feld als PDF-Objekt mit Widget-Annotation und Appearance Stream; die sichtbare Seite ist echter PDF-Inhalt, und die Formulardaten liegen darüber. XFA geht den entgegengesetzten Weg: Das Formular ist ein XML-Dokument, ein XDP-Paket im /XFA-Eintrag des AcroForm-Dictionary, und die sichtbaren Seiten werden beim Öffnen von einer XFA-Layout-Engine erzeugt. In einem dynamischen XFA-Formular sind die PDF-Seiten in der Datei nichts als der „Please wait“-Platzhalter, weil der eigentliche Inhalt nie als PDF existierte.

Die beiden Modelle schließen sich praktisch aus: Ein Dokument wird entweder als XFA oder als AcroForm verarbeitet, und Werkzeuge, die den /XFA-Eintrag ignorieren, sehen nur die Platzhalterhülle. ISO 32000-2 hat die Debatte beendet, indem XFA in PDF 2.0 vollständig als veraltet eingestuft wurde. Deshalb ist „in AcroForm konvertieren, solange wir es noch können“ zu einer normalen Eingangsanforderung geworden, nicht zu einer exotischen.

Nicht jedes XFA-Formular zeigt den Platzhalter, weshalb Eingangspipelines klassifizieren sollten, bevor sie konvertieren. Statische XFA-Formulare tragen vorgerenderte PDF-Seiten neben dem XML, sodass sie überall angezeigt werden und sich lediglich beim Ausfüllen inkonsistent verhalten; dynamische Formulare tragen nur den Platzhalter und müssen konvertiert werden, um überhaupt nutzbar zu sein. Der zuverlässige Unterscheider ist das Dokument selbst, nicht Dateiendung oder Absender: Ein Formular, das in einem Nicht-Adobe-Viewer echten Inhalt rendert und dennoch einen /XFA-Eintrag trägt, ist statisch oder hybrid, und eines, das die Warnseite zeigt, ist dynamisch. Klassifizieren Sie jede Eingangsdatei in eine dieser Kategorien und protokollieren Sie die Klassifikation, denn die beiden Arten scheitern nachgelagert unterschiedlich, und ein Supportticket über ein leeres archiviertes Formular ist in Sekunden beantwortet, wenn der Eingangssatz „dynamic XFA, converted, 47 fields mapped, 2 warnings“ sagt.

Ein geladenes XFA-Dokument in native Felder flattenen

HotPDFs Konvertierungseinstieg arbeitet auf einem geladenen Dokument. FlattenLoadedXFA parst die XFA-Template- und Datenpakete, layoutet das Formular und baut es als echte AcroForm-Felder auf echten PDF-Seiten neu auf:

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;

Behandeln Sie Rückgabewert und Warnliste als Teil der Ausgabe, nicht als Debug-Rauschen. Die Konvertierung ist inhärent verlustbehaftet: XFA-Scripting, berechnete Felder und dynamisches Subform-Verhalten haben kein AcroForm-Äquivalent, und XFAFlattenWarnings zählt genau auf, welche Template-Elemente nicht abgebildet werden konnten. Eine Pipeline, die die konvertierte Datei archiviert, ohne die Warnliste zu archivieren, wird irgendwann vor der Frage stehen, warum das Summenfeld in der Archivkopie leer ist, ohne eine aufgezeichnete Antwort zu besitzen. Der Parameter Editable entscheidet, ob die resultierenden AcroForm-Felder ausfüllbar bleiben; übergeben Sie True, wenn nachgelagert weiter mit dem Formular gearbeitet wird, und False-äquivalente Richtlinien, wenn das Ziel ein fester Datensatz ist.

Die Verifikation einer Konvertierung ist zwangsläufig visuell und strukturell. Öffnen Sie das Quellformular in Desktop Acrobat, dem einen Viewer, der die XFA-Engine noch ausführt, neben der konvertierten Datei in einem gewöhnlichen Viewer, und vergleichen Sie Feldwerte und Layout für mindestens ein repräsentativ ausgefülltes Formular pro Template. Strukturprüfungen bestätigen, dass die Feldanzahl zu MappedCount passt; nur Augen bestätigen, dass ein Datum, das XFA als 2026-06-11 formatiert hat, in der AcroForm-Kopie nicht als roher unformatierter Wert angekommen ist.

Vom XDP-Paket aus arbeiten

Manchmal ist die Eingabe kein ausgefülltes PDF, sondern das XDP-Paket selbst, exportiert aus einem Formularentwurfswerkzeug oder von einem Partnersystem empfangen. ApplyXFAAsAcroForm überspringt den Ladeschritt und wendet das Paket direkt auf das aktuelle Dokument an:

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

Dieselbe Aufruffamilie deckt auch die Authoring-Richtung ab, wenn Sie XFA erzeugen statt konsumieren müssen: AddXFAPacket hängt einzelne benannte Pakete wie 'xdp' oder 'config' an, SetXFADocument installiert eine vollständige XFA-Payload als einzelnen Stream, ClearXFAPackets setzt die Registrierung zurück, und AddXFASignaturePacket bettet XAdES-Signaturmaterial für Workflows ein, die die XML-Formulardaten selbst signieren. XFA im Jahr 2026 zu erzeugen ist eine Nischenanforderung, meistens von einem Legacy-Verbraucher erzwungen, aber wenn ein Vertrag es verlangt, halten diese Aufrufe es als Konfigurationsdetail statt als separates Werkzeug.

Das andere Flattening: AcroForm-Inhalte ehrlich benennen

„Flatten“ hat eine zweite Bedeutung, die regelmäßig Verwirrung verursacht: AcroForm-Feld-Appearances in den Seiten-Content-Stream einbrennen, sodass keine interaktiven Objekte übrig bleiben. HotPDF bietet dafür derzeit keine API, und es ist besser, diese Tatsache einzuplanen, als sie mitten im Projekt zu entdecken. Was die Bibliothek anbietet, sind Feldsperren bei der Erstellung plus Dokumentberechtigungen:

// 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

Verstehen Sie genau, was das erreicht und was nicht. Ein schreibgeschütztes Feld existiert weiterhin als Formularobjekt: Es erscheint im Feldbereich eines Viewers, sein Wert ist über die Formular-API extrahierbar, und ein Werkzeug, das die Datei neu schreibt, kann das Flag entfernen. Berechtigungsflags erhöhen die Hürde weiter, beruhen aber auf Viewer-Kooperation, wie ISO 32000-1 selbst anerkennt. Wenn ein Regulator verlangt, dass ein archivierter Datensatz keinerlei Formularobjekte enthält, lautet die ehrliche Engineering-Antwort mit HotPDF heute: das Dokument neu erzeugen und die Feldwerte als normalen TextOut-Inhalt auf ein frisches Dokument zeichnen, indem die geladenen Werte verwendet werden, statt Schreibschutz-Flags als Flattening auszugeben. Denken Sie daran, dass CryptKeyLength vor BeginDoc gesetzt sein muss, wenn Sie den Berechtigungsweg wählen; die Details stehen in unserem Artikel zu AES-256-Verschlüsselung und Berechtigungen.

Archivfolgen: XFA und die Compliance-Standards

PDF/A und PDF/X lehnen XFA vollständig ab, daher muss eine Eingangspipeline für ein ISO-19005-Archiv vor der Validierung konvertieren, und die Reihenfolge ist fix: laden, FlattenLoadedXFA, speichern, dann die Archivgenerierung oder Validierung auf dem AcroForm-Ergebnis ausführen. Validieren Sie die konvertierte Ausgabe mit veraPDF, statt anzunehmen, die Konvertierung bedeute Compliance; die Konvertierung repariert das Formularmodell, nicht Schriften, Farbe oder Metadaten. Feldverhalten auf der AcroForm-Seite, JavaScript-Trigger, Submit-Actions und Validierungsskripte, hat ein eigenes Werkzeugset, beschrieben in dem Artikel zu HotPDF AcroForm-Feldern und Actions.

FAQ

Warum zeigt mein PDF-Formular nur eine „Please wait“-Seite?

Es ist ein dynamisches XFA-Formular, und Ihr Viewer hat keinen XFA-Prozessor. Der sichtbare PDF-Inhalt ist nur ein Platzhalter; konvertieren Sie das Dokument mit FlattenLoadedXFA, um Seiten und Felder zu erhalten, die jeder Viewer rendern kann.

Erhält FlattenLoadedXFA Berechnungen und Skripte?

Nein. XFA-Scripting und dynamische Layoutlogik lassen sich nicht in AcroForm konvertieren; berechnete Werte, die in den Formulardaten vorhanden sind, werden als statische Werte übernommen, und XFAFlattenWarnings listet jedes Element auf, das nicht abgebildet werden konnte. Prüfen Sie diese Liste, bevor Sie der Ausgabe vertrauen.

Kann HotPDF ein Formular vollständig nichtinteraktiv machen?

Nicht mit einem Ein-Aufruf-Flattening: Es gibt keine API für AcroForm-Content-Flattening. Kombinieren Sie ffReadOnly-Felder mit Berechtigungsbeschränkungen für Manipulationsschutz, oder erzeugen Sie das Dokument mit als Klartext gezeichneten Werten neu, wenn null Formularobjekte eine harte Anforderung sind.

Produktreferenz

Die XFA-Registrierungs-, Konvertierungs- und Formular-APIs in diesem Artikel sind Teil der HotPDF Component für Delphi und C++Builder; die Dokumentation verfolgt den XFA-Funktionsumfang, wie er in den letzten Releases gewachsen ist.