Article technique

Aplatissement (Flattening) de XFA vers AcroForm dans Delphi à l'aide de HotPDF

Deux formulaires peuvent porter les mêmes champs et ne se comporter en rien de la même manière. Un AcroForm conserve ses champs en tant qu'objets PDF ordinaires reposant sur le vrai contenu de la page, de sorte que tout lecteur conforme le dessine. Un formulaire XFA dynamique ne conserve presque rien sous forme de PDF : les champs, la mise en page, même la géométrie de la page vivent dans un package XML, et les pages visibles sont produites au moment de l'ouverture par un moteur de mise en page que seul Adobe a jamais distribué à grande échelle. Transmettez ce fichier à un visualiseur web, à un moteur de rendu d'archives ou à un extracteur de texte et vous n'obtenez pas le formulaire. Vous obtenez une seule page grise indiquant : "Veuillez patienter... Si ce message n'est finalement pas remplacé par le contenu approprié du document, il se peut que votre lecteur PDF ne soit pas en mesure d'afficher ce type de document." Quiconque a assimilé de la paperasse gouvernementale ou d'assurance reconnaît cette page à vue

L'espace réservé (placeholder) n'est pas une corruption. C'est exactement ce que le format spécifie de se produire lorsqu'aucun processeur XFA n'est présent, et en 2026, cela décrit presque tous les visualiseurs en dehors d'Acrobat pour ordinateur de bureau. Ainsi, la mesure pratique consiste à convertir le formulaire dynamique en un AcroForm simple avant qu'il n'atteigne quoi que ce soit en aval. HotPDF, la bibliothèque PDF losLab pour Delphi et C++Builder, effectue cette conversion dans le code, en reconstruisant le formulaire XML sous forme de champs natifs sur des pages natives

Pourquoi les deux modèles ne peuvent pas coexister

L'AcroForm est défini dans la norme ISO 32000-1 §12.7. Chaque champ est un objet PDF doté d'une annotation de widget et d'un flux d'apparence, la page est un véritable contenu PDF et les données sont superposées. Le XFA inverse cela : le formulaire est un document XML, un package XDP stocké dans l'entrée /XFA du dictionnaire AcroForm, et les pages PDF d'un formulaire dynamique contiennent l'espace réservé "Veuillez patienter" et rien d'autre, car le vrai contenu n'a jamais été sérialisé en tant que PDF. Un lecteur traite un fichier selon un modèle ou l'autre. Ignorez l'entrée /XFA et vous voyez la coquille vide ; honorez-la sans moteur XFA et vous voyez l'avertissement. La norme ISO 32000-2 a mis fin au débat en supprimant le XFA du PDF 2.0, ce qui est la principale raison pour laquelle l'instruction "convertissons pendant que nous le pouvons encore" est passée d'un cas particulier à une politique de prise en charge (intake) de routine

Avant de convertir quoi que ce soit, classez-le, car tous les fichiers XFA ne montrent pas l'espace réservé. Les formulaires XFA statiques livrent des pages PDF pré-rendues à côté du XML, de sorte qu'elles s'affichent partout et ne se comportent mal que lorsqu'elles sont remplies. Les formulaires dynamiques livrent l'espace réservé seul et sont inutilisables jusqu'à leur conversion. La chose à laquelle se fier est le document, jamais l'extension ou l'expéditeur. Un fichier qui affiche un contenu réel dans un visualiseur non-Adobe tout en portant toujours une entrée /XFA est statique ou hybride ; un fichier qui montre la page d'avertissement est dynamique. Enregistrez dans quel bac (bucket) chaque fichier entrant a atterri. Les deux types échouent de manières différentes plus tard, et un ticket (ticket d'assistance) concernant un formulaire archivé vierge est clôturé en quelques secondes lorsque le journal de prise en charge indique déjà : "XFA dynamique, converti, 47 champs mappés, 2 avertissements"

Convertir un document XFA chargé en champs natifs

La conversion s'exécute sur un document déjà en mémoire. FlattenLoadedXFA analyse le modèle XFA et ses paquets de données, met le formulaire en page et le reconstruit en tant que champs AcroForm sur de vraies pages 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 = les champs restent modifiables
    Warnings := Pdf.XFAFlattenWarnings;
    for I := 0 to Warnings.Count - 1 do
      Log('XFA flatten warning: ' + Warnings[I]); // éléments non mappés
    Pdf.SaveLoadedDocument('native_acroform.pdf');
    Log(Format('Mapped %d fields', [MappedCount]));
  finally
    Pdf.Free;
  end;
end;

La valeur de retour et la liste des avertissements sont des données de sortie utiles (output), et non du bruit de débogage, alors conservez les deux. La conversion perd des informations par nature : les scripts XFA, les champs calculés et le comportement des sous-formulaires dynamiques n'ont pas d'équivalent AcroForm, et XFAFlattenWarnings nomme chaque élément de modèle qui n'a pas été mappé. Archivez le fichier converti sans sa liste d'avertissements et, un jour, vous contemplerez une boîte de totaux vide dans une copie archivée sans aucune trace de la raison. L'indicateur Editable contrôle si les nouveaux champs restent remplissables. Passez True lorsque des personnes continuent à travailler avec le formulaire par la suite, et verrouillez les valeurs (lock down) lorsque l'objectif est un enregistrement figé (frozen record)

