pdfa/zugferd2_add_xml_to_pdfa3b
ZUGFeRD 2: Add XML invoice to PDF.
Download PHP Code Switch to Java Code Show Output Show Input (zugferd2-invoice.xml) Show Input (ZUGFeRD2_invoice_noxml.pdf)
<?php
/*
* ZUGFeRD 2 Add XML Invoice to PDF:
* Import the pages of a plain PDF/A invoice with PDI and add a
* corresponding XML invoice to the output file. Note that the application
* must take care that the imported PDF invoice and the XML invoice match.
*
* Required software: PDFlib+PDI/PPS 9
* Required data: PDF/A input document, XML invoice file, XMP metadata
*/
/* This is where the data files are. Adjust as necessary. */
$searchpath = dirname(__FILE__,3)."/input";
/* By default annotations are also imported. In some cases this
* requires the Noto fonts for creating annotation appearance streams.
* We therefore set the searchpath to also point to the font directory.
*/
$fontpath = dirname(__FILE__,3)."/resource/font";
$infile = "ZUGFeRD2_invoice_noxml.pdf";
$title = "ZUGFeRD 2 Add XML Invoice to PDF";
$xmpfile = "ZUGFeRD2_extension_schema.xmp";
$xmlinvoicefile = "zugferd2-invoice.xml";
$attachmentname = "zugferd-invoice.xml";
try {
$p = new pdflib();
$p->set_option("searchpath={" . $searchpath . "}");
$p->set_option("searchpath={" . $fontpath . "}");
/* This means we must check return values of load_font() etc. */
$p->set_option("errorpolicy=return");
if ($p->begin_document("", "pdfa=PDF/A-3b metadata={filename={"
. $xmpfile . "}}") == -1)
throw new Exception("Error: " . $p->get_errmsg());
/* Open the input PDF */
$indoc = $p->open_pdi_document($infile, "");
if ($indoc == -1) {
throw new Exception("Error: " . $p->get_errmsg());
}
/*
* Clone PDF/A or PDF/X output intent
*/
if ($p->process_pdi($indoc, -1, "action=copyoutputintent") == -1) {
throw new Exception("Error: " . $p->get_errmsg());
}
$p->set_info("Creator", "PDFlib Cookbook");
$p->set_info("Title", $title);
$endpage = $p->pcos_get_number($indoc, "length:pages");
/* Loop over all pages of the input document */
for ($pageno = 1; $pageno <= $endpage; $pageno++) {
$page = $p->open_pdi_page($indoc, $pageno, "");
if ($page == -1) {
throw new Exception("Error: " . $p->get_errmsg());
}
/* Page size will be adjusted by fit_pdi_page() */
$p->begin_page_ext(0, 0, "width=a4.width height=a4.height");
/*
* Place the imported page on the output page, and adjust the
* page size
*/
$p->fit_pdi_page($page, 0, 0, "adjustpage");
$p->close_pdi_page($page);
$p->end_page_ext("");
}
/*
* Clone XMP metadata of input document if present. In order to
* be able to merge the XMP from the input document with the
* XMP needed according to ZUGFeRD for identifying the
* XML invoice, the XMP from the input document is supplied
* to the "metadata" option of PDF_end_document(), while the
* ZUGFeRD XMP was supplied to the "metadata" option of
* PDF_begin_document().
*/
$pfv_xmpfile = "/xmp/document.xmp";
if (!$p->pcos_get_string($indoc, "type:/Root/Metadata") == "stream") {
throw new Exception( "Error: XMP metadata missing in input document");
}
$xmp = $p->pcos_get_stream($indoc, "", "/Root/Metadata");
$p->create_pvf($pfv_xmpfile, $xmp, "");
$xmp_optlist = "metadata={filename=" . $pfv_xmpfile . "}";
$p->close_pdi_document($indoc);
/*
* Load the XML file for the invoice, and associate it with the
* document with relationship "Alternative". Also mark it as an
* attachment that can be retrieved with Acrobat's normal attachment
* dialog.
* The name of the attachment is explicitly specified, as the
* name of the disk file differs from the attachment name
* required by ZUGFeRD.
*/
$xml_invoice = $p->load_asset("Attachment", $xmlinvoicefile,
"mimetype=text/xml "
. "description={Rechnungsdaten im ZUGFeRD-XML-Format} "
. "relationship=Alternative documentattachment=true "
. "name=" . $attachmentname);
if ($xml_invoice == -1) {
throw new Exception("Error: " . $p->get_errmsg());
}
$p->end_document("associatedfiles={" . $xml_invoice . "} "
. $xmp_optlist);
$p->delete_pvf($pfv_xmpfile);
$buf = $p->get_buffer();
$len = strlen($buf);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=zugferd2_add_xml_to_pdfa3b.pdf");
print $buf;
} catch (PDFlibException $e) {
echo("PDFlib exception occurred:\n".
"[" . $e->get_errnum() . "] " . $e->get_apiname() .
": " . $e->get_errmsg() . "\n");
exit(1);
} catch (Throwable $e) {
echo("PHP exception occurred: " . $e->getMessage() . "\n");
exit(1);
}
$p = 0;