Skip to content
Metadata

Metadata

A PDF carries document-level metadata in two independent places, and readers regularly confuse them. The older one is the document information dictionary, a flat set of predefined keys reached through the trailer’s /Info entry. The newer one is XMP: an XML packet stored as a stream on the document catalog, organized into namespaced models that anything can extend. Section 14.3 of the PDF specification (PDF32000_2008) defines both.

The document info dictionary

Flat, fixed, and simple. The standard keys are Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate and Trapped. Creator is the application that produced the original document, Producer the one that converted it to PDF, which is why the two so often differ. Trapped is a name, one of True, False or Unknown, and it says whether trapping information has been added to the file.

In UniPDF this is model.PdfInfo. PdfReader.GetPdfInfo returns it, PdfWriter.SetDocInfo and PdfAppender.SetDocInfo write it. Keys outside the standard set are kept separately and reached through AddCustomInfo, GetCustomInfo and CustomKeys - AddCustomInfo returns an error if you pass a standard key.

XMP

XMP is an RDF/XML packet, and instead of fixed keys it holds any number of models keyed by namespace: pdf: for producer and PDF version, dc: for Dublin Core title and creator, xmp: for creation and modification times, xmpMM: for media management identifiers, pdfaid: and pdfuaid: for conformance claims. That extensibility is the point: a private namespace can be added without breaking any reader that does not know it.

UniPDF exposes XMP through model/xmputil. PdfReader.GetCatalogMetadata returns the raw metadata object, xmputil.LoadDocument parses the stream bytes into an xmputil.Document, and PdfWriter.SetCatalogMetadata writes a stream back. xmputil.NewDocument starts an empty packet when you would rather replace than edit.

LoadDocument decodes in lenient mode. A single malformed property, such as a loosely formatted date or an extension field with no matching model, is skipped rather than failing the whole packet, so well-formed properties stay readable. Genuinely malformed XML and I/O errors still return an error.

When the two disagree

Nothing in the format keeps the info dictionary and the XMP packet in sync, and plenty of tools write one without touching the other. The same document can report one title in /Info and a different one in dc:title. Where the specification cares, XMP is the authority for viewers that read it, and PDF/A requires the two to agree - a mismatch is a conformance failure.

So if you set metadata that has to survive validation, set both. xmputil Document.SetPdfInfo takes a PdfInfoOptions whose InfoDict field accepts the info dictionary directly, which maps the standard keys into the pdf: XMP model for you. Its Overwrite flag decides whether the existing pdf: model is cleared first or merged into.

Where to look

GuideWhat it covers
Get document info metadataReading /Info through PdfReader.GetPdfInfo, including custom keys.
Set document info metadataWriting /Info with the global setters or PdfWriter.SetDocInfo, plus custom keys.
Get XMP metadataParsing the catalog XMP packet and reading the pdf: info model.
Set XMP metadataBuilding a pdf: model from the info dictionary and writing the packet back.
Get XML metadataDumping the raw XMP stream as XML, without parsing it.
Get custom XMP metadataReading namespaces xmputil does not wrap, through the go-xmp document.
Set custom XMP metadataWriting properties in a namespace xmputil does not wrap.
Get PDF/A identification metadataReading the pdfaid: part and conformance level a file claims.
Get media management metadataReading xmpMM: document, instance and original document IDs.
Set media management metadataWriting xmpMM: identifiers and derivation history.
Last updated on