HotPDF escribe documentos PDF 2.0 nativos desde Delphi y C++Builder, incluyendo los tres perfiles de archivo PDF/A-4 y la salida accesible PDF/UA-2 con elementos de estructura bajo espacios de nombres. Seleccionarlos es cuestión de dos propiedades, pero las normas detrás de esas propiedades cambiaron más de lo que sugiere el número de versión: PDF/A-4 eliminó las letras de conformidad que todos aprendieron con PDF/A-2, y PDF/UA-2 introdujo espacios de nombres de estructura que un documento de parte 1 nunca tuvo
Este artículo cubre qué cambia de verdad en el archivo generado, y qué errores HotPDF convierte en una excepción en EndDoc en vez de en un documento que falla la validación en el sitio del cliente
Cómo difiere la identificación de PDF/A-4 respecto a las partes 2 y 3
PDF/A-4 se identifica por número de parte y año de revisión, sin letra de conformidad para la parte base. Pon PDFACompliance en '4' y HotPDF emite pdfaid:part=4 con pdfaid:rev=2020 y ninguna entrada pdfaid:conformance en absoluto. La letra no se perdió — la parte 4 no tiene niveles A/B/U, porque los requisitos que solían separarlos se integraron en la parte base
Dos extensiones conservan una letra. '4E' selecciona PDF/A-4e para documentos de ingeniería y emite conformancia E, que permite las rutas de anotación 3D y RichMedia que los otros perfiles prohíben. '4F' selecciona PDF/A-4f y emite conformancia F, que permite un archivo incrustado de cualquier formato. Los tres fuerzan encabezados PDF 2.0, exigen las verificaciones habituales de intent de salida y metadatos PDF/A, y prohíben el cifrado — un archivo de archivo cifrado es una contradicción que la norma no contempla
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-archive.pdf';
Pdf.PDFACompliance := '4F'; // PDF/A-4f: associated files of any format
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Invoice 2026-0731');
Pdf.AddPDFAssociatedFile('invoice.xml', 'text/xml',
'Structured invoice data', 'Data', LoadInvoiceBytes);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
AddPDFAssociatedFile incrusta el archivo, construye su FileSpec con un /AFRelationship, y lo registra tanto en el arreglo /AF del catálogo como en el árbol de nombres EmbeddedFiles. Ambos registros son obligatorios; un archivo listado en solo uno de ellos es la razón individual más común de que una factura híbrida pase una revisión rápida a ojo y falle un validador real. La cadena de relación acepta Source, Data, Alternative, Supplement o Unspecified, y el perfil activo debe ser PDF/A-3, PDF/A-4e o PDF/A-4f — el perfil base de parte 4 no admite archivos asociados. El nombre anterior AddPDFA3AssociatedFile sigue funcionando para código existente
Qué pide PDF/UA-2 que PDF/UA-1 no pedía
PDF/UA-2 fuerza PDF 2.0 y emite pdfuaid:part=2 con pdfuaid:rev=2024, e introduce espacios de nombres en el árbol de estructura. Un documento de parte 1 tenía un vocabulario plano de roles estándar. Un documento de parte 2 puede llevar roles personalizados siempre que cada uno pertenezca a un espacio de nombres declarado, que es lo que vuelve legible para la tecnología de asistencia un etiquetado específico de dominio en vez de una conjetura
Dos métodos implementan esto. RegisterStructureNamespace crea o reutiliza un diccionario indirecto /Type /Namespace y lo lista en StructTreeRoot /Namespaces, devolviendo el diccionario para que puedas reutilizarlo. AddStructureElementNS crea un elemento de estructura cuya entrada /NS apunta a ese diccionario, que es lo que autoriza un nombre de rol fuera del conjunto estándar. Llamadas repetidas con el mismo URI reutilizan un diccionario en vez de apilar duplicados
var
Root: THPDFDictionaryObject;
begin
Pdf.PDFUACompliance := True;
Pdf.PDFUAPart := 2; // part 2 forces PDF 2.0
Pdf.Lang := 'en-US';
Pdf.BeginDoc;
Root := Pdf.AddStructureElement('Document', nil);
Pdf.AddStructureElementNS('WidgetGroup',
'https://example.com/ns/widgets', Root);
Pdf.EndDoc;
end;
Lang no es decoración aquí. Un documento etiquetado sin idioma natural declarado deja a un lector de pantalla adivinando la pronunciación, y PDF/UA trata la omisión como un defecto en vez de una preferencia
¿Qué errores de estructura atrapa EndDoc?
Cuatro, y cada uno corresponde a un documento que de otro modo llegaría roto a un validador. La raíz de estructura debe contener exactamente un elemento Document de nivel superior. Cada diccionario de espacio de nombres debe ser indirecto, tipado como Namespace, y llevar un URI único no vacío. Cada referencia /NS de elemento de estructura debe resolver a un diccionario realmente listado en el arreglo raíz /Namespaces. Y un rol sin espacio de nombres debe ser un rol estándar de PDF 2.0 o resolver a través del RoleMap
Estos se disparan en EndDoc porque ese es el último momento en que el árbol completo existe en memoria y el primer momento en que está completo. Atraparlos antes significaría rechazar estados intermedios válidos; atraparlos después significaría no atraparlos en absoluto. La consecuencia práctica para tu código es que un bug de estructura aparece al final de la generación con un mensaje que nombra el problema, en vez de aparecer semanas después como un reporte de veraPDF que alguien reenvía desde un cliente
Los roles de PDF 2.0 que vale la pena conocer
La enumeración de roles tipados gana DocumentFragment, Aside, Title, FENote, Sub, Em, Strong y Artifact. Tres de esos cambian cómo etiquetas documentos de negocios ordinarios. Aside por fin da a las barras laterales y las citas destacadas un hogar que no es un Sect mal usado. FENote marca las notas al pie y las notas al final como lo que son, así un lector puede ofrecerlas en vez de intercalarlas con el cuerpo. Em y Strong sustituyen la conjetura semántica que venía de etiquetar el énfasis como formato a nivel de span
La sobrecarga de cadena adicionalmente acepta la forma abierta Hn, incluyendo H7 y más allá. PDF 1.7 se detenía en H6, lo que forzaba a los documentos técnicos profundos a aplanar su esquema o a reutilizar niveles. Si generas documentos de normas, códigos legales o catálogos de piezas, esto por sí solo puede ser la razón para mover la salida a PDF 2.0
Qué verificar antes de cambiar la salida de producción
PDF 2.0 es un cambio de encabezado con una larga cola. Las herramientas de ingesta de archivo antiguas, algunos RIP de impresión y una cantidad sorprendente de visores de línea de negocio aceptan solo hasta PDF 1.7, y fallan por el encabezado en vez de por algo que hayas hecho mal. Antes de cambiar, confirma los sistemas consumidores, y recuerda que seleccionar un perfil PDF/A-4 selecciona PDF 2.0 lo pidas o no
Una secuencia segura es conservar PDF/A-3 para los documentos que van hacia lectores desconocidos, usar PDF/A-4f para archivos internos donde controlas la ingesta, y adoptar PDF/UA-2 solo donde la política de accesibilidad lo nombre. Si estás trabajando primero el lado de archivo, las guías sobre la validación de PDF/A, PDF/X y PDF/UA y sobre las facturas híbridas ZUGFeRD y Factur-X sobre PDF/A-3 cubren las elecciones de perfil que importan antes que el número de versión, y las notas sobre el reporte de preflight automatizado muestran cómo convertir el veredicto en parte de tu construcción en vez de un paso manual
HotPDF entrega toda la superficie de creación de PDF 2.0 como código VCL nativo para Delphi y C++Builder, así que la salida PDF/A-4 y PDF/UA-2 no necesita ningún motor externo ni redistribuible — la página del componente HotPDF lista los perfiles soportados y las versiones de RAD Studio