Mustang 1.6.0 with XMP access and Factur-X support
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
1.5.6
|
||||
1.6.0
|
||||
=====
|
||||
2019-02-03
|
||||
|
||||
closes #69.
|
||||
Closes #69.
|
||||
Corrected EN 16931 XMP Schema Extension header
|
||||
Can now read xmp metadata via ZUGFeRDImporter getXMP
|
||||
Exporting valid EN16931 Factur-X when version/profile set to 2/EN16931 mode
|
||||
|
||||
|
||||
1.5.5
|
||||
=====
|
||||
|
||||
Binary file not shown.
@@ -33,17 +33,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||
@@ -79,6 +73,7 @@ public class ZUGFeRDImporter {
|
||||
private boolean amountFound;
|
||||
private boolean extractAttempt = false;
|
||||
private boolean parsed = false;
|
||||
private String xmpString = null; // XMP metadata
|
||||
private static final Logger LOG = Logger.getLogger(ZUGFeRDImporter.class.getName());
|
||||
|
||||
/**
|
||||
@@ -99,6 +94,21 @@ public class ZUGFeRDImporter {
|
||||
}
|
||||
}
|
||||
|
||||
static String convertStreamToString(java.io.InputStream is) {
|
||||
// source https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java referring to
|
||||
// https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks
|
||||
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
/***
|
||||
* get xmp metadata of the PDF, null if not available
|
||||
* @return string
|
||||
*/
|
||||
public String getXMP() {
|
||||
return xmpString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a ZUGFeRD invoice from a PDF document represented by an input
|
||||
* stream. Errors are reported via exception handling.
|
||||
@@ -112,6 +122,10 @@ public class ZUGFeRDImporter {
|
||||
try (PDDocument doc = PDDocument.load(pdfStream)) {
|
||||
// PDDocumentInformation info = doc.getDocumentInformation();
|
||||
PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
|
||||
//start
|
||||
InputStream XMP=doc.getDocumentCatalog().getMetadata().exportXMPMetadata();
|
||||
|
||||
xmpString=convertStreamToString(XMP);
|
||||
etn = names.getEmbeddedFiles();
|
||||
if (etn == null) {
|
||||
return;
|
||||
@@ -134,6 +148,7 @@ public class ZUGFeRDImporter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void extractFiles(Map<String, PDComplexFileSpecification> names) throws IOException {
|
||||
for (String filename : names.keySet()) {
|
||||
|
||||
|
||||
@@ -378,6 +378,81 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta
|
||||
|
||||
String amount = zi.getAmount();
|
||||
|
||||
assertEquals("<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" +
|
||||
" <x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n" +
|
||||
" <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:xmpMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n" +
|
||||
" <xmpMM:InstanceID>uuid:6776DD95-DAF6-768E-DAE6-2697750D95C5</xmpMM:InstanceID>\n" +
|
||||
" <xmpMM:DocumentID>uuid:47380404-5938-FE2C-8F0B-B505DCE43BF5</xmpMM:DocumentID>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:zf=\"urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#\">\n" +
|
||||
" <zf:ConformanceLevel>BASIC</zf:ConformanceLevel>\n" +
|
||||
" <zf:DocumentFileName>ZUGFeRD-invoice.xml</zf:DocumentFileName>\n" +
|
||||
" <zf:DocumentType>INVOICE</zf:DocumentType>\n" +
|
||||
" <zf:Version>1.0</zf:Version>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:pdfaExtension=\"http://www.aiim.org/pdfa/ns/extension/\" xmlns:pdfaSchema=\"http://www.aiim.org/pdfa/ns/schema#\" xmlns:pdfaProperty=\"http://www.aiim.org/pdfa/ns/property#\">\n" +
|
||||
" <pdfaExtension:schemas>\n" +
|
||||
" <rdf:Bag>\n" +
|
||||
" <rdf:li rdf:parseType=\"Resource\">\n" +
|
||||
" <pdfaSchema:schema>ZUGFeRD PDFA Extension Schema</pdfaSchema:schema>\n" +
|
||||
" <pdfaSchema:namespaceURI>urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>\n" +
|
||||
" <pdfaSchema:prefix>zf</pdfaSchema:prefix>\n" +
|
||||
" <pdfaSchema:property>\n" +
|
||||
" <rdf:Seq>\n" +
|
||||
" <rdf:li rdf:parseType=\"Resource\">\n" +
|
||||
" <pdfaProperty:name>DocumentFileName</pdfaProperty:name>\n" +
|
||||
" <pdfaProperty:valueType>Text</pdfaProperty:valueType>\n" +
|
||||
" <pdfaProperty:category>external</pdfaProperty:category>\n" +
|
||||
" <pdfaProperty:description>name of the embedded XML invoice file</pdfaProperty:description>\n" +
|
||||
" </rdf:li>\n" +
|
||||
" <rdf:li rdf:parseType=\"Resource\">\n" +
|
||||
" <pdfaProperty:name>DocumentType</pdfaProperty:name>\n" +
|
||||
" <pdfaProperty:valueType>Text</pdfaProperty:valueType>\n" +
|
||||
" <pdfaProperty:category>external</pdfaProperty:category>\n" +
|
||||
" <pdfaProperty:description>INVOICE</pdfaProperty:description>\n" +
|
||||
" </rdf:li>\n" +
|
||||
" <rdf:li rdf:parseType=\"Resource\">\n" +
|
||||
" <pdfaProperty:name>Version</pdfaProperty:name>\n" +
|
||||
" <pdfaProperty:valueType>Text</pdfaProperty:valueType>\n" +
|
||||
" <pdfaProperty:category>external</pdfaProperty:category>\n" +
|
||||
" <pdfaProperty:description>The actual version of the ZUGFeRD XML schema</pdfaProperty:description>\n" +
|
||||
" </rdf:li>\n" +
|
||||
" <rdf:li rdf:parseType=\"Resource\">\n" +
|
||||
" <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>\n" +
|
||||
" <pdfaProperty:valueType>Text</pdfaProperty:valueType>\n" +
|
||||
" <pdfaProperty:category>external</pdfaProperty:category>\n" +
|
||||
" <pdfaProperty:description>The conformance level of the embedded ZUGFeRD data</pdfaProperty:description>\n" +
|
||||
" </rdf:li>\n" +
|
||||
" </rdf:Seq>\n" +
|
||||
" </pdfaSchema:property>\n" +
|
||||
" </rdf:li>\n" +
|
||||
" </rdf:Bag>\n" +
|
||||
" </pdfaExtension:schemas>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n" +
|
||||
" <pdfaid:part>3</pdfaid:part>\n" +
|
||||
" <pdfaid:conformance>B</pdfaid:conformance>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n" +
|
||||
" <xmp:CreateDate>2014-07-11T13:39:46+02:00</xmp:CreateDate>\n" +
|
||||
" <xmp:ModifyDate>2014-07-11T13:39:46+02:00</xmp:ModifyDate>\n" +
|
||||
" <xmp:CreatorTool>zugferd_invoice.java</xmp:CreatorTool>\n" +
|
||||
" <xmp:MetadataDate>2014-07-11T13:39:46+02:00</xmp:MetadataDate>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n" +
|
||||
" <pdf:Producer>PDFlib Personalization Server 9.0.3 (JDK 1.6/Mac OS X-10.6 64)</pdf:Producer>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" <rdf:Description rdf:about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n" +
|
||||
" <dc:title>\n" +
|
||||
" <rdf:Alt>\n" +
|
||||
" <rdf:li xml:lang=\"x-default\">ZUGFeRD Rechnung $Revision: 1.13 $</rdf:li>\n" +
|
||||
" </rdf:Alt>\n" +
|
||||
" </dc:title>\n" +
|
||||
" </rdf:Description>\n" +
|
||||
" </rdf:RDF>\n" +
|
||||
" </x:xmpmeta>\n" +
|
||||
"<?xpacket end=\"r\"?>", zi.getXMP());
|
||||
// this resembles the data written in MustangReaderWriterCustomXMLTest
|
||||
assertEquals(amount, "1005.55");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user