Skip to content
Set XMP Media Management Metadata

Set XMP Media Management Metadata

Document.SetMediaManagement writes the xmpMM: namespace: the document and instance identifiers, the version number, and the DerivedFrom reference that links a new file to the one it came from. Most of it is generated for you, and the one decision you have to make is whether this write produces a new document or a new version of the same one.

NewDocumentIDEffect
false (default)Keeps the existing DocumentID. Use it when the file is being modified in place.
trueGenerates a fresh DocumentID and records the previous one under DerivedFrom. Use it when saving to a new file.

Either way a new InstanceID is generated, because the bytes changed.

Doing it

err := xmpDoc.SetMediaManagement(&xmputil.MediaManagementOptions{
    NewDocumentID: true,
})
if err != nil {
    return err
}

metadataBytes, err := xmpDoc.MarshalIndent("", "\t")
if err != nil {
    return err
}

metadataStream, err := core.MakeStream(metadataBytes, nil)
if err != nil {
    return err
}
return pdfWriter.SetCatalogMetadata(metadataStream)

Load the existing packet first with GetCatalogMetadata, core.GetStream and xmputil.LoadDocument, falling back to xmputil.NewDocument. It matters more here than elsewhere: SetMediaManagement reads the current DocumentID, InstanceID and VersionID off the packet to build DerivedFrom and to work out the next version. Start from an empty document and there is no history to derive from.

Passing nil options is valid and does the default thing: keep the document ID if there is one, generate one if not, generate a new instance ID, and increment the version.

VersionID increments automatically. If the existing value parses as an integer the next one is that plus one; if it does not parse, the number of recorded versions plus one is used; with no previous value it starts at 1. An explicit VersionID in the options is only honored when the packet has no version yet.

Limitations

Several documented fields on MediaManagementOptions are not read by the current implementation: OriginalDocumentID, DerivedFrom, ModifyComment, ModifyDate and Modifier. Setting them has no effect, and no error is returned. Only DocumentID, NewDocumentID, InstanceID and VersionID reach the packet.

That means xmpMM:OriginalDocumentID is not written by this call, and it is not generated either, despite what the field comment suggests. To set it, go through the go-xmp model:

mmModel, err := xmpmm.MakeModel(xmpDoc.GetGoXmpDocument())
if err != nil {
    return err
}
mmModel.OriginalDocumentID = xmp.GUID("56119f84-a812-484a-bb4c-61c7e7cb3265")

Version history is likewise not written. xmpMM:Versions reads back empty on a file whose metadata UniPDF produced, so the comment and modifier that belong to a version entry have nowhere to go.

DerivedFrom is only populated from what the loaded packet already held. A document with no previous DocumentID or InstanceID gets no DerivedFrom at all, even with NewDocumentID: true.

Run the example

The example copies the input to a writer, loads or creates the XMP packet, calls SetMediaManagement with NewDocumentID: true, and writes the packet to the output file. Inspect the result with the get media management metadata example. Note that the OriginalDocumentID, ModifyComment, ModifyDate and Modifier options it passes are ignored, so the original document ID will not appear in the output.

git clone https://github.com/unidoc/unipdf-examples.git
cd unipdf-examples/metadata
go run pdf_set_xmp_media_management_metadata.go input.pdf output.pdf

If this is your first time using UniPDF, follow the getting started guide to create an API key and set up your development environment.

View the full source
Last updated on