"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." Si su canalización documental ha ingerido alguna vez formularios gubernamentales o de seguros, ya conoce esta página. No es corrupción; es el marcador de posición que un formulario XFA dinámico muestra a cualquier visor que no tenga procesador XFA, lo que hoy significa casi todos salvo Acrobat de escritorio. Archivos, visores web y extracción automatizada ven todos una página inútil. HotPDF, la biblioteca PDF de losLab para Delphi y C++Builder, afronta esto con una ruta de conversión que transforma formularios XFA en documentos AcroForm nativos que cualquier lector conforme puede mostrar.
Dos modelos de formulario que solo se parecen por fuera
AcroForm, definido en ISO 32000-1 §12.7, almacena cada campo como un objeto PDF con una anotación widget y un appearance stream; la página que se ve es contenido PDF real, y los datos del formulario van encima. XFA adopta el enfoque opuesto: el formulario es un documento XML, un paquete XDP transportado en la entrada /XFA del diccionario AcroForm, y las páginas visibles se generan al abrir por un motor de maquetación XFA. En un formulario XFA dinámico, las páginas PDF del fichero no son más que el marcador "Please wait", porque el contenido real nunca existió como PDF.
En la práctica, los dos modelos son mutuamente excluyentes: un documento se procesa como XFA o como AcroForm, y las herramientas que ignoran la entrada /XFA solo ven la carcasa de marcador. ISO 32000-2 zanjó la discusión al desaprobar XFA por completo en PDF 2.0, por lo que "convertirlo a AcroForm mientras aún podemos" se ha convertido en un requisito estándar de ingesta, no en una rareza.
No todos los formularios XFA muestran el marcador, y por eso las canalizaciones de ingesta deben clasificar antes de convertir. Los formularios XFA estáticos llevan páginas PDF prerenderizadas junto al XML, así que se muestran en todas partes y solo se comportan de forma incoherente cuando se rellenan; los formularios dinámicos llevan solo el marcador y deben convertirse para ser utilizables. El discriminador fiable es el propio documento, no la extensión ni el remitente: un formulario que renderiza contenido real en un visor que no sea Adobe pero sigue llevando una entrada /XFA es estático o híbrido, y uno que muestra la página de advertencia es dinámico. Clasifique cada fichero de entrada en uno de esos grupos y registre la clasificación, porque los dos tipos fallan de forma distinta aguas abajo y un ticket de soporte sobre un formulario archivado en blanco se contesta en segundos cuando el registro de entrada dice "dynamic XFA, converted, 47 fields mapped, 2 warnings".
Aplanar un documento XFA cargado a campos nativos
El punto de entrada de conversión de HotPDF opera sobre un documento cargado. FlattenLoadedXFA analiza los paquetes de plantilla y datos XFA, maqueta el formulario y lo reconstruye como campos AcroForm reales sobre 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;
Trate el valor de retorno y la lista de avisos como parte de la salida, no como ruido de depuración. La conversión es inherentemente con pérdida: scripting XFA, campos calculados y comportamiento dinámico de subformularios no tienen equivalente AcroForm, y XFAFlattenWarnings enumera exactamente qué elementos de plantilla no pudieron mapearse. Una canalización que archiva el fichero convertido sin archivar la lista de avisos acabará enfrentándose a la pregunta "por qué la caja de totales está vacía en la copia archivada" sin respuesta registrada. El parámetro Editable decide si los campos AcroForm resultantes siguen siendo rellenables; pase True cuando los usuarios posteriores sigan trabajando con el formulario, y políticas equivalentes a False cuando el objetivo sea un registro fijo.
La verificación de una conversión es necesariamente visual además de estructural. Abra el formulario de origen en Acrobat de escritorio, el único visor que aún ejecuta el motor XFA, junto al fichero convertido en cualquier visor ordinario, y compare valores de campo y maquetación al menos para un formulario rellenado representativo por plantilla. Las comprobaciones estructurales confirman que el recuento de campos coincide con MappedCount; solo los ojos confirman que una fecha que XFA formateó como 2026-06-11 no llegó a la copia AcroForm como valor bruto sin formato.
Trabajar desde el lado XDP
A veces la entrada no es un PDF poblado, sino el propio paquete XDP, exportado desde una herramienta de diseño de formularios o recibido de un sistema socio. 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);
La misma familia de llamadas también cubre la dirección de autoría, cuando necesita producir XFA en lugar de consumirlo: AddXFAPacket adjunta paquetes con nombre, como 'xdp' o 'config', SetXFADocument instala una carga XFA completa de un solo stream, ClearXFAPackets restablece el registro y AddXFASignaturePacket embebe material de firma XAdES para flujos que firman los datos XML del propio formulario. Generar XFA en 2026 es un requisito de nicho, normalmente impulsado por un consumidor heredado, pero cuando un contrato lo exige estas llamadas lo mantienen como detalle de configuración en lugar de herramienta separada.
El otro aplanado: contenido AcroForm, dicho con honestidad
"Flatten" tiene un segundo significado que causa confusión recurrente: quemar las apariencias de campos AcroForm en el stream de contenido de página para que no quede ningún objeto interactivo. HotPDF no proporciona actualmente una API para esa operación, y es mejor planificar alrededor de ese hecho que descubrirlo a mitad de proyecto. Lo que sí ofrece la biblioteca es bloqueo a nivel de campo en el momento de creación, más 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
Entienda qué consigue esto y qué no. Un campo de solo lectura sigue existiendo como objeto de formulario: aparece en el panel de campos de un visor, su valor se puede extraer mediante la API de formularios y una herramienta que reescribe el fichero puede borrar la marca. Las marcas de permiso elevan más la barrera, pero descansan en la cooperación del visor, como reconoce el propio ISO 32000-1. Si un regulador exige que un registro archivado no contenga ningún objeto de formulario, la respuesta de ingeniería honesta con HotPDF hoy es regenerar el documento, renderizar los valores de campo como contenido ordinario TextOut en un documento nuevo usando los valores cargados, no fingir que las marcas de solo lectura son aplanado. Recuerde que CryptKeyLength debe establecerse antes de BeginDoc cuando tome la ruta de permisos; los detalles están en nuestro artículo sobre cifrado AES-256 y permisos.
Consecuencias de archivo: XFA y los estándares de conformidad
PDF/A y PDF/X rechazan XFA de plano, así que una canalización de ingesta que alimente un archivo ISO 19005 debe convertir antes de validar, y el orden de operaciones queda fijado: cargar, FlattenLoadedXFA, guardar y después ejecutar la generación o validación de archivo sobre el resultado AcroForm. Valide la salida convertida con veraPDF en lugar de asumir que la conversión implica conformidad; la conversión arregla el modelo de formulario, no fuentes, color ni metadatos. El comportamiento de campo en el lado AcroForm, disparadores JavaScript, acciones de envío y scripts de validación, tiene su propia caja de herramientas, cubierta en el artículo sobre campos y acciones AcroForm en HotPDF.
FAQ
¿Por qué mi formulario PDF muestra solo una página "Please wait"?
Es un formulario XFA dinámico, y su visor no tiene procesador XFA. El contenido PDF visible es solo un marcador; convierta el documento con FlattenLoadedXFA para obtener páginas y campos que todo visor pueda renderizar.
¿FlattenLoadedXFA conserva cálculos y scripts?
No. El scripting XFA y la lógica de maquetación dinámica no se pueden convertir a AcroForm; los valores calculados presentes en los datos del formulario se trasladan como valores estáticos, y XFAFlattenWarnings lista cada elemento que no pudo mapearse. Revise esa lista antes de confiar en la salida.
¿Puede HotPDF convertir un formulario en completamente no interactivo?
No mediante un aplanado de una sola llamada: no hay API de aplanado de contenido AcroForm. Combine campos ffReadOnly con restricciones de permisos para resistencia a manipulación, o regenere el documento con los valores dibujados como texto plano cuando cero objetos de formulario sea un requisito duro.
Referencia de producto
Las API de registro, conversión y formularios XFA de este artículo forman parte de HotPDF Component para Delphi y C++Builder; su documentación sigue la evolución del conjunto de funciones XFA a través de versiones recientes.