Ga naar inhoud
getnextpdf.com

Wat een PDF over zichzelf weet: metadata en het XMP-packet

Spec: ISO 16684-1:2019Spec: ISO 32000-2

Open een moderne PDF en hij kan je twee keer over zichzelf vertellen. Er is een kleine, oude sleutel/waarde-lijst die de Document Information dictionary heet, en er kan een blok XML zijn — het XMP-packet — dat grotendeels hetzelfde zegt in een rijkere, gestructureerde vorm. Deze pagina gaat over die twee parallelle systemen, waarom ze allebei blijven bestaan, en waarom archiverings- en zoekpijplijnen erop staan dat ze het eens zijn.

Het korte antwoord op de titel: een PDF kent zijn titel, auteur, onderwerp, trefwoorden, het programma dat hem maakte, en wanneer. Hij slaat die kennis op twee plaatsen tegelijk op, en de interessante engineering zit in het eerlijk houden ervan.

Metadata is het deel van een document dat een mens zelden ziet en een machine bijna altijd leest. De bestandsvoorvertoning van je besturingssysteem, een digital-asset-manager, een bibliotheekcatalogus, een zoekindex, een e-discovery-tool — veel ervan lezen de metadata vóór, of naast, de documenttekst, en vertrouwen op wat erin staat.

Dus wanneer de twee systemen het oneens zijn — de Info dictionary noemt de ene auteur en het XMP-packet de andere — kiest iets verderop in de keten er een, en jij mag niet kiezen welke. Een zoekindex kan de verkeerde titel tonen. Een archiveringsvalidator kan het bestand ronduit afwijzen. De afwijking is onzichtbaar totdat een pijplijn erover struikelt, wat het slechtste moment is om het te ontdekken.

  • Een PDF kan metadata in twee parallelle systemen dragen: de oudere Document Information dictionary en het moderne XMP-packet van RDF/XML.
  • Het XMP-packet is verpakt in een xpacket-processing instruction — een begin-header en een end-trailer — zodat een tool het kan vinden en zelfs ter plekke kan herschrijven zonder het hele bestand opnieuw te parsen.
  • Eigenschappen leven in namespaces: dc (Dublin Core) voor titel en maker, xmp voor aanmaak- en wijzigingsdatums, pdf voor de producer, xmpMM voor documentidentiteit en -historie.
  • PDF/A vereist XMP-metadata, en DocInfo-vermeldingen die een XMP-equivalent hebben moeten daarmee overeenkomen — een meningsverschil is een validatiefout.
  • NextPDF behandelt de twee als één taak: het schrijft beide, leest XMP terug en bewaakt de grootte van het packet, met fail-closed in plaats van het uitsturen van een misvormd bestand.

De eerlijke formulering is dat dit een synchronisatieprobleem is verkleed als een opmaakprobleem. De Document Information dictionary (Spec: ISO 32000-2, §14.3.3), waarnaar vanuit de trailer wordt verwezen door de /Info-vermelding, is een platte lijst van strings: Title, Author, Subject, Keywords, Creator, Producer en een paar datums. Het is eenvoudig, het dateert van vóór XML, en het reist nog steeds mee in vrijwel elk bestand omdat zoveel tools het nog steeds als eerste lezen.

Het XMP-packet (Spec: ISO 16684-1:2019, §7) is de moderne helft. Het is een XML-document — RDF/XML, om precies te zijn — dat het bestand modelleert als een set benoemde eigenschappen gegroepeerd in schema’s, waarbij elk schema aan een namespace is gebonden (Spec: ISO 16684-1:2019, §6). Die structuur is wat de platte dictionary niet kan: een waarde kan een geordende lijst zijn, een taalgetagd alternatief (“titel in het Engels, titel in het Frans”), of een gestructureerd record. In een PDF leeft die XML in een metadata stream die aan de document catalog is gehecht (Spec: ISO 32000-2, §14.3.2), wat de canonieke plek is waar een actuele reader kijkt.

Drie details zijn het ontleden waard, want daar maken tools het packet verkeerd.

De wrapper. Een XMP-packet is omsloten door een processing instruction zodat, in formaten waar het packet als rechtstreeks doorzoekbare bytes wordt opgeslagen, een programma de metadata kan lokaliseren zonder een volledige parse; specifiek in PDF is de catalog-metadata stream de canonieke locator. De begin-header draagt een byte-order mark die de tekstcodering declareert; de end-trailer draagt een vlag die aangeeft of het packet alleen-lezen is of ter plekke mag worden bewerkt. Wanneer het beschrijfbaar is, laat de serializer een reeks witruimte-padding na de XML zodat een editor de inhoud iets kan laten groeien zonder elke daaropvolgende byte te verschuiven. Die padding is geen versiering — het is wat het ter plekke bewerken van metadata mogelijk maakt.

