Question
“How can I alter the default metadata when exporting to PDF/A?”
Solution
Use the TppPDFDevice.OnGetPDFMetadata event to retrieve the default metadata and alter it to meet your specific needs. All metadata is in XML format so it is beneficial to use the Delphi built-in XML classes to edit the data. The following example shows how to alter the Conformance Level when exporting to the PDF/A-3 ZUGFeRD format.
Download: ZUGFeRDCustomMetaData.zip
1. First implement the OnGetPDFMetadata event in the TppReport.OnFileDeviceCreate event.
procedure TForm1.ppReport1FileDeviceCreate(Sender: TObject);
begin
//Assign the OnGetMetaData event of the PDF Device
if ppReport1.FileDevice is TppPDFDevice then
TppPDFDevice(ppReport1.FileDevice).OnGetPDFMetaData := ehPDF_GetMetaData;
end;
2. Next, we plan to use the built-in Delphi XML classes to edit the XML. For this example we will simply alter the value of an existing XML node. To do so, we will need a separate routine to recursively find the XML node we need.
function FindNodeByName(aNode: IXMLNode; const aName: String): IXMLNode;
var
liIndex: Integer;
begin
Result := nil;
if aNode = nil then Exit;
if (aNode.NodeName = aName) then
Result := aNode
else if (aNode.HasChildNodes) then
begin
liIndex := 0;
while (Result = nil) and (liIndex < aNode.ChildNodes.Count) do
begin
Result := FindNodeByName(aNode.ChildNodes[liIndex], aName);
liIndex := liIndex + 1;
end;
end;
end;
3. Finally, we put everything together to alter a specific node in the existing metadata to meet our needs. The following code alters the “zf:ConformanceLevel” node to have a value of “COMFORT” instead of the default “BASIC”.
procedure TForm1.ehPDF_GetMetaData(Sender: TObject; aMetaData: TStrings);
var
lXMLDoc: TXMLDocument;
lNodeElement: IXMLNode;
begin
lXMLDoc := TXMLDocument.Create(Self);
//Load the existing XML text into the XML Document object
lXMLDoc.LoadFromXML(aMetaData.Text);
//Find the node that needs to be edited
lNodeElement := FindNodeByName(lXMLDoc.DocumentElement,'zf:ConformanceLevel');
//Update the node value
if lNodeElement <> nil then
lNodeElement.Text := 'COMFORT';
//Save the updated XML back to the PDF
aMetaData.Text := lXMLDoc.XML.Text;
lXMLDoc.Free;
end;