Skip to content

7. PDF/A & accessibility

Producing archival PDF/A output and accessible, tagged documents.

A PDF you file for the long term, or hand to someone using a screen reader, has to carry more than pixels. It needs embedded fonts so it renders the same in 2050, a declared language, machine-readable structure so a reader can follow the logical order, and metadata that says exactly which standard it conforms to. This chapter covers the three switches that produce such documents (PDF/A mode, tagged structure, and XMP metadata) and how they fit together.

All of these go through PdfDocumentRenderer and PdfSaveOptions, the same path you used for security.

PDF/A (ISO 19005) is the archival profile: it constrains PDF so a document reproduces reliably for decades. Embed all fonts, use device-independent colour, carry XMP metadata with a PDF/A identifier, and (crucially), no encryption, no JavaScript, no external references. You opt in with PdfSaveOptions.PdfAMode:

using Rivoli.Pdf;
var renderer = new PdfDocumentRenderer("1.4");
renderer.RenderToFile(doc, "archive.pdf", new PdfSaveOptions
{
PdfAMode = PdfAMode.PdfA1b,
Language = "en-US",
});

The PdfAMode enum (namespace Rivoli.Pdf) offers:

ValueConformanceNotes
Nonen/aStandard PDF (the default)
PdfA1bPDF/A-1b, Level B (Basic)Reliable visual reproduction; fonts embedded, device-independent colour, PDF/A XMP. Based on PDF 1.4
PdfA1aPDF/A-1a, Level A (Accessible)Everything in 1b plus tagged structure, declared language, and Unicode mapping for a logical reading order

Later parts of the family (PDF/A-2, PDF/A-3) are noted as future work in the enum and are not yet selectable.

A tagged PDF carries a structure tree: a logical outline of headings, paragraphs, lists, tables, and the reading order through them. This is what makes a document navigable by assistive technology rather than a flat wall of glyphs. Turn it on with EnableTaggedPDF:

renderer.RenderToFile(doc, "accessible.pdf", new PdfSaveOptions
{
EnableTaggedPDF = true,
Language = "en-US",
});

Tagging is coupled to the accessible profile: selecting PdfAMode.PdfA1a implies tagged output even if you do not set the flag explicitly, because Level A requires a structure tree. The renderer writes a StructTreeRoot, a MarkInfo dictionary, and marks every painting operator: content that is not semantic (decorative rules, backgrounds) is wrapped as an /Artifact so it is accounted for rather than left untagged.

A declared natural language lets a screen reader pick the right pronunciation rules and is mandatory for Level A and PDF/UA. Set it with Language (BCP-47 tag), which the renderer writes as the catalog /Lang:

Language = "en-US", // or "fr-FR", "de-DE", …

If you do not set it, the value falls back to PdfGlobalOptions.DefaultLanguage.

XMP is the standardized, embedded metadata stream that carries the document’s title, authorship, and (for conformance), the identifiers that declare which standard the file meets. It is controlled by IncludeXmpMetadata:

renderer.RenderToFile(doc, "archive.pdf", new PdfSaveOptions
{
PdfAMode = PdfAMode.PdfA1b,
IncludeXmpMetadata = true,
Language = "en-US",
});

When you request PDF/A, the XMP stream carries the PDF/A identification schema (pdfaid:part and pdfaid:conformance, e.g. part 1 / level B). When the output is fully tagged, the renderer additionally declares PDF/UA-1 conformance through the pdfuaid identifier, and registers the pdfuaid extension schema as ISO 19005-1 §6.7.9 requires for unrecognized namespaces. Title and author come from the document’s Metadata, so populate that when you create the document:

var doc = Document.Create("Annual Report 2025", "Finance Team");
doc.Metadata.Subject = "Year-end financial summary";
doc.Metadata.Keywords = "finance, annual, 2025";

PDF/UA (ISO 14289, “Universal Accessibility”) is the accessibility profile built on top of tagged PDF: a structure tree, a declared language, artifacted non-content, and the metadata that asserts conformance. There is no separate “PDF/UA mode” switch: you produce a PDF/UA-shaped document by enabling tagging, declaring a language, and including XMP:

renderer.RenderToFile(doc, "ua.pdf", new PdfSaveOptions
{
EnableTaggedPDF = true,
IncludeXmpMetadata = true,
Language = "en-US",
});

A fully archival, accessible document is just the three switches together: minus encryption, which the profile forbids:

var doc = Document.Create("Compliance Report", "Records Office");
var renderer = new PdfDocumentRenderer("1.4");
renderer.RenderToFile(doc, "report-archival.pdf", new PdfSaveOptions
{
PdfAMode = PdfAMode.PdfA1a, // Level A implies tagging
IncludeXmpMetadata = true,
Language = "en-US",
// SecuritySettings here would make Validate() throw.
});