Sample code for 30+ languages & platforms
Xbase++

PDF Update or Add XML Metadata

Demonstrates how to add or update the XML metadata stored in a PDF.

Note: This example requires Chilkat v10.1.0 or later.

Chilkat Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL oPdf
LOCAL oXml
LOCAL oSbExisting
LOCAL nHasMetadata
LOCAL oDt
LOCAL cTs
LOCAL oSbDocId
LOCAL oSbInstanceId
LOCAL oSb

nSuccess := 0

//  This requires the Chilkat API to have been previously unlocked.
//  See Global Unlock Sample for sample code.

oPdf := CreateObject("Chilkat.Pdf")

//  Load a PDF file.
//  If the PDF file already has metadata, we'll update it.
//  Otherwise this example adds the metadata.
nSuccess := oPdf:LoadFile("qa_data/pdf/blank_with_metadata.pdf")
IF (nSuccess == 0)
    ? oPdf:LastErrorText
    oPdf:destroy()
    RETURN
ENDIF

oXml := CreateObject("Chilkat.Xml")
oSbExisting := CreateObject("Chilkat.StringBuilder")

nHasMetadata := oPdf:GetMetadata(oSbExisting)
IF (nHasMetadata == 1)
    oXml:LoadSb(oSbExisting, 1)
ELSE

    //  Otherwise create the bare minimum XMP metadata.
    oXml:Tag := "x:xmpmeta"
    oXml:AddAttribute("xmlns:x", "adobe:ns:meta/")
    oXml:AddAttribute("x:xmptk", "Adobe XMP Core 9.1-c001 79.675d0f7, 2023/06/11-19:21:16 ")
    oXml:UpdateAttrAt("rdf:RDF", 1, "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
    oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "rdf:about", "")
    oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "xmlns:xmp", "http://ns.adobe.com/xap/1.0/")
    oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "xmlns:dc", "http://purl.org/dc/elements/1.1/")
    oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "xmlns:xmpMM", "http://ns.adobe.com/xap/1.0/mm/")
    oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "xmlns:pdf", "http://ns.adobe.com/pdf/1.3/")
    oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "xmlns:xmpRights", "http://ns.adobe.com/xap/1.0/rights/")

    oDt := CreateObject("Chilkat.CkDateTime")
    oDt:SetFromCurrentSystemTime()
    cTs := oDt:GetAsTimestamp(1)

    oXml:UpdateChildContent("rdf:RDF|rdf:Description|xmp:ModifyDate", cTs)
    oXml:UpdateChildContent("rdf:RDF|rdf:Description|xmp:CreateDate", cTs)
    oXml:UpdateChildContent("rdf:RDF|rdf:Description|xmp:MetadataDate", cTs)

    oXml:UpdateChildContent("rdf:RDF|rdf:Description|xmp:CreatorTool", "My Custom Application")
    oXml:UpdateChildContent("rdf:RDF|rdf:Description|dc:format", "application/pdf")

    oSbDocId := CreateObject("Chilkat.StringBuilder")
    oSbDocId:Append("uuid:")
    oSbDocId:AppendUuid(1)
    oXml:UpdateChildContent("rdf:RDF|rdf:Description|xmpMM:DocumentID", oSbDocId:GetAsString())

    oSbInstanceId := CreateObject("Chilkat.StringBuilder")
    oSbInstanceId:Append("uuid:")
    oSbInstanceId:AppendUuid(1)
    oXml:UpdateChildContent("rdf:RDF|rdf:Description|xmpMM:InstanceID", oSbInstanceId:GetAsString())

ENDIF

//  Add our custom metadata tags to either the existing XML metdata, or the newly created metadata.
oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "xmlns:zf", "urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#")
oXml:UpdateAttrAt("rdf:RDF|rdf:Description", 1, "rdf:about", " ")
oXml:UpdateChildContent("rdf:RDF|rdf:Description|zf:ConformanceLevel", "BASIC")
oXml:UpdateChildContent("rdf:RDF|rdf:Description|zf:DocumentFileName", "ZZZZZZ-invoice.xml")
oXml:UpdateChildContent("rdf:RDF|rdf:Description|zf:DocumentType", "INVOICE")
oXml:UpdateChildContent("rdf:RDF|rdf:Description|zf:Version", "1.0")

//  Create a new PDF with the updated metadata.
oSb := CreateObject("Chilkat.StringBuilder")
oXml:GetXmlSb(oSb)
nSuccess := oPdf:UpdateMetadata(oSb, "c:/temp/qa_output/out.pdf")
IF (nSuccess == 1)
    ? "Success"
ELSE
    ? oPdf:LastErrorText
ENDIF

//  To see the metadata in Adobe Acrobat DC,
//  1) Open the PDF.
//  2) CTRL-D to show the Document Properties dialog.
//  3) In the dialog, click on the "Additional Metadata" button.
//  4) In the Additional Data dialog, click on "Advanced"
//  5) Expand the namespace tree for the metadata you added.

? "OK"

oPdf:destroy()
oXml:destroy()
oSbExisting:destroy()
oDt:destroy()
oSbDocId:destroy()
oSbInstanceId:destroy()
oSb:destroy()