losLab PDF Library mueve datos de formularios hacia adentro y hacia afuera de un PDF de tres maneras diferentes: FDF y XFDF para valores de campos de AcroForm, esos mismos dos formatos para comentarios de anotaciones, y un paquete XDP de XFA completo escrito directamente en el formulario. ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF y SetXFAFromString son los puntos de entrada, y cada uno de ellos tiene una variante de archivo y una variante de cadena de caracteres
La razón por la que existen tantos métodos es que los datos de formularios PDF no son una sola cosa. Un AcroForm completo tiene valores de campos, también puede contener comentarios de revisión, y un formulario XFA heredado incrusta una descripción de aplicación XML completa que no tiene nada que ver con ninguno de los dos anteriores. losLab PDF Library mantiene estas tres tareas en API separadas a propósito, porque fusionarlas forzaría el modelo de datos incorrecto en al menos dos de ellas. Decidir qué familia necesita es la primera opción de diseño, y usualmente se resuelve en el momento en que usted sabe qué es lo que consume el sistema receptor del otro lado
¿Cuál es la diferencia entre los datos de formulario FDF, XFDF y XFA?
FDF y XFDF contienen la misma información en dos sintaxis diferentes, y XFA es un mundo aparte. FDF es un documento miniatura con sintaxis de PDF (ISO 32000-2 §12.7.8): un arreglo /Fields de diccionarios << /T (nombre) /V (valor) >>, con cadenas de caracteres escapadas exactamente de la misma manera en que se escapan las cadenas de caracteres literales dentro de un PDF. XFDF es la forma XML de los mismos datos (ISO 19444), un árbol <fields> que Acrobat y la mayoría de los motores de formularios leen y escriben de forma nativa. XFA no es ninguno de los dos: es una plantilla de XML Forms Architecture más sus datos, almacenados como un XML Data Package (XDP) que el PDF referencia desde /AcroForm/XFA. Elija FDF o XFDF cuando interactúe con valores de campos, y recurra a XFA solo cuando esté manteniendo un documento que fue creado originalmente como un formulario XFA
Dentro de FDF y XFDF, losLab PDF Library traza una segunda línea: valores de campos frente a comentarios de anotaciones. La familia de datos de formulario (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) lee y escribe el subárbol /Fields y no toca nada más. La familia de anotaciones (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) lee y escribe el subárbol /Annots en su lugar, que es lo que Acrobat define como Exportar comentarios. Ambos nunca se superponen, por lo que exportar valores de campos no arrastrará notas de revisión perdidas, e importar comentarios no alterará los valores que un usuario ya haya ingresado. Lo que hace un control (widget) cuando se hace clic en él o se recalcula es un tercer tema, cubierto en la nota complementaria sobre acciones de formulario interactivas y JavaScript
¿Cómo se llena un formulario PDF desde FDF o XFDF en Delphi?
Cargue el documento, llame a un método de importación y guarde. ImportFormDataFromXFDF e ImportFormDataFromFDF analizan los datos de formulario entrantes, asocian cada entrada a un campo de AcroForm por su nombre completamente calificado, establecen el valor y devuelven el conteo de campos realmente actualizados. Ambos métodos solo actualizan los campos que ya existen en el PDF de destino; ninguno crea un campo para un nombre que el formulario no defina, lo cual evita que un archivo de datos perdido o malicioso amplíe silenciosamente su formulario
var
Lib: TPDFlib;
FieldsSet: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('application-blank.pdf', '');
// XFDF produced by a case-management system, already UTF-8 on disk
FieldsSet := Lib.ImportFormDataFromXFDF('applicant-1042.xfdf');
if FieldsSet > 0 then
Lib.SaveToFile('application-filled.pdf');
finally
Lib.Free;
end;
end;
Dos detalles deciden si los datos complejos sobreviven al viaje. El primero es el escapado: FDF almacena valores como cadenas de caracteres literales de PDF, por lo que un valor que contenga un paréntesis, una barra invertida o un byte no imprimible llega envuelto en el escapado octal definido en ISO 32000-2 §7.3.4.2, y losLab PDF Library invierte ese escapado en la importación para que los paréntesis y las barras regresen como los caracteres literales que el usuario escribió. El segundo es la codificación: los métodos basados en archivos escriben y leen XFDF and FDF como UTF-8, que es lo que promete la declaración XFDF y lo que cualquier valor de campo no ASCII (un nombre con acento, un símbolo de moneda, una dirección CJK) necesita para realizar el viaje de ida y vuelta sin corrupción. Si usted mismo construye el XFDF, declare UTF-8 y escriba UTF-8, y la importación funcionará correctamente
Campos jerárquicos, selecciones de múltiples valores y texto enriquecido
Los nombres de campos jerárquicos son el primer lugar donde falla un exportador básico. AcroForm direcciona un campo anidado con un título completo con puntos como Applicant.FullName, pero XFDF no coloca esa cadena de caracteres con puntos en un solo atributo name; ISO 19444 lo anida como <field name="Applicant"><field name="FullName">. losLab PDF Library divide el título con puntos en elementos <field> anidados al exportar y vuelve a ensamblar los elementos anidados en el título completo al importar, de modo que ambas direcciones se mantengan simétricas. Al exportar, también omite los campos primarios no terminales, porque un nodo primario en un AcroForm solo contiene el nivel de nomenclatura y no tiene valor propio; emitirlo produciría un <value></value> vacío que no coincide con el formulario real. Las casillas de lista de selección múltiple son el segundo peligro: un campo de elección puede contener varios valores seleccionados a la vez, lo que XFDF expresa como elementos <value> repetidos y FDF expresa como un arreglo /V, y losLab PDF Library solo divide un campo en múltiples valores cuando es realmente una elección de selección múltiple, por lo que un campo de texto multilínea ordinario conserva sus saltos de línea en lugar de dividirse en valores erróneos
El texto enriquecido es el tercero, y en el que la gente se equivoca con más frecuencia. Un campo con formato almacena su marcado en la entrada RV como un subárbol XHTML, y XFDF lo lleva en <value-richtext>. losLab PDF Library escribe ese subárbol como un fragmento XML activo en lugar de escaparlo, de modo que una herramienta downstream lea texto enriquecido real en lugar de una cadena de caracteres de etiquetas visibles; al importar, conserva el subárbol RV original y sigue aplicando el <value> simple a V. Cuando un campo ofrece ambos, el valor simple gana para V y el texto enriquecido se incluye de forma complementaria en RV, que es la regla de interoperabilidad que evita que una importación de texto enriquecido reescriba silenciosamente un valor que otra herramienta ya configuró. Cuando su texto enriquecido exista para transmitir la estructura del documento a la tecnología de asistencia, trátelo de la misma manera que trataría el orden de lectura analizado en la nota sobre PDF etiquetado y estructura de accesibilidad
var
Lib: TPDFlib;
const
XFDF =
'<?xml version="1.0" encoding="UTF-8"?>' +
'<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">' +
'<fields>' +
' <field name="Applicant">' +
' <field name="FullName"><value>Alice Example</value></field>' +
' </field>' +
' <field name="Skills">' +
' <value>Delphi</value><value>PDF</value>' +
' </field>' +
' <field name="Notes">' +
' <value>See attachment</value>' +
' <value-richtext><body><p>See <b>attachment</b></p></body></value-richtext>' +
' </field>' +
'</fields></xfdf>';
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('intake.pdf', '');
// Applicant.FullName reassembles; Skills fills the /V + /I arrays;
// Notes gets V from <value> and RV from <value-richtext>
Lib.ImportFormDataFromXFDFString(XFDF);
Lib.SaveToFile('intake-filled.pdf');
finally
Lib.Free;
end;
end;
¿Cómo se realiza el viaje de ida y vuelta de los comentarios de anotación como FDF o XFDF?
Los comentarios viajan en la familia de anotaciones, y el subconjunto compatible es deliberadamente pequeño. ExportAnnotationsToXFDF e ImportAnnotationsFromXFDF, junto con sus homólogos FDF, transportan marcado de estilo de texto con los campos que realmente realizan el viaje de ida y vuelta de manera limpia: el subtipo de anotación, su rectángulo, su índice de página basado en 0, el autor en T, the subject in Subj, el contenido simple (Contents) y el color, que mapea el triplete DeviceRGB /C de PDF hacia y desde un atributo XFDF #RRGGBB. La importación acepta solo nombres de elementos conocidos y omite cualquier entrada cuya página esté fuera de rango o cuyo rectángulo no esté presente, de modo que un XFDF editado a mano o externo no pueda introducir una anotación mal formada en el documento. Lo que el subconjunto aún no transporta vale la pena mencionarlo claramente: el contenido de texto enriquecido (RC), ventanas emergentes (popups), quadpoints, listas de tinta, vértices y flujos de apariencia integrados están fuera de alcance por ahora, por lo que la geometría de resaltado y las apariencias de sellos personalizados no sobrevivirán a esta ruta. Para confirmar qué se importó realmente, recorra las anotaciones de la página o el árbol de elementos más amplio cubierto en búsqueda de texto y enumeración de elementos de página
var
Src, Dest: TPDFlib;
Xfdf: WideString;
begin
Src := TPDFlib.Create;
Dest := TPDFlib.Create;
try
Src.LoadFromFile('reviewed.pdf', '');
Xfdf := Src.ExportAnnotationsToXFDFString; // <annots> subset only
Dest.LoadFromFile('clean-copy.pdf', ''); // pages must line up by index
Dest.ImportAnnotationsFromXFDFString(Xfdf);
Dest.SaveToFile('clean-copy-commented.pdf');
finally
Dest.Free;
Src.Free;
end;
end;
Escribir un paquete XDP de XFA completo con SetXFAFromString
XFA es el caso atípico, y SetXFAFromString es la forma en que se escribe todo a la vez. El método toma un XML Data Package completo, el documento <xdp:xdp> con sus paquetes de plantilla y conjuntos de datos, y lo almacena como el flujo de datos referenciado desde /AcroForm/XFA. losLab PDF Library crea el contenedor AcroForm bajo demanda cuando el documento no tiene ninguno, por lo que no es necesario agregar un campo desechable solo para darle a la XFA un lugar donde colgarse, y descarta cualquier estado XFA analizado que tuviera guardado para que una lectura posterior refleje el paquete que acaba de escribir en lugar de un caché obsoleto. Debido a que un paquete XFA es XML y no necesariamente UTF-8, la biblioteca detecta una marca de orden de bytes UTF-16 y decodifica el paquete correctamente antes de analizarlo, lo cual es importante para los paquetes producidos por herramientas que utilizan UTF-16 por defecto
Una vez que el paquete está en su lugar, GetXFAFormFieldValue y SetXFAFormFieldValue direccionan campos individuales a través de su ruta Scripting Object Model. losLab PDF Library acepta las raíces SOM estándar así como rutas relativas simples, por lo que form1.FullName, $data.form1.FullName y xfa.datasets.data.form1.FullName se resuelven en el mismo nodo de datos, y el lado de la plantilla acepta $template y xfa.template de la misma manera. Esa tolerancia es importante cuando las rutas SOM son generadas por otro sistema que siempre emite el formulario completamente calificado
var
Lib: TPDFlib;
const
Xdp =
'<?xml version="1.0" encoding="UTF-8"?>' +
'<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">' +
' <template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">' +
' <subform name="form1">' +
' <field name="FullName"><ui><textEdit/></ui></field>' +
' </subform>' +
' </template>' +
' <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">' +
' <xfa:data><form1><FullName>Alice Example</FullName></form1></xfa:data>' +
' </xfa:datasets>' +
'</xdp:xdp>';
begin
Lib := TPDFlib.Create;
try
Lib.SetXFAFromString(Xdp, 0); // creates the AcroForm container if none exists
// read back through the data DOM with an SOM path
if Lib.GetXFAFormFieldValue('form1.FullName') = 'Alice Example' then
Lib.SetXFAFormFieldValue('form1.FullName', 'Bob Example');
Lib.SaveToFile('xfa-packet.pdf');
finally
Lib.Free;
end;
end;
El resumen honesto es que los valores de los campos realizan el viaje de ida y vuelta por completo a través de FDF y XFDF, incluyendo jerarquía, selección múltiple y texto enriquecido; los comentarios de anotaciones lo realizan como un subconjunto de marcado de texto definido con brechas claras; y XFA se escribe y lee como un paquete completo con acceso SOM por campo además. Coincida el formato con el consumidor, declare UTF-8 para cualquier cosa que construya manualmente y recuerde que los métodos de importación solo tocan campos y anotaciones que ya se ajustan al documento. Los métodos de datos de formulario, anotación y XFA descritos aquí forman parte de losLab PDF Library para Delphi y C++Builder, cuya referencia contiene la lista completa de parámetros para cada punto de entrada de exportación e importación