HotPDF scrive documenti PDF 2.0 nativi da Delphi e C++Builder, inclusi i tre profili archivistici PDF/A-4 e l'output accessibile PDF/UA-2 con elementi di struttura in namespace. Selezionarli è questione di due proprietà, ma gli standard dietro quelle proprietà sono cambiati più di quanto suggerisca il numero di versione: PDF/A-4 ha abbandonato le lettere di conformance che tutti hanno imparato con PDF/A-2, e PDF/UA-2 ha introdotto i namespace di struttura che un documento di parte 1 non aveva mai avuto
Questo articolo copre cosa cambia davvero nel file generato, e quali errori HotPDF trasforma in un'eccezione a EndDoc anziché in un documento che fallisce la validazione presso il cliente
Come differisce l'identificazione PDF/A-4 dalla parte 2 e 3
PDF/A-4 si identifica per numero di parte e anno di revisione, senza lettera di conformance per la parte base. Imposta PDFACompliance a '4' e HotPDF emette pdfaid:part=4 con pdfaid:rev=2020 e nessuna voce pdfaid:conformance del tutto. La lettera non è andata persa — la parte 4 non ha livelli A/B/U, perché i requisiti che li separavano sono stati inglobati nella parte base
Due estensioni conservano una lettera. '4E' seleziona PDF/A-4e per documenti tecnici ed emette conformance E, che ammette i percorsi di annotazione 3D e RichMedia che gli altri profili vietano. '4F' seleziona PDF/A-4f ed emette conformance F, che ammette un file incorporato di qualsiasi formato. Tutte e tre forzano un header PDF 2.0, richiedono i consueti controlli di output intent e metadati PDF/A, e vietano la cifratura — un file archivistico cifrato è una contraddizione che lo standard non prende in considerazione
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 incorpora il file, costruisce la sua FileSpec con una /AFRelationship, e la registra sia nell'array /AF del Catalog sia nel name tree EmbeddedFiles. Entrambe le registrazioni sono obbligatorie; un file elencato solo in una delle due è il motivo più comune per cui una fattura ibrida supera un controllo visivo rapido e fallisce un validatore vero. La stringa di relazione accetta Source, Data, Alternative, Supplement o Unspecified, e il profilo attivo deve essere PDF/A-3, PDF/A-4e o PDF/A-4f — il profilo di parte 4 base non ammette file associati. Il vecchio nome AddPDFA3AssociatedFile continua a funzionare per il codice esistente
Cosa richiede PDF/UA-2 che PDF/UA-1 non richiedeva
PDF/UA-2 forza PDF 2.0 ed emette pdfuaid:part=2 con pdfuaid:rev=2024, e introduce i namespace nell'albero di struttura. Un documento di parte 1 aveva un unico vocabolario piatto di ruoli standard. Un documento di parte 2 può portare ruoli personalizzati purché ciascuno appartenga a un namespace dichiarato, il che è ciò che rende il tagging specifico di dominio leggibile alle tecnologie assistive invece che un'ipotesi
Due metodi implementano questo. RegisterStructureNamespace crea o riusa un dizionario indiretto /Type /Namespace e lo elenca in StructTreeRoot /Namespaces, restituendo il dizionario così puoi riusarlo. AddStructureElementNS crea un elemento di struttura la cui voce /NS punta a quel dizionario, che è ciò che autorizza un nome di ruolo fuori dall'insieme standard. Chiamate ripetute con lo stesso URI riusano un solo dizionario anziché accumulare duplicati
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 non è decorativo qui. Un documento taggato senza lingua naturale dichiarata lascia un lettore schermo a indovinare la pronuncia, e PDF/UA tratta l'omissione come un difetto anziché come una preferenza
Quali errori di struttura intercetta EndDoc?
Quattro, e ciascuno corrisponde a un documento che altrimenti arriverebbe rotto a un validatore. La radice di struttura deve contenere esattamente un elemento Document di primo livello. Ogni dizionario di namespace deve essere indiretto, tipizzato come Namespace, e portare un URI univoco non vuoto. Ogni riferimento /NS di un elemento di struttura deve risolvere a un dizionario effettivamente elencato nell'array /Namespaces della radice. E un ruolo senza namespace deve essere un ruolo standard di PDF 2.0 o risolvere attraverso la RoleMap
Questi scattano a EndDoc perché è l'ultimo momento in cui l'intero albero esiste in memoria ed è il primo in cui è completo. Intercettarli prima significherebbe rifiutare stati intermedi validi; intercettarli dopo significherebbe non intercettarli affatto. La conseguenza pratica per il tuo codice è che un bug di struttura emerge alla fine della generazione con un messaggio che nomina il problema, invece di emergere settimane dopo come un report veraPDF che qualcuno inoltra da un cliente
I ruoli di PDF 2.0 che vale la pena conoscere
L'enum tipizzato dei ruoli guadagna DocumentFragment, Aside, Title, FENote, Sub, Em, Strong e Artifact. Tre di questi cambiano come tagghi i normali documenti aziendali. Aside finalmente dà a barre laterali e pull quote una casa che non sia un Sect usato male. FENote marca note a piè di pagina e note di chiusura per ciò che sono, così un lettore può offrirle anziché interpolarle con il corpo testo. Em e Strong sostituiscono l'ipotesi semantica che derivava dal taggare l'enfasi come formattazione a livello di span
L'overload stringa accetta inoltre la forma aperta Hn, inclusi H7 e oltre. PDF 1.7 si fermava a H6, il che costringeva i documenti tecnici profondi ad appiattire la propria outline o a riusare i livelli. Se generi documenti di normative, codici legali o cataloghi di parti, questo da solo può essere il motivo per spostare l'output a PDF 2.0
Cosa controllare prima di cambiare l'output di produzione
PDF 2.0 è un cambio di header con una lunga coda. Strumenti di ingest archivistici più vecchi, alcuni RIP di stampa e un numero sorprendente di visualizzatori line-of-business accettano solo fino a PDF 1.7, e falliscono sull'header anziché su qualcosa che hai fatto sbagliato. Prima di cambiare, conferma i sistemi consumer, e ricorda che selezionare un profilo PDF/A-4 seleziona PDF 2.0 indipendentemente dal fatto che tu lo chieda o no
Una sequenza sicura è mantenere PDF/A-3 per i documenti che vanno verso lettori sconosciuti, usare PDF/A-4f per archivi interni dove controlli l'ingest, e adottare PDF/UA-2 solo dove la policy di accessibilità lo nomini. Se stai lavorando prima sul lato archivistico, le guide alla validazione PDF/A, PDF/X e PDF/UA e a ZUGFeRD e Factur-X su PDF/A-3 coprono le scelte di profilo che contano prima del numero di versione, e le note sul report di preflight automatizzato mostrano come rendere il verdetto parte della tua build anziché un passo manuale
HotPDF distribuisce l'intera superficie di authoring PDF 2.0 come codice VCL nativo per Delphi e C++Builder, così l'output PDF/A-4 e PDF/UA-2 non richiede alcun motore esterno o ridistribuibile — la pagina del componente HotPDF elenca i profili supportati e le versioni di RAD Studio