Dos formularios pueden tener los mismos campos y no comportarse en absoluto igual. Un AcroForm mantiene sus campos como objetos PDF ordinarios situados sobre contenido de página real, por lo que cualquier lector compatible lo dibuja. Un formulario XFA dinámico casi no mantiene nada como PDF: los campos, el diseño e incluso la geometría de la página viven en un paquete XML, y las páginas visibles se producen en el momento de la apertura mediante un motor de diseño que solo Adobe distribuyó de manera masiva. Alimente ese archivo a un visor web, un renderizador de archivo o un extractor de texto y no obtendrá el formulario. Obtendrá una sola página gris que dice "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." Cualquiera que haya procesado papeleo del gobierno o seguros conoce esa página a simple vista
El marcador de posición no es corrupción. Es exactamente lo que el formato especifica que debe ocurrir cuando no hay un procesador XFA presente, y para 2026 eso describe a casi todos los visores que no sean Acrobat para escritorio. Por lo tanto, la medida práctica es convertir el formulario dinámico en un AcroForm simple antes de que llegue a cualquier flujo posterior. HotPDF, la biblioteca PDF de losLab para Delphi y C++Builder, realiza esa conversión en código, reconstruyendo el formulario XML como campos nativos en páginas nativas
Por qué los dos modelos no pueden coexistir
AcroForm se define en ISO 32000-1 §12.7. Cada campo es un objeto PDF con una anotación de widget y una secuencia de apariencia, la página es contenido PDF genuino, y los datos se sitúan encima. XFA invierte eso: el formulario es un documento XML, un paquete XDP almacenado en la entrada /XFA del diccionario de AcroForm, y las páginas PDF de un formulario dinámico contienen el marcador de posición de "Please wait" y nada más, porque el contenido real nunca se serializó como PDF. Un lector procesa un archivo como un modelo o como el otro. Ignore la entrada /XFA y verá el cascarón vacío; hónrela sin un motor XFA y verá la advertencia. ISO 32000-2 terminó el debate al eliminar XFA de PDF 2.0, lo cual es la razón principal por la que "convertir mientras aún podamos" pasó de ser un caso excepcional a una política de recepción rutinaria
Antes de convertir algo, clasifíquelo, porque no todos los archivos XFA muestran el marcador de posición. Los formularios XFA estáticos envían páginas PDF pre-renderizadas junto al XML, por lo que se muestran en todas partes y solo funcionan mal cuando se completan. Los formularios dinámicos envían solo el marcador de posición y son inutilizables hasta que se convierten. En lo que hay que confiar es en el documento, nunca en la extensión o el remitente. Un archivo que renderiza contenido real en un visor que no es de Adobe pero aún contiene una entrada /XFA es estático o híbrido; un archivo que muestra la página de advertencia es dinámico. Registre en qué grupo aterrizó cada archivo de recepción. Los dos tipos se rompen de maneras diferentes más adelante, y un ticket sobre un formulario archivado en blanco se cierra en segundos cuando el registro de recepción ya dice "XFA dinámico, convertido, 47 campos mapeados, 2 advertencias"
Convertir un documento XFA cargado en campos nativos
La conversión se ejecuta sobre un documento ya en memoria. FlattenLoadedXFA analiza la plantilla XFA y sus paquetes de datos, diseña el formulario y lo reconstruye como campos AcroForm en páginas PDF reales:
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;
El valor de retorno y la lista de advertencias son la salida, no ruido de depuración, así que conserve ambos. La conversión pierde información por su naturaleza: el scripting XFA, los campos calculados y el comportamiento dinámico de los subformularios no tienen una contraparte en AcroForm, y XFAFlattenWarnings nombra cada elemento de la plantilla que no se mapeó. Archive el archivo convertido sin su lista de advertencias y algún día se quedará mirando una caja de totales vacía en una copia archivada sin registro del porqué. La bandera Editable controla si los campos nuevos siguen siendo rellenables. Pase True cuando las personas sigan trabajando con el formulario después, y bloquee los valores cuando el objetivo sea un registro congelado
Revisar una conversión es en parte visual y en parte estructural, y usted necesita ambas mitades. La mitad estructural es fácil: confirme que el recuento de campos coincide con MappedCount. La mitad visual es la que atrapa el daño real. Abra el formulario de origen en Acrobat para escritorio, que sigue siendo el único visor que ejecuta el motor XFA, junto al archivo convertido en un lector ordinario, y compare los valores y el diseño en al menos una muestra completada por plantilla. Una fecha que el motor XFA mostraba como 2026-06-11 puede aterrizar en la copia AcroForm como un valor bruto sin formato, y solo sus ojos captarán eso
Cuando la entrada es un paquete XDP
No todos los trabajos comienzan a partir de un PDF completado. A veces recibe el paquete XDP por sí solo, exportado desde una herramienta de diseño de formularios o entregado por un sistema asociado. ApplyXFAAsAcroForm omite el paso de carga y aplica el paquete directamente al documento actual:
XDPBytes := TFile.ReadAllBytes('benefit-claim.xdp');
MappedCount := Pdf.ApplyXFAAsAcroForm(XDPBytes, True);
El mismo grupo de llamadas también funciona en la otra dirección, para el caso más raro en el que tiene que emitir XFA en lugar de consumirlo. AddXFAPacket adjunta paquetes individuales con nombre, como 'xdp' o 'config'. SetXFADocument instala una carga útil completa de una sola secuencia en una llamada. ClearXFAPackets borra el registro para que pueda comenzar de nuevo, y AddXFASignaturePacket incrusta material XAdES para flujos de trabajo que firman los datos del formulario XML directamente. Producir XFA en 2026 es una necesidad de nicho, casi siempre forzada por un consumidor heredado que se niega a cualquier otra cosa, pero cuando un contrato lo nombra, estas llamadas lo reducen a una opción de configuración en lugar de una herramienta separada
El otro significado de "flatten" (acoplar)
La palabra "flatten" (acoplar) hace tropezar muchas conversaciones, porque nombra una segunda operación completamente distinta: integrar las apariencias de los campos AcroForm en la secuencia de contenido de la página hasta que no queden objetos interactivos. HotPDF no tiene una API para eso en la actualidad, y usted querrá saberlo ahora en lugar de a la mitad de un proyecto. Lo que la biblioteca le brinda en su lugar es un bloqueo a nivel de campo cuando se crea el campo, respaldado por permisos de documento:
// 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
Tenga claro lo que eso le aporta y lo que no. Un campo de solo lectura sigue siendo un objeto de formulario. Aparece en el panel de campos del visor, su valor es legible a través de la API de formularios y una herramienta que reescribe el archivo puede volver a borrar la bandera de solo lectura. Las banderas de permiso elevan la barra, pero dependen de que el visor elija respetarlas, una limitación que la norma ISO 32000-1 establece claramente. Cuando un regulador insiste en que un registro archivado no contenga objetos de formulario en absoluto, la respuesta honesta con HotPDF hoy es reconstruir el documento: extraer los valores, y luego dibujarlos como contenido ordinario de TextOut en una página nueva, en lugar de disfrazar las banderas de solo lectura como acoplamiento. Una cosa a recordar en la ruta de los permisos es que CryptKeyLength debe configurarse antes de BeginDoc; el resto está en nuestro artículo sobre permisos y cifrado AES-256
Lo que significa XFA para el cumplimiento de archivos
Tanto PDF/A como PDF/X rechazan XFA rotundamente. Por lo tanto, una canalización que alimenta a un archivo ISO 19005 debe convertirse primero, y el orden no es negociable: cargue, FlattenLoadedXFA, guarde, luego ejecute la generación o validación de archivo en el resultado AcroForm. No trate la conversión como prueba de cumplimiento. Arregla el modelo del formulario y deja las fuentes, el color y los metadatos exactamente como estaban, por lo que debe validar la salida con veraPDF antes de confiar en ella. Una vez que el formulario está en el lado de AcroForm, su comportamiento obtiene su propio conjunto de controles. Los disparadores de JavaScript, las acciones de envío y los scripts de validación están cubiertos en el artículo sobre acciones y campos de AcroForm en HotPDF
Las APIs de registro, conversión y formularios XFA que se muestran aquí se envían con el Componente HotPDF para Delphi y C++Builder, cuya documentación rastrea el conjunto de características XFA a medida que ha crecido a lo largo de los lanzamientos recientes