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
| Guide | What it covers |
|---|---|
| Get document info metadata | Reading /Info through PdfReader.GetPdfInfo, including custom keys. |
| Set document info metadata | Writing /Info with the global setters or PdfWriter.SetDocInfo, plus custom keys. |
| Get XMP metadata | Parsing the catalog XMP packet and reading the pdf: info model. |
| Set XMP metadata | Building a pdf: model from the info dictionary and writing the packet back. |
| Get XML metadata | Dumping the raw XMP stream as XML, without parsing it. |
| Get custom XMP metadata | Reading namespaces xmputil does not wrap, through the go-xmp document. |
| Set custom XMP metadata | Writing properties in a namespace xmputil does not wrap. |
| Get PDF/A identification metadata | Reading the pdfaid: part and conformance level a file claims. |
| Get media management metadata | Reading xmpMM: document, instance and original document IDs. |
| Set media management metadata | Writing xmpMM: identifiers and derivation history. |