La vérification d'une conversion est en partie visuelle et en partie structurelle, et vous avez besoin des deux moitiés. La moitié structurelle est simple : confirmez que le nombre de champs correspond à MappedCount. La moitié visuelle est celle qui détecte les vrais dégâts. Ouvrez le formulaire source dans Acrobat pour ordinateur de bureau, qui reste le seul visualiseur exécutant le moteur XFA, à côté du fichier converti dans un lecteur ordinaire, et comparez les valeurs et la mise en page sur au moins un échantillon rempli par modèle. Une date que le moteur XFA affichait sous la forme 2026-06-11 peut atterrir dans la copie AcroForm comme une valeur brute, non formatée, et seuls vos yeux le remarqueront

Lorsque l'entrée est un package XDP

Toutes les tâches ne démarrent pas à partir d'un PDF pré-rempli. Parfois, vous recevez le package XDP seul, exporté à partir d'un outil de conception de formulaires ou transmis par un système partenaire. ApplyXFAAsAcroForm supprime l'étape de chargement et applique le package directement au document en cours :

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

Le même groupe d'appels fonctionne également dans l'autre sens, pour le cas plus rare où vous devez émettre du XFA plutôt que de le consommer. AddXFAPacket attache des paquets nommés individuels tels que 'xdp' ou 'config'. SetXFADocument installe une charge utile complète (single-stream) en un seul appel. ClearXFAPackets efface l'enregistrement pour que vous puissiez recommencer, et AddXFASignaturePacket intègre le matériel XAdES pour les flux de travail qui signent directement les données du formulaire XML. Produire du XFA en 2026 est un besoin de niche, presque toujours imposé par un ancien consommateur (legacy consumer) qui refuse tout le reste, mais lorsqu'un contrat l'exige, ces appels permettent de maintenir cela à l'état de choix de configuration au lieu d'un outil distinct

L'autre signification de "aplatir" (flatten)

Le mot "flatten" (aplatir) fait trébucher beaucoup de conversations, car il désigne une deuxième opération tout à fait différente : graver (burning) les apparences des champs AcroForm dans le flux de contenu de la page jusqu'à ce qu'il ne reste plus aucun objet interactif. HotPDF n'a pas d'API pour cela aujourd'hui, et vous voulez le savoir maintenant plutôt qu'à mi-chemin d'un projet. Ce que la bibliothèque vous offre à la place, c'est le verrouillage au niveau du champ lorsque le champ est créé, soutenu par les autorisations du document :

// Verrouille la valeur à la création du champ : champ de texte en lecture seule
Pdf.CurrentPage.AddTextField('CaseNumber', 'BC-2026-0117',
  Rect(50, 700, 220, 720), 0, [ffReadOnly]);

// Ceinture et bretelles : restreint le remplissage de formulaire sur tout le document
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.OwnerPassword := 'records-owner';
Pdf.ProtectOptions := [prPrint, prInformationCopy, prExtractContent];
// permission de remplissage refusée : prFillAnnotations est absent de l'ensemble

Soyez clair sur ce que cela vous apporte et ce que cela ne fait pas. Un champ en lecture seule est toujours un objet de formulaire. Il apparaît dans le panneau des champs du visualiseur, sa valeur est lisible via l'API du formulaire et un outil qui réécrit le fichier peut effacer à nouveau l'indicateur (flag) de lecture seule. Les indicateurs d'autorisation placent la barre plus haut mais dépendent du fait que le visualiseur choisisse de les respecter, une limitation que la norme ISO 32000-1 énonce clairement. Lorsqu'un organisme de réglementation insiste pour qu'un dossier archivé ne contienne aucun objet de formulaire, la réponse honnête avec HotPDF aujourd'hui est de reconstruire le document : lire les valeurs, puis les dessiner comme un contenu ordinaire avec TextOut sur une nouvelle page, au lieu de déguiser (dressing up) des indicateurs en lecture seule en aplatissement (flattening). Une chose à retenir sur la voie des autorisations est que CryptKeyLength doit être défini avant BeginDoc ; le reste se trouve dans notre article sur le chiffrement AES-256 et les autorisations

Ce que signifie le XFA pour la conformité de l'archivage

Les formats PDF/A et PDF/X rejettent tous deux catégoriquement le XFA. Un pipeline alimentant une archive ISO 19005 doit donc d'abord procéder à la conversion, et l'ordre n'est pas négociable : charger, FlattenLoadedXFA, enregistrer, puis exécuter la génération ou la validation de l'archivage sur le résultat AcroForm. Ne traitez pas la conversion comme une preuve de conformité. Elle corrige le modèle de formulaire et laisse les polices, la couleur et les métadonnées exactement telles qu'elles étaient, validez donc la sortie avec veraPDF avant de lui faire confiance. Une fois le formulaire du côté AcroForm, son comportement obtient son propre ensemble de contrôles. Les déclencheurs JavaScript, les actions de soumission et les scripts de validation sont couverts dans l'article sur les champs et actions AcroForm de HotPDF

Les API d'enregistrement XFA, de conversion et de formulaire présentées ici sont livrées avec le Composant HotPDF pour Delphi et C++Builder, dont la documentation suit l'ensemble des fonctionnalités XFA au fur et à mesure de sa croissance au cours des dernières versions