De namespaces. Een eigenschap is alleen betekenisvol ten opzichte van zijn namespace, en een handvol is bijna universeel. Dublin Core (dc) bevat de titel en de maker. Het XMP-basisschema (xmp) bevat de aanmaak- en wijzigingsdatums en het authoring-tool. Het PDF-schema (pdf) bevat de producer-string en de trefwoorden. Het media-management-schema (xmpMM) bevat de identiteit van het document en zijn afleidingshistorie — het spoor dat zegt “dit bestand komt voort uit dat bestand.” Het eens worden over deze namespace-URI’s en eigenschapsnamen — meestal getoond met conventionele prefixen — is het hele doel van de core schemas (Spec: ISO 16684-1:2019, Annex B); twee tools die beide de Dublin Core-titeleigenschap spreken, werken samen zonder voorafgaande afspraak.

De consistentieregel. Omdat beide systemen dezelfde eigenschap kunnen benoemen, kunnen ze het oneens zijn. De archiveringsprofielen weigeren dat toe te staan. Een PDF/A-bestand moet een XMP-metadata stream dragen, en elke Document Information-vermelding die een XMP-equivalent heeft, moet daarmee overeenkomen; een meningsverschil is een validatiefout. De praktische les is direct: in een archiveringspijplijn zijn de twee geen onafhankelijke velden maar één feit dat twee keer is geschreven, en ze moeten gelijk blijven lopen.

NextPDF behandelt alle drie als één zorg. De metadataflow is één pad, niet twee concurrerende paden.

  1. Collect the values onceTitle, author, subject, keywords, creator, producer and dates are set on the document a single time, so there is one source of truth, not two.
  2. Write the Info dictionaryThe DocInfo writer emits the legacy Title, Author, Subject, Keywords, Creator, Producer and date entries that older tools read first.
  3. Build the XMP packetThe XMP builder serializes the same values as RDF/XML under dc, xmp, pdf and xmpMM, wrapped in the xpacket header and trailer with writable padding.
  4. Guard the packet sizeBefore serialization is accepted, the engine checks the packet against a size bound and fails closed with a typed exception rather than emit a malformed or oversized stream.
  5. Read XMP back to verifyThe XMP reader parses the packet so a pipeline can confirm the engine wrote the metadata it was given — the kind of check an archival validator builds on.
Hoe NextPDF de twee metadatasystemen van een document consistent houdt: één set waarden wordt zowel naar de Info dictionary als naar het XMP-packet geschreven, het packet wordt op grootte bewaakt voordat het wordt geserialiseerd, en hetzelfde packet kan worden teruggelezen zodat een pijplijn kan bevestigen dat de metadata is geserialiseerd zoals bedoeld.

De vorm hieronder zet metadata één keer en laat de engine die over beide systemen uitwaaieren, en leest dan de XMP-titel terug zodat een pijplijn die kan inspecteren. De size guard is de regel die “waarschijnlijk goed” verandert in “aantoonbaar geweigerd als dat niet zo is.”

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Metadata\Exception\XmpPacketTooLargeException;
$document = Document::createStandalone();
// Set the values ONCE. The engine writes them to both the Info dictionary
// and the XMP packet, so the two systems cannot drift apart at the source.
$document->setTitle('Annual Report 2026');
$document->setAuthor('Records Office');
$document->setSubject('Statutory annual filing');
$document->setKeywords('annual report, statutory, 2026');
try {
// Building the document serializes the XMP packet. The engine guards the
// packet size and fails closed: a packet that exceeds the bound is a
// typed exception, never a silently truncated or malformed stream.
$bytes = $document->getPdfData();
} catch (XmpPacketTooLargeException $e) {
// Decide deliberately: trim the metadata, not the guarantees.
error_log('XMP packet exceeded the size bound: ' . $e->getMessage());
throw $e;
}
// Read the packet back. This confirms the XMP the engine serialized carries the
// value you set — the kind of integrity check an archival pipeline runs before
// it trusts the file. (Both systems are written from one source, so they agree
// by construction; reading the XMP back proves it serialized as intended.)
$xmp = $document->readXmpMetadata($bytes);
$xmpTitle = $xmp->get('dc', 'title'); // 'Annual Report 2026'
if ($xmpTitle !== $document->getTitle()) {
throw new \RuntimeException('XMP title does not match the value that was set.');
}

