diff --git a/libraryBasic/src/test/java/org/mustangproject/ZUGFeRD/ZF2InvoiceImporterTest.java b/libraryBasic/src/test/java/org/mustangproject/ZUGFeRD/ZF2InvoiceImporterTest.java
index 12ef39d3..26098f4e 100644
--- a/libraryBasic/src/test/java/org/mustangproject/ZUGFeRD/ZF2InvoiceImporterTest.java
+++ b/libraryBasic/src/test/java/org/mustangproject/ZUGFeRD/ZF2InvoiceImporterTest.java
@@ -39,7 +39,7 @@ import junit.framework.TestSuite;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ZF2InvoiceImporterTest extends TestCase {
- final String TARGET_PDF = "./target/testout-ZF2New.pdf";
+ final String TARGET_PDF = "./target/testout-ZF2new.pdf";
public void testInvoiceImport() {
diff --git a/libraryExtended/ZUV-Architektur.graphml b/libraryExtended/ZUV-Architektur.graphml
new file mode 100644
index 00000000..f1e1e09d
--- /dev/null
+++ b/libraryExtended/ZUV-Architektur.graphml
@@ -0,0 +1,993 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PDF+XML
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ZUGFeRD
+
+
+
+
+
+
+
+
+
+ Folder 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schematron files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schema files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Codelist XMLs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EN16931
+
+
+
+
+
+
+
+
+
+ Folder 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CEF Codelist Excel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CEN Schematron
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UN/CEFACT
+
+
+
+
+
+
+
+
+
+ Folder 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schema files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XML Report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ZUV
+
+
+
+
+
+
+
+
+
+ Folder 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PH-Schematron
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XML
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Metadata
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Metadata check
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XSLT files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XSLT files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Additional data
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Additional data check
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PH-Schematron
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mustangproject
+
+
+
+
+
+
+
+
+
+ Folder 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PDFBox
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mustang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ VeraPDF
+
+
+
+
+
+
+
+
+
+ Folder 6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ VeraPDF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schema check
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XSLT files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PH-Schematron
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XRechnung
+
+
+
+
+
+
+
+
+
+ Folder 7
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schematron
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libraryExtended/ZUV-Architektur.svg b/libraryExtended/ZUV-Architektur.svg
new file mode 100644
index 00000000..f3eda531
--- /dev/null
+++ b/libraryExtended/ZUV-Architektur.svg
@@ -0,0 +1,1117 @@
+
diff --git a/libraryExtended/pom.xml b/libraryExtended/pom.xml
index 1df61ee1..4527336e 100644
--- a/libraryExtended/pom.xml
+++ b/libraryExtended/pom.xml
@@ -68,7 +68,7 @@
com.helger
ph-schematron
- 5.0.8
+ 5.6.0
org.mustangproject
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/EPart.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/EPart.java
index 827f2da5..486bd65e 100644
--- a/libraryExtended/src/main/java/org/mustangproject/library/extended/EPart.java
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/EPart.java
@@ -1,5 +1,5 @@
package org.mustangproject.library.extended;
public enum EPart {
- xml, pdf, none
+ fx, xr, pdf, none
}
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/Main.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/Main.java
new file mode 100644
index 00000000..06d05c7a
--- /dev/null
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/Main.java
@@ -0,0 +1,94 @@
+package org.mustangproject.library.extended;
+
+import java.io.File;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sanityinc.jargs.CmdLineParser;
+import com.sanityinc.jargs.CmdLineParser.Option;
+
+public class Main {
+
+ static final ClassLoader cl = Main.class.getClassLoader();
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Main.class.getCanonicalName()); // log output is
+ // ignored for the
+ // time being
+
+ public void run(String[] args) {
+
+ /***
+ * prerequisite is a mvn generate-resources
+ */
+
+ CmdLineParser parser = new CmdLineParser();
+ Option actionOption = parser.addStringOption('a', "action");
+ Option filenameOption = parser.addStringOption('f', "Filename");
+
+ Option licenseOption = parser.addBooleanOption('l', "license");
+ Option helpOption = parser.addBooleanOption('h', "help");
+ Option logAppendOption = parser.addStringOption("logAppend");
+
+ boolean optionsRecognized = false;
+
+ try {
+ parser.parse(args);
+ } catch (CmdLineParser.OptionException e) {
+ System.err.println(e.getMessage());
+ System.exit(-2);
+ }
+
+ Boolean helpRequested = parser.getOptionValue(helpOption);
+
+ if (parser.getOptionValue(licenseOption) != null) {
+ optionsRecognized = true;
+
+ System.out.println("Copyright 2018 Jochen Stärk\n" + "\n"
+ + "Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+ + "you may not use this file except in compliance with the License.\n"
+ + "You may obtain a copy of the License at\n" + "\n"
+ + " http://www.apache.org/licenses/LICENSE-2.0\n" + "\n"
+ + "Unless required by applicable law or agreed to in writing, software\n"
+ + "distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+ + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+ + "See the License for the specific language governing permissions and\n"
+ + "limitations under the License.\n\n\n\n\n"
+ + "This software is embedding the PDF/A validator VeraPDF, "
+ + "http://verapdf.org/, which is available under GPL and MPL licenses.");
+
+ System.exit(0);
+ }
+ String filename = parser.getOptionValue(filenameOption);
+ String action = parser.getOptionValue(actionOption);
+ File logdir = new File("log");
+ if (!logdir.exists() || !logdir.isDirectory() || !logdir.canWrite()) {
+ System.err.println("Need writable subdirectory 'log' for log files.");
+ }
+
+ if ((action != null) && (action.equals("validate"))) {
+ ZUGFeRDValidator zfv=new ZUGFeRDValidator();
+ zfv.setLogAppend(parser.getOptionValue(logAppendOption));
+ System.out.println(zfv.validate(filename));
+
+ optionsRecognized = !zfv.hasOptionsError();
+ if (!zfv.wasCompletelyValid()) {
+ System.exit(-1);
+ }
+
+ }
+
+ if ((!optionsRecognized) || (helpRequested != null && helpRequested.booleanValue())) {
+ System.out.println(
+ "usage: --action validate -f | [-l (shows license)][--logAppend \"String to be appended to validation result log\"]");
+ System.exit(-1);
+ }
+
+ }
+
+ public static void main(String[] args) {
+ new Main().run(args);
+ }
+
+
+}
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationContext.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationContext.java
index e71fd702..29397fe4 100644
--- a/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationContext.java
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationContext.java
@@ -1,5 +1,6 @@
package org.mustangproject.library.extended;
+import java.util.ArrayList;
import java.util.Vector;
import org.slf4j.Logger;
@@ -115,6 +116,19 @@ public class ValidationContext {
return res;
}
+ /***
+ *
+ * @return the unique error types as comma separated string
+ */
+ public String getCSVResult() {
+ ArrayList errorcodes = new ArrayList();
+ for (ValidationResultItem validationResultItem : results) {
+ String errorCodeStr=Integer.toString(validationResultItem.getSection());
+ errorcodes.add(errorCodeStr);
+ }
+ return String.join(",", errorcodes);
+ }
+
public void setInvalid() {
isValid = false;
}
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationResultItem.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationResultItem.java
index 870aba6e..67804850 100644
--- a/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationResultItem.java
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/ValidationResultItem.java
@@ -22,10 +22,12 @@ public class ValidationResultItem {
private EPart part;
+ private XMLTools xt;
public ValidationResultItem(ESeverity sev, String msg) {
setSeverity(sev);
setMessage(msg);
+ xt=new XMLTools();
}
public ValidationResultItem setMessage(String msg) {
message=msg;
@@ -72,16 +74,16 @@ public class ValidationResultItem {
additionalAttributes+=" type=\""+section+"\"";
}
if (location!=null) {
- additionalAttributes+=" location=\""+XMLTools.encodeAttribute(location)+"\"";
+ additionalAttributes+=" location=\""+xt.escapeAttributeEntities(location)+"\"";
}
if (criterion!=null) {
- additionalAttributes+=" criterion=\""+XMLTools.encodeAttribute(criterion)+"\"";
+ additionalAttributes+=" criterion=\""+xt.escapeAttributeEntities(criterion)+"\"";
}
if (stacktrace!=null) {
- additionalContents+=""+XMLTools.encodeAttribute(stacktrace)+"";
+ additionalContents+=""+xt.escapeAttributeEntities(stacktrace)+"";
}
hasBeenOutputted=true;
- return "<"+tagname+additionalAttributes+">"+XMLTools.encodeXML(message+additionalContents)+""+tagname+">";
+ return "<"+tagname+additionalAttributes+">"+xt.escapeElementEntities(message+additionalContents)+""+tagname+">";
}
public String getXMLOnce() {
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/Validator.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/Validator.java
index 46540ff7..ff3e4ec3 100644
--- a/libraryExtended/src/main/java/org/mustangproject/library/extended/Validator.java
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/Validator.java
@@ -57,4 +57,4 @@ public abstract class Validator {
-}
\ No newline at end of file
+}
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLTools.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLTools.java
index 69edb6c1..ac3936e3 100644
--- a/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLTools.java
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLTools.java
@@ -1,50 +1,13 @@
package org.mustangproject.library.extended;
+import org.dom4j.io.XMLWriter;
-public class XMLTools {
- public static String encodeXML(CharSequence s) {
- StringBuilder sb = new StringBuilder();
- int len = s.length();
- for (int i=0;i= 0xd800 && c <= 0xdbff && i + 1 < len) {
- c = ((c-0xd7c0)<<10) | (s.charAt(++i)&0x3ff); // UTF16 decode
- }
- if (c < 0x80) { // ASCII range: test most common case first
- if (c < 0x20 && (c != '\t' && c != '\r' && c != '\n')) {
- // Illegal XML character, even encoded. Skip or substitute
- sb.append("�"); // Unicode replacement character
- } else {
- switch(c) {
- case '&': sb.append("&"); break;
- case '>': sb.append(">"); break;
- case '<': sb.append("<"); break;
- // Uncomment next two if encoding for an XML attribute
-// case '\'' sb.append("'"); break;
-// case '\"' sb.append("""); break;
- // Uncomment next three if you prefer, but not required
-// case '\n' sb.append("
"); break;
-// case '\r' sb.append("
"); break;
-// case '\t' sb.append(" "); break;
-
- default: sb.append((char)c);
- }
- }
- } else if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) {
- // Illegal XML character, even encoded. Skip or substitute
- sb.append("�"); // Unicode replacement character
- } else {
- sb.append("");
- sb.append(Integer.toHexString(c));
- sb.append(';');
- }
- }
- return sb.toString();
+public class XMLTools extends XMLWriter {
+ public String escapeAttributeEntities(String s) {
+ return super.escapeAttributeEntities(s);
}
- public static String encodeAttribute(String s) {
- String res=s.replace("\n", "").replace("\r", "").replace("\"", "");
-
- return XMLTools.encodeXML(res);
+ public String escapeElementEntities(String s) {
+ return super.escapeElementEntities(s);
}
diff --git a/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLValidator.java b/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLValidator.java
index f7f30afc..430e12c3 100644
--- a/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLValidator.java
+++ b/libraryExtended/src/main/java/org/mustangproject/library/extended/XMLValidator.java
@@ -1,10 +1,6 @@
package org.mustangproject.library.extended;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
+import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -13,349 +9,409 @@ import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.*;
+import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
-import org.oclc.purl.dsdl.svrl.FailedAssert;
-import org.oclc.purl.dsdl.svrl.FiredRule;
-import org.oclc.purl.dsdl.svrl.SchematronOutputType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-
+import com.helger.schematron.svrl.jaxb.FailedAssert;
+import com.helger.schematron.svrl.jaxb.FiredRule;
+import com.helger.schematron.svrl.jaxb.SchematronOutputType;
import com.helger.schematron.ISchematronResource;
import com.helger.schematron.xslt.SchematronResourceXSLT;
+import com.helger.schematron.svrl.SVRLHelper;
+import org.xml.sax.InputSource;
public class XMLValidator extends Validator {
- public XMLValidator(ValidationContext ctx) {
- super(ctx);
- }
+ public XMLValidator(ValidationContext ctx) {
+ super(ctx);
+ }
- private static final Logger LOGGER = LoggerFactory.getLogger(XMLValidator.class.getCanonicalName()); // log output
- // is
- // ignored for the
- // time being
+ private static final Logger LOGGER = LoggerFactory.getLogger(XMLValidator.class.getCanonicalName()); // log output
+ // is
+ // ignored for the
+ // time being
- protected String zfXML = "";
- protected String filename = "";
- int firedRules=0;
- int failedRules=0;
- ISchematronResource aResSCH = null;
+ protected String zfXML = "";
+ protected String filename = "";
+ int firedRules = 0;
+ int failedRules = 0;
+ ISchematronResource aResSCH = null;
- public void setFilename(String name) throws IrrecoverableValidationError { // from XML Filename
- filename = name;
- // file existence must have been checked before
+ public void setFilename(String name) throws IrrecoverableValidationError { // from XML Filename
+ filename = name;
+ // file existence must have been checked before
- try {
- zfXML = removeBOMFromString(Files.readAllBytes(Paths.get(name)));
- } catch (IOException e) {
+ try {
+ zfXML = new String(Files.readAllBytes(Paths.get(name)));
+ } catch (IOException e) {
- ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(9)
- .setPart(EPart.xml);
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- e.printStackTrace(pw);
- vri.setStacktrace(sw.toString());
- context.addResultItem(vri);
- }
- }
+ ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(9)
+ .setPart(EPart.fx);
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ vri.setStacktrace(sw.toString());
+ context.addResultItem(vri);
+ }
+ }
- public void setStringContent(String xml) {
- zfXML = xml;
- }
+ public void setStringContent(String xml) {
+ zfXML = xml;
+ }
- protected String removeBOMFromString(byte[] rawXML) {
- byte[] bomlessData;
+ public static boolean matchesURI(String uri1, String uri2) {
+ return (uri1.equals(uri2) || uri1.startsWith(uri2 + "#"));
+ }
- if ((rawXML != null) && (rawXML.length > 3) && (rawXML[0] == (byte) 0xEF) && (rawXML[1] == (byte) 0xBB)
- && (rawXML[2] == (byte) 0xBF)) {
- // I don't like BOMs, lets remove it
- bomlessData = new byte[rawXML.length - 3];
- System.arraycopy(rawXML, 3, bomlessData, 0, rawXML.length - 3);
- } else {
- bomlessData = rawXML;
- }
+ /***
+ *
+ * @param xmlString
+ * @param overrideProfileCheck
+ * if set to true, all ZF2 files will be checked against EN16931
+ * schematron, since no other schematron is available
+ * @return
+ */
+ @Override
+ public void validate() throws IrrecoverableValidationError {
+ long startXMLTime = Calendar.getInstance().getTimeInMillis();
+ firedRules = 0;
+ failedRules = 0;
- return new String(bomlessData);
- }
-
- public static boolean matchesURI(String uri1, String uri2) {
- return (uri1.equals(uri2)||uri1.startsWith(uri2+"#"));
- }
+ ByteArrayInputStream xmlByteInputStream = new ByteArrayInputStream(zfXML.getBytes(StandardCharsets.UTF_8));
- /***
- *
- * @param xmlString
- * @param overrideProfileCheck
- * if set to true, all ZF2 files will be checked against EN16931
- * schematron, since no other schematron is available
- * @return
- */
- @Override
- public void validate() throws IrrecoverableValidationError {
- long startXMLTime = Calendar.getInstance().getTimeInMillis();
- firedRules=0;
- failedRules=0;
+ if (zfXML.isEmpty()) {
+ ValidationResultItem res = new ValidationResultItem(ESeverity.exception,
+ "XML data not found in " + filename
+ + ": did you specify a pdf or xml file and does the xml file contain an embedded XML file?")
+ .setSection(3);
+ context.addResultItem(res);
-
- ByteArrayInputStream xmlByteInputStream = new ByteArrayInputStream(zfXML.getBytes(StandardCharsets.UTF_8));
+ } else {
- if (zfXML.isEmpty()) {
- ValidationResultItem res = new ValidationResultItem(ESeverity.exception,
- "XML data not found in " + filename
- + ": did you specify a pdf or xml file and does the xml file contain an embedded XML file?")
- .setSection(3);
- context.addResultItem(res);
+ // final ISchematronResource aResSCH =
+ // SchematronResourceSCH.fromFile (new File("ZUGFeRD_1p0.scmt"));
+ // ... DOES work but is highly deprecated (and rightly so) because
+ // it takes 30-40min,
- } else {
+ try {
- // final ISchematronResource aResSCH =
- // SchematronResourceSCH.fromFile (new File("ZUGFeRD_1p0.scmt"));
- // ... DOES work but is highly deprecated (and rightly so) because
- // it takes 30-40min,
+ /***
+ * private static final String VALID_SCHEMATRON = "test-sch/valid01.sch";
+ * private static final String VALID_XMLINSTANCE = "test-xml/valid01.xml";
+ *
+ * @Test public void testWriteValid () throws Exception { final Document aDoc =
+ * SchematronResourceSCH.fromClassPath (VALID_SCHEMATRON)
+ * .applySchematronValidation (new ClassPathResource (VALID_XMLINSTANCE));
+ *
+ */
- try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true); // otherwise we can not act namespace independently, i.e. use
+ // document.getElementsByTagNameNS("*",...
- /***
- * private static final String VALID_SCHEMATRON = "test-sch/valid01.sch";
- * private static final String VALID_XMLINSTANCE = "test-xml/valid01.xml";
- *
- * @Test public void testWriteValid () throws Exception { final Document aDoc =
- * SchematronResourceSCH.fromClassPath (VALID_SCHEMATRON)
- * .applySchematronValidation (new ClassPathResource (VALID_XMLINSTANCE));
- *
- */
-
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware(true); // otherwise we can not act namespace independently, i.e. use
- // document.getElementsByTagNameNS("*",...
+ DocumentBuilder db = dbf.newDocumentBuilder();
- DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(xmlByteInputStream);
- Document doc = db.parse(xmlByteInputStream);
+ Element root = doc.getDocumentElement();
- Element root = doc.getDocumentElement();
+ NodeList ndList;
- NodeList ndList;
+ // rootNode = document.getDocumentElement();
+ // ApplicableSupplyChainTradeSettlement
- // rootNode = document.getDocumentElement();
- // ApplicableSupplyChainTradeSettlement
+ // Create XPathFactory object
+ XPathFactory xpathFactory = XPathFactory.newInstance();
- // Create XPathFactory object
- XPathFactory xpathFactory = XPathFactory.newInstance();
+ // Create XPath object
+ XPath xpath = xpathFactory.newXPath();
+ XPathExpression expr = xpath.compile(
+ "//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"]/text()");
+ // evaluate expression result on XML document
+ ndList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
- // Create XPath object
- XPath xpath = xpathFactory.newXPath();
- XPathExpression expr = xpath.compile(
- "//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"]/text()");
- // evaluate expression result on XML document
- ndList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ for (int bookingIndex = 0; bookingIndex < ndList.getLength(); bookingIndex++) {
+ Node booking = ndList.item(bookingIndex);
+ // if there is a attribute in the tag number:value
+ // urn:ferd:CrossIndustryDocument:invoice:1p0:extended
+ // setForeignReference(booking.getTextContent());
- for (int bookingIndex = 0; bookingIndex < ndList.getLength(); bookingIndex++) {
- Node booking = ndList.item(bookingIndex);
- // if there is a attribute in the tag number:value
- // urn:ferd:CrossIndustryDocument:invoice:1p0:extended
- // setForeignReference(booking.getTextContent());
+ context.setProfile(booking.getNodeValue());
+ }
+ boolean isMiniumum = false;
+ boolean isBasic = false;
+ boolean isBasicWithoutLines = false;
+ boolean isEN16931 = false;
+ boolean isExtended = false;
+ String xsltFilename = null;
+ // urn:ferd:CrossIndustryDocument:invoice:1p0:extended,
+ // urn:ferd:CrossIndustryDocument:invoice:1p0:comfort,
+ // urn:ferd:CrossIndustryDocument:invoice:1p0:basic,
- context.setProfile(booking.getNodeValue());
- }
- boolean isMiniumum = false;
- boolean isBasic = false;
- boolean isBasicWithoutLines = false;
- boolean isEN16931 = false;
- boolean isExtended = false;
- String xsltFilename = null;
- // urn:ferd:CrossIndustryDocument:invoice:1p0:extended,
- // urn:ferd:CrossIndustryDocument:invoice:1p0:comfort,
- // urn:ferd:CrossIndustryDocument:invoice:1p0:basic,
+ // urn:cen.eu:en16931:2017
+ // urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:basic
+ if (root.getNodeName().equalsIgnoreCase("rsm:CrossIndustryInvoice")) { // ZUGFeRD 2.0 or Factur-X
+ context.setVersion("2");
- // urn:cen.eu:en16931:2017
- // urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:basic
- if (root.getNodeName().equalsIgnoreCase("rsm:CrossIndustryInvoice")) { // ZUGFeRD 2.0 or Factur-X
- context.setVersion("2");
+ isMiniumum = context.getProfile().contains("minimum");
+ isBasic = context.getProfile().contains("basic");
+ isBasicWithoutLines = context.getProfile().contains("basicwl");
+ if (isBasicWithoutLines) {
+ isBasic = false;// basicwl also contains the string basic...
+ }
+ isEN16931 = matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:en16931")
+ || matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017");
- isMiniumum = context.getProfile().contains("minimum");
- isBasic = context.getProfile().contains("basic");
- isBasicWithoutLines = context.getProfile().contains("basicwl");
- if(isBasicWithoutLines) {
- isBasic=false;// basicwl also contains the string basic...
- }
- isEN16931 = matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:en16931")
- || matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017");
+ isExtended = context.getProfile().contains("extended");
+ if (isExtended) {
+ isEN16931 = false;// the uri for extended is urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended and thus contains en16931...
+ }
+ if (isMiniumum) {
+ LOGGER.debug("is Minimum");
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "zf2/MINIMUM/FACTUR-X_MINIMUM.xsd", 18, EPart.fx);
+ xsltFilename = "/xslt/zugferd21_minimum.xsl";
+ } else if (isBasicWithoutLines) {
+ LOGGER.debug("is Basic/WL");
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "zf2/BASIC-WL/FACTUR-X_BASIC-WL.xsd", 18, EPart.fx);
+ xsltFilename = "/xslt/zugferd21_basicwl.xsl";
+ } else if (isBasic) {
+ LOGGER.debug("is Basic");
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "zf2/BASIC/FACTUR-X_BASIC.xsd", 18, EPart.fx);
+ xsltFilename = "/xslt/zugferd21_basic.xsl";
+ } else if (isEN16931) {
+ LOGGER.debug("is EN16931");
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "zf2/EN16931/FACTUR-X_EN16931.xsd", 18, EPart.fx);
+ xsltFilename = "/xslt/zugferd21_en16931.xsl";
+ } else if (isExtended) {
+ LOGGER.debug("is EXTENDED");
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "zf2/EXTENDED/FACTUR-X_EXTENDED.xsd", 18, EPart.fx);
+ xsltFilename = "/xslt/zugferd21_extended.xsl";
+ } /*
+ * ISchematronResource aResSCH = SchematronResourceXSLT.fromFile(new File(
+ * "/Users/jstaerk/workspace/ZUV/src/main/resources/ZUGFeRDSchematronStylesheet.xsl"
+ * ));
+ */
- isExtended = context.getProfile().contains("extended");
- if(isExtended) {
- isEN16931=false;// the uri for extended is urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended and thus contains en16931...
- }
- if (isMiniumum) {
- LOGGER.debug("is Minimum");
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8),"zf2/MINIMUM/FACTUR-X_MINIMUM.xsd", 18, EPart.xml);
- xsltFilename="/xslt/zugferd21_minimum.xsl";
- } else if (isBasicWithoutLines) {
- LOGGER.debug("is Basic/WL");
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8),"zf2/BASIC-WL/FACTUR-X_BASIC-WL.xsd", 18, EPart.xml);
- xsltFilename="/xslt/zugferd21_basicwl.xsl";
- } else if (isBasic) {
- LOGGER.debug("is Basic");
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8),"zf2/BASIC/FACTUR-X_BASIC.xsd", 18, EPart.xml);
- xsltFilename="/xslt/zugferd21_basic.xsl";
- } else if (isEN16931) {
- LOGGER.debug("is EN16931");
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8),"zf2/EN16931/FACTUR-X_EN16931.xsd", 18, EPart.xml);
- xsltFilename="/xslt/zugferd21_en16931.xsl";
- } else if (isExtended) {
- LOGGER.debug("is EXTENDED");
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8),"zf2/EXTENDED/FACTUR-X_EXTENDED.xsd", 18, EPart.xml);
- xsltFilename="/xslt/zugferd21_extended.xsl";
- } /*
- * ISchematronResource aResSCH = SchematronResourceXSLT.fromFile(new File(
- * "/Users/jstaerk/workspace/ZUV/src/main/resources/ZUGFeRDSchematronStylesheet.xsl"
- * ));
- */
+ // takes around 10 Seconds. //
+ // http://www.bentoweb.org/refs/TCDL2.0/tsdtf_schematron.html // explains that
+ // this xslt can be created using sth like
+ // saxon java net.sf.saxon.Transform -o tcdl2.0.tsdtf.sch.tmp.xsl -s
+ // tcdl2.0.tsdtf.sch iso_svrl.xsl
- // takes around 10 Seconds. //
- // http://www.bentoweb.org/refs/TCDL2.0/tsdtf_schematron.html // explains that
- // this xslt can be created using sth like
- // saxon java net.sf.saxon.Transform -o tcdl2.0.tsdtf.sch.tmp.xsl -s
- // tcdl2.0.tsdtf.sch iso_svrl.xsl
+ } else { // ZUGFeRD 1.0
+ context.setVersion("1");
+ //
+ if ((!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:basic"))
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
+ context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
+ .setSection(25).setPart(EPart.fx));
+ }
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "zf1/ZUGFeRD1p0.xsd", 18, EPart.fx);
- } else { // ZUGFeRD 1.0
- context.setVersion("1");
- //
- if ((!matchesURI(context.getProfile(),"urn:ferd:CrossIndustryDocument:invoice:1p0:basic"))
- && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
- && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
- context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
- .setSection(25).setPart(EPart.xml));
- }
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8),"zf1/ZUGFeRD1p0.xsd", 18, EPart.xml);
-
- xsltFilename="/xslt/ZUGFeRD_1p0.xslt";
- }
- if (context.getVersion().equals("2")) {
- if ((!matchesURI(context.getProfile(), "urn:factur-x.eu:1p0:minimum"))
- && (!matchesURI(context.getProfile(),"urn:zugferd.de:2p0:minimum"))
- && (!matchesURI(context.getProfile(),"urn:factur-x.eu:1p0:basicwl"))
- && (!matchesURI(context.getProfile(),"urn:zugferd.de:2p0:basicwl"))
- && (!matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic"))
- && (!matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic"))
- && (!matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017"))
- && (!matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"))
- && (!matchesURI(context.getProfile(),"urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended")))
+ xsltFilename = "/xslt/ZUGFeRD_1p0.xslt";
+ }
+ if (context.getVersion().equals("2")) {
+ if ((!matchesURI(context.getProfile(), "urn:factur-x.eu:1p0:minimum"))
+ && (!matchesURI(context.getProfile(), "urn:zugferd.de:2p0:minimum"))
+ && (!matchesURI(context.getProfile(), "urn:factur-x.eu:1p0:basicwl"))
+ && (!matchesURI(context.getProfile(), "urn:zugferd.de:2p0:basicwl"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended"))) {
+ context.addResultItem(
+ new ValidationResultItem(ESeverity.error, "Unsupported profile type " + context.getProfile())
+ .setSection(25).setPart(EPart.fx));
- {
- context.addResultItem(
- new ValidationResultItem(ESeverity.error, "Unsupported profile type "+context.getProfile())
- .setSection(25).setPart(EPart.xml));
+ }
+ } else /** v1 */ {//urn:ferd:invoice:rc:comfort
+ if ((!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:basic"))
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
+ context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
+ .setSection(25).setPart(EPart.fx));
- }
- } else /** v1 */
- {//urn:ferd:invoice:rc:comfort
- if ((!matchesURI(context.getProfile(),"urn:ferd:CrossIndustryDocument:invoice:1p0:basic"))
- && (!matchesURI(context.getProfile(),"urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
- && (!matchesURI(context.getProfile(),"urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
- context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
- .setSection(25).setPart(EPart.xml));
+ }
+ }
- }
- }
-
- // main schematron validation
- validateSchematron(zfXML, xsltFilename, 4);
+ // main schematron validation
+ validateSchematron(zfXML, xsltFilename, 4, ESeverity.error);
-
- if (context.getVersion().equals("2")
- && isEN16931) {
- //additionally validate against CEN
- validateSchematron(zfXML, "/xslt/cii16931schematron/EN16931-CII-validation.xslt", 24);
- }
-
+ if (context.getVersion().equals("2")
+ && isEN16931) {
+ //additionally validate against CEN
+ validateSchematron(zfXML, "/xslt/cii16931schematron/EN16931-CII-validation.xslt", 24, ESeverity.error);
- } catch (IrrecoverableValidationError er) {
- throw er;
- } catch (Exception e) {
- ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(22)
- .setPart(EPart.xml);
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- e.printStackTrace(pw);
- vri.setStacktrace(sw.toString());
- context.addResultItem(vri);
- }
+ validateXR(zfXML);
+ }
- }
- long endTime = Calendar.getInstance().getTimeInMillis();
-
- context.addCustomXML("" + ((context.getVersion() != null) ? context.getVersion() : "invalid")
- + "" + ((context.getProfile() != null) ? context.getProfile() : "invalid") +
- ""+firedRules+""+failedRules+"" + "" + (endTime - startXMLTime) + "");
- }
-
- public void validateSchematron(String xml, String xsltFilename, int section) throws IrrecoverableValidationError{
- ISchematronResource aResSCH = null;
- aResSCH = SchematronResourceXSLT.fromClassPath(xsltFilename);
- if (aResSCH != null) {
- if (!aResSCH.isValidSchematron()) {
- throw new IllegalArgumentException(xsltFilename+" is invalid Schematron!");
- }
+ } catch (IrrecoverableValidationError er) {
+ throw er;
+ } catch (Exception e) {
+ ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(22)
+ .setPart(EPart.fx);
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ vri.setStacktrace(sw.toString());
+ context.addResultItem(vri);
+ }
- SchematronOutputType sout;
- try {
- sout = aResSCH
- .applySchematronValidationToSVRL(new StreamSource(new StringReader(xml)));
- } catch (Exception e) {
- throw new IrrecoverableValidationError(e.getMessage());
- }
+ }
+ long endTime = Calendar.getInstance().getTimeInMillis();
- List