기술 문서

Delphi에서 HotPDF로 PDF 2.0과 PDF/A-4, PDF/UA-2 출력하기

HotPDF는 Delphi와 C++Builder에서 네이티브 PDF 2.0 문서를 작성하며, 세 가지 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=4pdfaid: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은 파일을 임베드하고, /AFRelationship를 가진 FileSpec을 구성하며, 카탈로그 /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=2pdfuaid: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 역할

타입이 지정된 역할 열거는 DocumentFragment, Aside, Title, FENote, Sub, Em, Strong, Artifact를 얻습니다. 그중 세 가지는 일반적인 비즈니스 문서를 태깅하는 방식을 바꿉니다. Aside는 마침내 사이드바와 발췌문에 오용된 Sect가 아닌 제자리를 줍니다. FENote는 각주와 미주를 있는 그대로 표시하여 리더가 본문 텍스트와 섞는 대신 그것들을 제안할 수 있게 합니다. EmStrong은 강조를 스팬 수준 서식으로 태깅하던 의미론적 추측을 대체합니다

문자열 오버로드는 추가로 개방형 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 검증 가이드와 PDF/A-3의 ZUGFeRD와 Factur-X 하이브리드 청구서 가이드가 버전 번호보다 먼저 중요한 프로파일 선택을 다루며, 자동화된 프리플라이트 보고에 관한 글은 판정을 수동 단계가 아닌 빌드의 일부로 만드는 방법을 보여줍니다

HotPDF는 PDF 2.0 저작 표면 전체를 Delphi와 C++Builder를 위한 네이티브 VCL 코드로 배포하므로 PDF/A-4와 PDF/UA-2 출력은 외부 엔진이나 재배포 가능 패키지가 필요 없습니다. 지원되는 프로파일과 RAD Studio 버전은 HotPDF 컴포넌트 페이지에 나열되어 있습니다