Er is hier geen pad waar de twee systemen stilletjes uiteenlopen: de waarden komen één keer binnen, beide writers verbruiken dezelfde bron, en de reader laat een pijplijn het resultaat controleren.

De veelvoorkomende overtuiging is dat de Info dictionary verouderd is en je hem kunt negeren. Dat kan niet — nog niet. Een grote hoeveelheid geïnstalleerde software, waaronder sommige bestandsvoorvertoningen van besturingssystemen en oudere archiveringstools, leest nog steeds de Info dictionary als eerste of als enige. Hem weglaten moderniseert een bestand niet; het laat het bestand er naamloos uitzien voor alles wat XMP nog niet heeft overgenomen.

De spiegelbeeldfout is de twee behandelen als onafhankelijke velden die je apart invult. Dat is precies hoe ze uiteenlopen. Het zijn twee serialisaties van één feit. Schrijf ze vanuit één bron, of accepteer dat iets verderop in de keten de versie kiest die je niet bedoelde.

  • NextPDF schrijft beide systemen en leest XMP terug. Zijn bereik is de XMP-metadata builder, de DocInfo-writer en een XMP-reader. Het belooft niet een algemene RDF/XML-query-engine te zijn.
  • Het XMP-packet wordt op grootte bewaakt en faalt fail-closed. Een packet dat de grens van de engine overschrijdt, werpt een getypeerde exception. De engine zal geen afgekapt, voorbij-de-limiet-gepad of anderszins misvormd packet uitsturen om een te groot verzoek te laten “passen.”
  • Consistentie wordt afgedwongen tijdens het schrijven vanuit één bron; het is geen magische verzoening van een bestand dat je niet hebt geproduceerd. Als je een document importeert waarvan de twee systemen het al oneens zijn, is het oplossen daarvan jouw beslissing, niet een impliciete herschrijving.
  • De metadatavereisten van PDF/A maken deel uit van het archiveringsprofiel. Deze pagina legt de regel uit; het conformiteitsoordeel hoort bij een validator, zoals altijd bij archiveringswerk. Zie de archiveringspagina voor die grens.

De metadata builder, de DocInfo-writer en de XMP-reader zijn Core-capaciteiten. De eerlijke kanttekening zit bij de size guard, hieronder.

Metadata: Info dictionary and XMP packet — edition availability
EditionAvailability
Core

The XMP metadata builder, the Document Information dictionary writer, and the XMP reader ship in Core, with the size guard that fails closed on an oversized packet — including the PDF/A conformance output and validation that make the XMP metadata stream mandatory and require DocInfo to match it.

Pro

Adds batch and templated metadata workflows over the same Core writer and reader.

Enterprise

Adds the broader conformance policy and reporting surface across a document estate.

  • Document Information dictionary — de oudere, platte sleutel/waarde-metadata waarnaar vanuit de trailer wordt verwezen door de /Info-vermelding: Title, Author, Subject, Keywords, Creator, Producer en datums. Dateert van vóór XMP; nog steeds breed gelezen.
  • XMP — het Extensible Metadata Platform, een XML-formaat (RDF/XML) voor het beschrijven van een resource met benoemde eigenschappen gegroepeerd in schema’s. Gestandaardiseerd als ISO 16684-1.
  • xpacket — de processing instruction die een XMP-packet omhult, met een begin-header (coderingsmarkering) en een end-trailer (alleen-lezen- of beschrijfbaar-vlag), zodat een tool het packet kan lokaliseren en bewerken zonder een volledige parse.
  • Namespace / schema — een benoemde woordenschat van eigenschappen gebonden aan een URI. Gangbare prefixen: dc (Dublin Core), xmp (XMP basic), pdf (PDF-specifiek), xmpMM (media management / documentidentiteit).
  • Metadata stream — het PDF-object, gehecht aan de document catalog, dat het XMP-packet draagt. De canonieke locatie die een moderne reader als eerste controleert.
  • PDF/A — de archief-PDF-profielfamilie (ISO 19005). Het vereist een XMP-metadata stream en eist dat elke Document Information-vermelding met een XMP-equivalent daarmee overeenkomt, anders mislukt de validatie.