Embedding files and adding custom XMP with PDF/A-3b
As of 2025, electronic invoicing based on Zugferd will be mandatory in Germany which means that some of our customers will have to embed different file types in a PDF/A-3. Additionally, sometimes, when writing files with any of the PDF/A presets or PDFVersion parameter set, Mako will drop XMP properties if they cannot be parsed correctly.
This C# example demonstrates how to create a PDF/A-3b file with a custom .xml file attachment and custom XMP metadata that is preserved in the PDF output. It uses the XmpCore library to generate the custom XMP, with a minor modification to ensure compatibility, and subsequently merged with the mandatory PDF/A-3b metadata. The example makes use of the setIgnoreXmp(false) feature introduced inMako 8, which ensures that the custom XMP is preserved in the final output.
Custom XMP C# Example
C#
/* --------------------------------------------------------------------------------
* <copyright file="Program.cs" company="Global Graphics Software Ltd">
* Copyright (c) 2025 Global Graphics Software Ltd. All rights reserved.
* </copyright>
* <summary>
* This example is provided on an "as is" basis and without warranty of any kind.
* Global Graphics Software Ltd. does not warrant or make any representations
* regarding the use or results of use of this example.
* </summary>
* ---------------------------------------------------------------------------------
*/
using JawsMako;
using XmpCore;
using XmpCore.Impl;
using XmpCore.Options;
namespace XMPissue;
internal class Program
{
static int Main(string[] args)
{
try
{
var testFilepath = "..\\..\\..\\..\\TestFiles\\";
Directory.CreateDirectory(testFilepath);
using var mako = IJawsMako.create();
IJawsMako.enableAllFeatures(mako);
using var factory = mako.getFactory();
var assembly = IDocumentAssembly.create(mako);
var document = IDocument.create(mako);
var page = IPage.create(mako);
var content = IDOMFixedPage.create(factory, 210 / 25.4 * 96, 297 / 25.4 * 96); // XPS units
page.setContent(content);
document.appendPage(page);
assembly.appendDocument(document);
// Create ZugFERD XMP
var xmp = XmpMetaFactory.Create();
XmpMetaFactory.SchemaRegistry.RegisterNamespace(@"urn:ferd:pdfa:invoice:rc#", "zf");
var namespaces = XmpMetaFactory.SchemaRegistry.Namespaces;
xmp.SetProperty(@"urn:ferd:pdfa:invoice:rc#", "DocumentType", "INVOICE");
var options = new SerializeOptions();
options.OmitPacketWrapper = true;
options.UseCanonicalFormat = true;
var newXmp = XmpSerializerHelper.SerializeToString((XmpMeta)xmp, options);
newXmp = newXmp[1..]; //remove leading question mark
// Prepare XMP packet for Mako
var pair = mako.getTempStore().createTemporaryReaderWriterPair();
var newXmpStreamReader = pair.inputStream;
var newXmpStreamWriter = pair.outputStream;
newXmpStreamWriter.open();
newXmpStreamWriter.completeWrite(newXmp);
newXmpStreamReader.close();
assembly.setXmpPacket(newXmpStreamReader);
// Add attachment
IRAInputStream fileStream = IInputStream.createFromFile(mako, testFilepath + "factur-x.xml");
if (fileStream is not null && fileStream.open())
{
var metadata = new IFileSpecAsEmbeddedData.Data();
metadata.fileName = "faktur-x.xml";
metadata.description = "ZUGFeRD-invoice";
metadata.mimeType = "text/xml";
metadata.modificationDate = DateTime.Now.ToString();
metadata.fileSize = (ulong)fileStream.IRAStream_length();
metadata.fileDataStream = fileStream;
IFileSpecAsEmbeddedData embeddedFile = IFileSpecAsEmbeddedData.createInstance(mako.getFactory(), metadata);
if (embeddedFile is not null)
document.addEmbeddedStream(embeddedFile);
}
var output = IPDFOutput.create(mako);
output.setPreset("PDF/A-3b");
output.setIgnoreXmp(false);
output.setValidateXmp(false);
output.writeAssembly(assembly, testFilepath + "zugferd.pdf");
}
catch (MakoException e)
{
Console.WriteLine($"Exception thrown: {e.m_errorCode}: {e.m_msg}");
}
catch (Exception e)
{
Console.WriteLine($"Exception thrown: {e}");
}
return 0;
}
}
JavaScript errors detected
Please note, these errors can depend on your browser setup.
If this problem persists, please contact our support.