ZUGFeRD / mustangproject

Open Source Java e-Invoicing library, validator and tool (Factur-X/ZUGFeRD, UNCEFACT/CII XRechnung)
http://www.mustangproject.org
Apache License 2.0
168 stars 99 forks source link

DocumentException ZUGFeRDValidator #300

Open Ulukai opened 1 year ago

Ulukai commented 1 year ago

Wir haben das ZUGFeRD mustangproject schon seit einigen Jahren bei uns über maven integriert und nun möchten wir auch den ZUGFeRDValidator einbinden. Dabei bin ich auf ein Problem gestoßen:

org.dom4j.DocumentException: Error on line 1 of document  : The processing instruction target matching "[xX][mM][lL]" is not allowed.
    at org.dom4j.io.SAXReader.read(SAXReader.java:511)
    at org.dom4j.DocumentHelper.parseText(DocumentHelper.java:279)
    at org.mustangproject.validator.ZUGFeRDValidator.validate(ZUGFeRDValidator.java:234)
Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 94; The processing instruction target matching "[xX][mM][lL]" is not allowed.
    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)
    at org.apache.xerces.impl.XMLScanner.scanPIData(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanPIData(Unknown Source)
    at org.apache.xerces.impl.XMLScanner.scanPI(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at org.dom4j.io.SAXReader.read(SAXReader.java:494)
    ... 56 more

Folgendes ist mir dabei aufgefallen: /org/mustangproject/validator/PDFValidator.java:117 pdfReport = reportStream.toString("utf-8").replaceAll("<\\?xml version=\"1\\.0\" encoding=\"utf-8\"\\?>", "");

Dieses replaceAll() greift nicht, wenn die XML-Deklaration mit Single-Quotes geschrieben wird, sprich <?xml version='1.0' encoding='utf-8'?>, was bei mir aber gerade der Fall ist. Da im XML-Standard beide Schreibweisen erlaubt sind, macht es wahrscheinlich Sinn die Regex zu erweitern, damit beide Zeichen erkannt werden.

jstaerk commented 1 year ago

sehr interessant, danke für den report

jstaerk commented 1 year ago

hab einen test gebaut & eingecheckt mit single quotes, der läuft durch. Das erwähnte replaceAll greift auch nur auf dem verapdf-ausgabereport weil da was konkateniert werden muss.

Ulukai commented 1 year ago

Das erwähnte replaceAll greift auch nur auf dem verapdf-ausgabereport

Ja, das habe ich auch gemeint. Genau dieser verapdf-Ausgabereport wird aus irgendeinem Grund - evtl. irgendwelchen dependencies, Versionsunterschieden - mit Single-Quote ausgeliefert. Und da dann die erwähnte regex nicht greift und der ZUGFeRDValidator den verapdf-Ausgabereport mit eigenen Sachen konkateniert, bleibt diese XML-Deklaration irgendwo mitten im ZUGFeRDValidator-Ausgabereport stehen, was dann in ZUGFeRDValidator.java:234 die DocumentException verursacht.

jstaerk commented 1 year ago

kannst du den report mal anhängen? Welche version von Verapdf hat er sich denn da gezogen? Und reden wir von Windows, Linux oder ganz was anderem?

Ulukai commented 1 year ago

Windows 10 Java 11 (AdoptOpenJDK)

ValidationLog.txt

image

jstaerk commented 1 year ago

komisch das ist eigentlich korrekt, wie kann ich das reproduzieren?

Ulukai commented 1 year ago

Das weiß ich nicht! Ich kann es reproduzieren, indem ich in unserer Anwendung z.B. das angehängte PDF versuche zu validieren:

// Validierung
ZUGFeRDValidator zfv = new ZUGFeRDValidator();
String validationResult = zfv.validate(jasperPDF.getAbsolutePath());

20230001.pdf