HotPDF zapisuje natywne dokumenty PDF 2.0 z Delphi i C++Builder, w tym trzy profile archiwalne PDF/A-4 oraz dostępne wyjście PDF/UA-2 z elementami struktury w przestrzeniach nazw. Wybranie ich to kwestia dwóch właściwości, ale normy za tymi właściwościami zmieniły się bardziej, niż sugeruje numer wersji: PDF/A-4 porzucił litery zgodności, których wszyscy nauczyli się przy PDF/A-2, a PDF/UA-2 wprowadził przestrzenie nazw struktury, których dokument części 1 nigdy nie miał
Ten artykuł obejmuje to, co faktycznie zmienia się w wygenerowanym pliku, oraz które błędy HotPDF zamienia w wyjątek przy EndDoc, zamiast w dokument, który zawiedzie walidację u klienta
Czym identyfikacja PDF/A-4 różni się od części 2 i 3
PDF/A-4 identyfikuje się numerem części i rokiem rewizji, bez litery zgodności dla części bazowej. Ustaw PDFACompliance na '4', a HotPDF emituje pdfaid:part=4 z pdfaid:rev=2020 i bez żadnego wpisu pdfaid:conformance w ogóle. Litera nie zaginęła — część 4 nie ma poziomów A/B/U, ponieważ wymagania, które kiedyś je rozdzielały, zostały włożone w część bazową
Dwa rozszerzenia zachowują literę. '4E' wybiera PDF/A-4e dla dokumentów inżynieryjnych i emituje zgodność E, która dopuszcza ścieżki adnotacji 3D i RichMedia, jakie zabraniają inne profile. '4F' wybiera PDF/A-4f i emituje zgodność F, która dopuszcza osadzony plik dowolnego formatu. Wszystkie trzy wymuszają nagłówek PDF 2.0, wymagają zwykłej intencji wyjścia PDF/A i sprawdzeń metadanych oraz zabraniają szyfrowania — szyfrowany plik archiwalny to sprzeczność, której norma nie dopuszcza
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 osadza plik, buduje jego FileSpec z /AFRelationship i rejestruje go zarówno w tablicy /AF katalogu, jak i w drzewie nazw EmbeddedFiles. Obie rejestracje są wymagane; plik wymieniony tylko w jednej z nich to najczęstszy powód, dla którego hybrydowa faktura przechodzi szybkie sprawdzenie wzrokiem i zawodzi na prawdziwym walidatorze. Ciąg znaków relacji przyjmuje Source, Data, Alternative, Supplement lub Unspecified, a aktywny profil musi być PDF/A-3, PDF/A-4e lub PDF/A-4f — bazowy profil części 4 nie dopuszcza plików powiązanych. Starsza nazwa AddPDFA3AssociatedFile wciąż działa dla istniejącego kodu
Czego PDF/UA-2 wymaga, a czego PDF/UA-1 nie wymagał
PDF/UA-2 wymusza PDF 2.0 i emituje pdfuaid:part=2 z pdfuaid:rev=2024, a także wprowadza przestrzenie nazw do drzewa struktury. Dokument części 1 miał jeden płaski słownik ról standardowych. Dokument części 2 może nieść własne role, dopóki każda z nich należy do zadeklarowanej przestrzeni nazw, co czyni domenowe tagowanie zrozumiałym dla technologii asystującej zamiast zgadywanką
Dwie metody to implementują. RegisterStructureNamespace tworzy lub ponownie używa pośredni słownik /Type /Namespace i wpisuje go do StructTreeRoot /Namespaces, zwracając słownik, żebyś mógł go użyć ponownie. AddStructureElementNS tworzy element struktury, którego wpis /NS wskazuje na ten słownik, co licencjonuje nazwę roli poza zestawem standardowym. Powtórzone wywołania z tym samym URI używają jednego słownika zamiast nagromadzać duplikaty
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 nie jest tu ozdobą. Otagowany dokument bez zadeklarowanego języka naturalnego zostawia czytnik ekranu zgadujący wymowę, a PDF/UA traktuje ten brak jako wadę, nie preferencję
Jakie błędy struktury łapie EndDoc?
Cztery, a każdy z nich odpowiada dokumentowi, który inaczej dotarłby do walidatora zepsuty. Korzeń struktury musi zawierać dokładnie jeden wierzchołkowy element Document. Każdy słownik przestrzeni nazw musi być pośredni, określony typem Namespace i nieść unikalny niepusty URI. Każde odniesienie /NS elementu struktury musi się rozwiązywać do słownika faktycznie wymienionego w tablicy /Namespaces korzenia. A rola bez przestrzeni nazw musi być rolą standardową PDF 2.0 albo rozwiązywać się przez RoleMap
Te odpalają się przy EndDoc, bo to jest ostatnia chwila, kiedy całe drzewo istnieje w pamięci, i pierwsza, kiedy jest kompletne. Złapanie ich wcześniej oznaczałoby odrzucanie poprawnych stanów pośrednich; złapanie później oznaczałoby nie złapanie wcale. Praktycznym skutkiem dla Twojego kodu jest to, że błąd struktury ujawnia się na końcu generowania z komunikatem nazywającym problem, zamiast ujawniać się tygodnie później jako raport veraPDF, który ktoś przekazuje od klienta
Role PDF 2.0, o których warto wiedzieć
Typizowane wyliczenie ról zyskuje DocumentFragment, Aside, Title, FENote, Sub, Em, Strong i Artifact. Trzy z nich zmieniają sposób tagowania zwykłych dokumentów biznesowych. Aside w końcu daje panelom bocznym i wyróżnionym cytatom dom, który nie jest źle używanym Sect. FENote oznacza przypisy i przypisy końcowe jako to, czym są, więc czytnik może je zaoferować zamiast przeplatać je z tekstem głównym. Em i Strong zastępują semantyczną zgadywankę, która wynikała z tagowania wyróżnienia jako formatowania na poziomie spanu
Przeciążenie łańcuchowe dodatkowo przyjmuje otwartą formę Hn, w tym H7 i dalej. PDF 1.7 zatrzymywał się na H6, co zmuszało głębokie dokumenty techniczne do spłaszczania konspektu lub ponownego używania poziomów. Jeśli generujesz dokumenty normatywne, kody prawne lub katalogi części, to samo w sobie może być powodem przeniesienia wyjścia na PDF 2.0
Co sprawdzić przed przełączeniem wyjścia produkcyjnego
PDF 2.0 to zmiana nagłówka z długim ogonem. Starsze narzędzia archiwizujące, niektóre RIP-y drukujące i zaskakująca liczba viewerów linii biznesowej akceptują tylko do PDF 1.7 i zawodzą na nagłówku, a nie na czymkolwiek, co zrobiłeś źle. Przed przełączeniem potwierdź systemy konsumenckie i pamiętaj, że wybór profilu PDF/A-4 wybiera PDF 2.0 niezależnie od tego, o co prosiłeś
Bezpieczna kolejność to utrzymać PDF/A-3 dla dokumentów wychodzących do nieznanych czytelników, używać PDF/A-4f do archiwów wewnętrznych, gdzie kontrolujesz ingest, i adoptować PDF/UA-2 tylko tam, gdzie polityka dostępności go wymienia. Jeśli przerabiasz najpierw stronę archiwalną, przewodniki po walidacji PDF/A, PDF/X i PDF/UA oraz po hybrydowych fakturach ZUGFeRD i Factur-X na PDF/A-3 obejmują wybory profilu, które mają znaczenie przed numerem wersji, a notatki o automatyzacji raportowania preflighitu pokazują, jak uczynić werdykt częścią budowania zamiast ręcznym krokiem
HotPDF dostarcza całą powierzchnię autorskią PDF 2.0 jako natywny kod VCL dla Delphi i C++Builder, więc wyjście PDF/A-4 i PDF/UA-2 nie wymaga zewnętrznego silnika ani redystrybuucji — strona komponentu HotPDF wymienia obsługiwane profile i wersje RAD Studio