Sample code for 30+ languages & platforms
Zig

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 Zig Downloads

Zig
const std = @import("std");
const chilkat = @import("chilkat");

pub fn main(init: std.process.Init) !void {
    const alloc = init.arena.allocator();

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

    const pdf = try chilkat.Pdf.init();
    defer pdf.deinit();

    // Load a PDF file.
    // If the PDF file already has metadata, we'll update it.
    // Otherwise this example adds the metadata.
    pdf.loadFile("qa_data/pdf/blank_with_metadata.pdf") catch {
        std.debug.print("{s}\n", .{try pdf.getLastErrorText(alloc)});
        return;
    };

    const xml = try chilkat.Xml.init();
    defer xml.deinit();
    const sb_existing = try chilkat.StringBuilder.init();
    defer sb_existing.deinit();

    if (pdf.getMetadata(sb_existing)) {
        xml.loadSb(sb_existing, true) catch {};
    } else |_| {
        // Otherwise create the bare minimum XMP metadata.
        xml.setTag("x:xmpmeta");
        xml.addAttribute("xmlns:x", "adobe:ns:meta/") catch {};
        xml.addAttribute("x:xmptk", "Adobe XMP Core 9.1-c001 79.675d0f7, 2023/06/11-19:21:16 ") catch {};
        xml.updateAttrAt("rdf:RDF", true, "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#") catch {};
        xml.updateAttrAt("rdf:RDF|rdf:Description", true, "rdf:about", "") catch {};
        xml.updateAttrAt("rdf:RDF|rdf:Description", true, "xmlns:xmp", "http://ns.adobe.com/xap/1.0/") catch {};
        xml.updateAttrAt("rdf:RDF|rdf:Description", true, "xmlns:dc", "http://purl.org/dc/elements/1.1/") catch {};
        xml.updateAttrAt("rdf:RDF|rdf:Description", true, "xmlns:xmpMM", "http://ns.adobe.com/xap/1.0/mm/") catch {};
        xml.updateAttrAt("rdf:RDF|rdf:Description", true, "xmlns:pdf", "http://ns.adobe.com/pdf/1.3/") catch {};
        xml.updateAttrAt("rdf:RDF|rdf:Description", true, "xmlns:xmpRights", "http://ns.adobe.com/xap/1.0/rights/") catch {};

        const dt = try chilkat.DateTime.init();
        defer dt.deinit();
        dt.setFromCurrentSystemTime() catch {};
        const ts = try dt.getAsTimestamp(alloc, true);

        xml.updateChildContent("rdf:RDF|rdf:Description|xmp:ModifyDate", ts);
        xml.updateChildContent("rdf:RDF|rdf:Description|xmp:CreateDate", ts);
        xml.updateChildContent("rdf:RDF|rdf:Description|xmp:MetadataDate", ts);

        xml.updateChildContent("rdf:RDF|rdf:Description|xmp:CreatorTool", "My Custom Application");
        xml.updateChildContent("rdf:RDF|rdf:Description|dc:format", "application/pdf");

        const sb_doc_id = try chilkat.StringBuilder.init();
        defer sb_doc_id.deinit();
        sb_doc_id.append("uuid:") catch {};
        sb_doc_id.appendUuid(true) catch {};
        xml.updateChildContent("rdf:RDF|rdf:Description|xmpMM:DocumentID", try sb_doc_id.getAsString(alloc));

        const sb_instance_id = try chilkat.StringBuilder.init();
        defer sb_instance_id.deinit();
        sb_instance_id.append("uuid:") catch {};
        sb_instance_id.appendUuid(true) catch {};
        xml.updateChildContent("rdf:RDF|rdf:Description|xmpMM:InstanceID", try sb_instance_id.getAsString(alloc));
    }

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

    // Create a new PDF with the updated metadata.
    const sb = try chilkat.StringBuilder.init();
    defer sb.deinit();
    xml.getXmlSb(sb) catch {};
    if (pdf.updateMetadata(sb, "c:/temp/qa_output/out.pdf")) {
        std.debug.print("Success\n", .{});
    } else |_| {
        std.debug.print("{s}\n", .{try pdf.getLastErrorText(alloc)});
    }

    // 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.

    std.debug.print("OK\n", .{});
}