HotPDF пише рідні документи PDF 2.0 з Delphi та C++Builder, включно з трьома архівними профілями PDF/A-4 та доступним виводом PDF/UA-2 з елементами структури в просторах імен. Їхній вибір зводиться до двох властивостей, але стандарти за цими властивостями змінилися більше, ніж свідчить номер версії: PDF/A-4 прибрав літери відповідності, які усі вивчили з PDF/A-2, а PDF/UA-2 уводить простори імен структури, яких документ частини 1 ніколи не мав
Ця стаття описує, що фактично змінюється в згенерованому файлі та які помилки HotPDF перетворює на виняток під час EndDoc, а не на документ, що не проходить валідацію на боці клієнта
Як ідентифікація PDF/A-4 відрізняється від частин 2 та 3
PDF/A-4 ідентифікує себе номером частини та роком редакції, без літери відповідності для базової частини. Установіть PDFACompliance на '4', і HotPDF видасть pdfaid:part=4 з pdfaid:rev=2020 і взагалі без запису pdfaid:conformance. Літера не загубилася — у частини 4 немає рівнів A/B/U, бо вимоги, що колись розділяли їх, були згорнуті в базову частину
Два розширення зберігають літеру. '4E' обирає PDF/A-4e для інженерних документів і видає відповідність E, що дозволяє шляхи анотацій 3D та RichMedia, які інші профілі забороняють. '4F' обирає PDF/A-4f і видає відповідність F, що дозволяє вбудований файл будь-якого формату. Усі три примусово встановлюють заголовок PDF 2.0, вимагають звичайної вихідної наміренції PDF/A та перевірок метаданих і забороняють шифрування — зашифрований архівний файл є протиріччям, яке стандарт не припускає
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 вбудовує файл, будує його FileSpec із /AFRelationship та реєструє його одночасно в масиві Catalog /AF та дереві імен EmbeddedFiles. Обидві реєстрації обов'язкові; файл, указаний лише в одній із них, — єдина найпоширеніша причина, через яку гібридний рахунок проходить швидку візуальну перевірку й не проходить справжній валідатор. Рядок зв'язку приймає Source, Data, Alternative, Supplement або Unspecified, а активний профіль має бути PDF/A-3, PDF/A-4e або PDF/A-4f — базовий профіль частини 4 не приймає пов'язаних файлів. Старіше ім'я AddPDFA3AssociatedFile усе ще працює для наявного коду
Чого вимагає PDF/UA-2, чого не вимагав PDF/UA-1
PDF/UA-2 змушує використовувати PDF 2.0 і видає pdfuaid:part=2 з pdfuaid:rev=2024, а також уводить простори імен у дерево структури. Документ частини 1 мав один плоский словник стандартних ролей. Документ частини 2 може нести власні ролі, за умови що кожна належить до оголошеного простору імен, — і саме це робить доменно-специфічне тегування зрозумілим для допоміжних технологій, а не вгадуванням
Два методи це реалізують. RegisterStructureNamespace створює або повторно використовує непрямий словник /Type /Namespace та вказує його в StructTreeRoot /Namespaces, повертаючи словник, щоб ви могли використати його повторно. AddStructureElementNS створює елемент структури, чиїй запис /NS вказує на цей словник, що й дозволяє ім'я ролі поза стандартним набором. Повторні виклики з тим самим URI повторно використовують один словник, а не накопичують дублікати
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 тут не прикраса. Тегований документ без оголошеної природної мови змушує читач з екрана вгадувати вимову, а PDF/UA розглядає це упущення як дефект, а не як уподобання
Які помилки структури ловить EndDoc?
Чотири, і кожна відповідає документу, який інакше дістався б валідатору зламаним. Корінь структури має містити рівно один елемент Document верхнього рівня. Кожен словник простору імен має бути непрямим, типізованим як Namespace, і нести унікальний непорожній URI. Кожне посилання /NS елемента структури має вирішуватися до словника, фактично вказаного в масиві кореня /Namespaces. А роль без простору імен має бути стандартною роллю PDF 2.0 або вирішуватися через RoleMap
Вони спрацьовують під час EndDoc, бо це останній момент, коли усе дерево існує в пам'яті, і перший, коли воно повне. Ловити їх раніше означало б відхиляти правомірні проміжні стани; ловити пізніше означало б не зловити взагалі. Практичний наслідок для вашого коду полягає в тому, що вада структури спливає наприкінці генерації з повідомленням, що називає проблему, замість того, щоб спливати через кілька тижнів як звіт veraPDF, який хтось пересилає від клієнта
Ролі PDF 2.0, про які варто знати
Типізований enum ролей отримує DocumentFragment, Aside, Title, FENote, Sub, Em, Strong та Artifact. Три з них змінюють те, як ви тегуєте звичайні ділові документи. Aside нарешті дає бічним панелям та винесеним цитатам дім, що не є зловживанням Sect. FENote позначає виноски та кінцеві примітки як те, чим вони є, тож читач може запропонувати їх, а не перемежувати з основним текстом. Em та Strong замінюють семантичне вгадування, що виникало з тегування наголосу як форматування рівня span
Строкове перевантаження додатково приймає відкриту форму Hn, включно з H7 і далі. PDF 1.7 зупинявся на H6, що змушувало глибокі технічні документи сплощувати свій план або повторно використовувати рівні. Якщо ви генеруєте документи стандартів, правові кодекси чи каталоги деталей, саме це може бути причиною перевести вивід на PDF 2.0
Що перевірити перед переходом виробничого виводу
PDF 2.0 — це зміна заголовка з довгим хвостом. Старіші інструменти архівного приймання, деякі RIP-и друку й напрочуд багато бізнесних переглядачів приймають лише до PDF 1.7 і відмовляють на заголовку, а не на чомусь, що ви зробили неправильно. Перед переходом підтвердіть споживні системи й пам'ятайте, що вибір профілю PDF/A-4 вибирає PDF 2.0, просили ви про це чи ні
Безпечна послідовність: тримати PDF/A-3 для документів, що йдуть назовні невідомим читачам; використовувати PDF/A-4f для внутрішніх архівів, де ви контролюєте приймання; та прийняти PDF/UA-2 лише там, де політика доступності його називає. Якщо ви спочатку опрацьовуєте архівний бік, посібники з валідації PDF/A, PDF/X та PDF/UA і гібридних рахунків ZUGFeRD та Factur-X на PDF/A-3 описують вибір профілю, що важить раніше за номер версії, а нотатки автоматизованої звітності префлайта показують, як зробити вердикт частиною вашої збірки, а не ручним кроком
HotPDF постачає всю поверхню авторинга PDF 2.0 як рідний VCL-код для Delphi та C++Builder, тож вивід PDF/A-4 та PDF/UA-2 не потребує зовнішнього рушія чи поширюваного пакета — сторінка компонента HotPDF перераховує підтримувані профілі та версії RAD Studio