El componente PDFium Component para Delphi y Lazarus intercambia datos de formularios y anotaciones a través de XFDF, el formato de intercambio XML definido por la norma ISO 19444-1. TPdf.ExportXFDF serializa cada valor de campo de formulario y cada anotación compatible en el documento cargado a un archivo XFDF o a un TStream; TPdf.ImportXFDF lee de vuelta un documento XFDF, recreando las anotaciones en sus páginas y aplicando los valores de los campos. Ese viaje de ida y vuelta cubre dos flujos de trabajo que toda aplicación de documentos necesita con el tiempo: un revisor realiza anotaciones en un PDF en Acrobat y le envía los comentarios para combinarlos, o una regla de cumplimiento exige que los datos del formulario residan en un archivo independiente, diferenciable y auditable, en lugar de estar integrados en el propio PDF
¿Admite PDFium la importación y exportación de XFDF?
La biblioteca PDFium en sí misma no lo admite. La API nativa de C no tiene funciones XFDF o FDF en absoluto; nada en sus cabeceras públicas lee o escribe ninguno de los formatos, por lo que ninguna envoltura (wrapper) resolverá el problema. Por lo tanto, PDFium Component implementa todo el motor XFDF en Pascal, en una unidad dedicada que construye y analiza el XML directamente sobre el modelo de datos de anotaciones y campos de formulario de TPdf existente. El generador escribe el XML manualmente y el lector es un analizador de máquina de estados escrito a mano, por lo que esta característica no añade dependencias de Delphi XMLDoc ni de las unidades DOM de FPC, y se comporta de manera idéntica en Delphi y Lazarus
Esa elección de diseño es importante cuando evalúa alternativas. Si ha estado llamando a funciones directas FPDF_* desde Pascal, XFDF representa un muro: la capacidad simplemente no existe en la DLL. El componente supera ese muro tratando a XFDF como un problema puro de serialización: recopila los valores de los campos y los registros de anotaciones que el wrapper ya sabe leer, los escribe como XML estándar y realiza el proceso inverso en la importación
¿Qué contiene un archivo XFDF?
La norma ISO 19444-1 define XFDF como la representación XML de FDF, y su contenido se divide en dos bloques principales. El elemento <fields> contiene nombres de campos de formulario jerárquicos y sus valores (todo lo que un usuario escribió, seleccionó o marcó en un AcroForm). El elemento <annots> contiene las anotaciones: TPdf.ExportXFDF emite 18 subtipos: texto, resaltado, subrayado, tachado, ondulado, línea, círculo, cuadrado, acento circunflejo (caret), polígono, polilínea, sello, tinta, texto libre, archivo adjunto, sonido, enlace y redacción. Las anotaciones Widget están ausentes deliberadamente de <annots> debido a que sus datos ya viajan en <fields>, y los subtipos internos del visor como Popup no forman parte del vocabulario de XFDF
Para que el viaje de ida y vuelta sea fiel, el registro TPdfAnnotation se amplió con los metadatos que XFDF espera: Name (el identificador único NM), Subject, ModificationDate, CreationDate, Icon, Opacity, extremos de línea, vértices de polígonos y polilíneas, y rutas de trazo de tinta. Cada nuevo campo se asocia con un indicador booleano Has*, por lo que el código que construía anotaciones en versiones anteriores se sigue compilando y produciendo los mismos diccionarios: un campo no establecido nunca se escribe. Si ya crea marcas mediante programación, el mismo registro que utiliza para anotaciones de marcas de texto con puntos cuadrangulares (quad points) ahora contiene todo lo que XFDF necesita
¿Cómo exportar datos de formularios y anotaciones a XFDF?
Una llamada procesa todo el documento. Cargue el PDF con el llenado de formularios habilitado, llame a ExportXFDF y el componente recorrerá cada página, recopilará los valores de los campos y las anotaciones, y escribirá el XML. El valor devuelto es la cantidad de bytes UTF-8 escritos, lo que representa una comprobación básica útil en los registros
var
Pdf: TPdf;
Bytes: Integer;
begin
Pdf := TPdf.Create(Self);
Pdf.FormFill := True; // needed so field values are live
Pdf.FileName := 'expense-report.pdf';
Pdf.Active := True;
Bytes := Pdf.ExportXFDF('expense-report.xfdf');
ShowMessage(Format('%d bytes of XFDF written', [Bytes]));
end;
Ambas direcciones tienen una sobrecarga de TStream, por lo que nada obliga a utilizar un archivo temporal en disco. Exportar a un TMemoryStream es la forma natural cuando el XFDF se dirige a una respuesta HTTP, a un objeto binario (blob) de base de datos o a una entrada de archivo firmado
var
Buffer: TMemoryStream;
begin
Buffer := TMemoryStream.Create;
try
Pdf.ExportXFDF(Buffer); // same XML, no file involved
Buffer.Position := 0;
// hand the stream to a web response, blob column, or zip entry
finally
Buffer.Free;
end;
end;
¿Cómo combina ImportXFDF los comentarios de vuelta en el documento?
El lado de la importación es donde se cierra el flujo de trabajo del revisor. Un colega realiza anotaciones en el contrato en Acrobat, exporta los comentarios como XFDF y le envía unos pocos kilobytes de XML en lugar de una segunda copia del PDF. TPdf.ImportXFDF analiza ese archivo, crea cada anotación en la página que especifica su atributo page y escribe los valores de los campos en las anotaciones widget correspondientes. La función devuelve la suma de campos más anotaciones aplicadas, por lo que la interfaz de usuario puede confirmar exactamente qué cantidad de datos llegó
El analizador es un escáner de etiquetas escrito a mano, diseñado para la tolerancia en lugar del rigor: los elementos desconocidos se omiten, las instrucciones de procesamiento, las declaraciones DOCTYPE y los comentarios se ignoran, los nombres de banderas no reconocidos se descartan y los valores de atributos se procesan a través de todo el conjunto de referencias de caracteres numéricos y entidades XML, incluidas las parejas sustitutas de UTF-16. El XFDF producido por Acrobat, por un visor web o por otra herramienta se combina sin inconvenientes. Una vez que las anotaciones están en el documento, el ciclo de revisión continúa con los mecanismos de respuesta y estado descritos en la construcción de un flujo de trabajo de revisión de anotaciones con PDFium Component, y los valores de campo importados participan en la lógica normal de orden de tabulación analizada en la navegación por campos de formulario
¿Por qué los separadores decimales son importantes para XFDF?
Cada anotación en XFDF se posiciona mediante cadenas de coordenadas (rect="70.5,540,200,560" y similares) y la norma ISO 19444-1 exige el punto como separador decimal. El formato de punto flotante predeterminado de Delphi sigue la configuración regional de Windows, por lo que en un sistema alemán o francés un simple FloatToStr convierte 70.5 en 70,5, lo que corrompe una lista de coordenadas separada por comas en datos inválidos que otros procesadores rechazan o leen incorrectamente. PDFium Component normaliza cada número que escribe: el separador decimal de la configuración regional se reescribe como un punto y se recortan los ceros a la derecha, por lo que el archivo exportado es idéntico a nivel de bytes tanto si se produjo en una máquina en-US como en una de-DE. Si alguna vez ha depurado una herramienta PDF que funcionaba en la oficina y fallaba en el sitio de un cliente europeo, se ha encontrado con esta misma categoría de error; vale la pena saber que el componente lo resuelve por usted
¿Cuáles son los límites del viaje de ida y vuelta?
Vale la pena declarar claramente dos límites. En primer lugar, XFDF transporta datos de anotación, no apariencias renderizadas (los flujos de apariencia no forman parte del formato, por lo que el visor receptor regenera el aspecto de cada anotación a partir de sus propiedades). Un resaltado o un cuadrado se renderizará correctamente en todas partes; un sello con una apariencia personalizada recurrirá a lo que el visor de destino dibuje para ese nombre de sello. En segundo lugar, la API de PDFium subyacente tiene métodos de escritura (setters) para cadenas de texto, pero ninguno para números de anotación o geometría de ruta, por lo que la opacidad (Opacity), los extremos de línea, los vértices y los trazos de tinta son solo de exportación: el componente los conserva fielmente al escribir XFDF, pero no puede reescribirlos en un PDF durante la importación. Los valores de los campos, contenidos, colores, rectángulos, quad points, fechas y metadatos de identidad realizan el viaje de ida y vuelta completo en ambas direcciones
Para un inicio práctico, la muestra XfdfLab se distribuye en los conjuntos de demostración de Delphi, C++Builder y Lazarus, y conecta ambas llamadas a botones sobre cualquier PDF que abra. El soporte XFDF está incluido en la versión actual de PDFium Component, junto con las API de anotaciones y formularios sobre las que se construye