closes #606
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
package org.mustangproject.validator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringReader;
|
||||
@@ -69,15 +70,13 @@ public class XMLValidator extends Validator {
|
||||
final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(9)
|
||||
.setPart(EPart.fx);
|
||||
try (final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw))
|
||||
{
|
||||
e.printStackTrace(pw);
|
||||
vri.setStacktrace(sw.toString());
|
||||
context.addResultItem(vri);
|
||||
final PrintWriter pw = new PrintWriter(sw)) {
|
||||
e.printStackTrace(pw);
|
||||
vri.setStacktrace(sw.toString());
|
||||
context.addResultItem(vri);
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException (ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -125,9 +124,9 @@ public class XMLValidator extends Validator {
|
||||
|
||||
if (zfXML.isEmpty()) {
|
||||
final 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);
|
||||
"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);
|
||||
|
||||
} else {
|
||||
@@ -170,7 +169,7 @@ public class XMLValidator extends Validator {
|
||||
// Create XPath object
|
||||
final XPath xpath = xpathFactory.newXPath();
|
||||
final XPathExpression expr = xpath.compile(
|
||||
"(//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"])/text()|//*[local-name()=\"CustomizationID\"]/text()");
|
||||
"(//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"])/text()|//*[local-name()=\"CustomizationID\"]/text()");
|
||||
// evaluate expression result on XML document
|
||||
ndList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
|
||||
|
||||
@@ -191,7 +190,7 @@ public class XMLValidator extends Validator {
|
||||
boolean isExtended = false;
|
||||
boolean isXRechnung = false;
|
||||
String currentZFVersionDir = "ZF_232";
|
||||
int mainSchematronSectionErrorTypeCode=4;
|
||||
int mainSchematronSectionErrorTypeCode = 4;
|
||||
String xsltFilename = null;
|
||||
// urn:ferd:CrossIndustryDocument:invoice:1p0:extended,
|
||||
// urn:ferd:CrossIndustryDocument:invoice:1p0:comfort,
|
||||
@@ -224,7 +223,7 @@ public class XMLValidator extends Validator {
|
||||
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");
|
||||
|| matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017");
|
||||
|
||||
isExtended = context.getProfile().contains("extended");
|
||||
isXRechnung = context.getProfile().contains("xrechnung");
|
||||
@@ -269,16 +268,16 @@ public class XMLValidator extends Validator {
|
||||
// saxon java net.sf.saxon.Transform -o tcdl2.0.tsdtf.sch.tmp.xsl -s
|
||||
// tcdl2.0.tsdtf.sch iso_svrl.xsl
|
||||
|
||||
} else if (root.getLocalName().equalsIgnoreCase("Invoice") || root.getLocalName().equalsIgnoreCase("CreditNote") ) {
|
||||
} else if (root.getLocalName().equalsIgnoreCase("Invoice") || root.getLocalName().equalsIgnoreCase("CreditNote")) {
|
||||
context.setGeneration("2");
|
||||
context.setFormat("UBL");
|
||||
isXRechnung = context.getProfile().contains("xrechnung");
|
||||
// UBL
|
||||
LOGGER.debug("UBL");
|
||||
validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "UBL_21/maindoc/UBL-"+root.getLocalName()+"-2.1.xsd", 18, EPart.fx);
|
||||
validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "UBL_21/maindoc/UBL-" + root.getLocalName() + "-2.1.xsd", 18, EPart.fx);
|
||||
xsltFilename = "/xslt/en16931schematron/EN16931-UBL-validation.xslt";
|
||||
|
||||
mainSchematronSectionErrorTypeCode=24;
|
||||
mainSchematronSectionErrorTypeCode = 24;
|
||||
|
||||
if (isXRechnung) {
|
||||
validateSchematron(zfXML, xsltFilename, 24, ESeverity.error);
|
||||
@@ -287,14 +286,14 @@ public class XMLValidator extends Validator {
|
||||
XRechnung is a EN16931 subset so the validation vis a vis FACTUR-X_EN16931.xslt=schematron also has to pass
|
||||
* */
|
||||
//validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "ZF_211/EN16931/FACTUR-X_EN16931.xsd", 18, EPart.fx);
|
||||
String xrVersion=context.getProfile().substring(context.getProfile().length()-3).replace(".","");
|
||||
if (!xrVersion.equals("12")&&!xrVersion.equals("20")&&!xrVersion.equals("21")&&!xrVersion.equals("22")&&!xrVersion.equals("23")&&!xrVersion.equals("30")) {
|
||||
String xrVersion = context.getProfile().substring(context.getProfile().length() - 3).replace(".", "");
|
||||
if (!xrVersion.equals("12") && !xrVersion.equals("20") && !xrVersion.equals("21") && !xrVersion.equals("22") && !xrVersion.equals("23") && !xrVersion.equals("30")) {
|
||||
throw new Exception("Unsupported XR version");
|
||||
}
|
||||
LOGGER.debug("is XRechnung v"+xrVersion);
|
||||
xsltFilename = "/xslt/XR_"+xrVersion+"/XRechnung-UBL-validation.xslt";
|
||||
LOGGER.debug("is XRechnung v" + xrVersion);
|
||||
xsltFilename = "/xslt/XR_" + xrVersion + "/XRechnung-UBL-validation.xslt";
|
||||
XrechnungSeverity = ESeverity.error;
|
||||
mainSchematronSectionErrorTypeCode=27;
|
||||
mainSchematronSectionErrorTypeCode = 27;
|
||||
|
||||
}
|
||||
|
||||
@@ -302,58 +301,58 @@ public class XMLValidator extends Validator {
|
||||
context.setGeneration("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"))) {
|
||||
&& (!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));
|
||||
.setSection(25).setPart(EPart.fx));
|
||||
}
|
||||
validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "ZF_10/ZUGFeRD1p0.xsd", 18, EPart.fx);
|
||||
|
||||
xsltFilename = "/xslt/ZUGFeRD_1p0.xslt";
|
||||
} else { // unknown document root
|
||||
context.addResultItem(new ValidationResultItem(ESeverity.fatal, "Unsupported root element")
|
||||
.setSection(3).setPart(EPart.fx));
|
||||
.setSection(3).setPart(EPart.fx));
|
||||
}
|
||||
if (context.getFormat().equals("CII")) {
|
||||
|
||||
if (context.getGeneration().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"))) {
|
||||
&& (!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));
|
||||
new ValidationResultItem(ESeverity.error, "Unsupported profile type " + context.getProfile())
|
||||
.setSection(25).setPart(EPart.fx));
|
||||
|
||||
}
|
||||
} else /** v1 */ {
|
||||
if (isOrderX) {
|
||||
//order-x 1.0
|
||||
if ((!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:basic"))
|
||||
&& (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:comfort"))
|
||||
&& (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:extended"))) {
|
||||
&& (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:comfort"))
|
||||
&& (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:extended"))) {
|
||||
//zf 1.0
|
||||
context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
|
||||
.setSection(25).setPart(EPart.fx));
|
||||
.setSection(25).setPart(EPart.fx));
|
||||
|
||||
}
|
||||
} else 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"))) {
|
||||
&& (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
|
||||
&& (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
|
||||
//zf 1.0
|
||||
context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
|
||||
.setSection(25).setPart(EPart.fx));
|
||||
.setSection(25).setPart(EPart.fx));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xsltFilename!=null) {
|
||||
if (xsltFilename != null) {
|
||||
// main schematron validation
|
||||
validateSchematron(zfXML, xsltFilename, mainSchematronSectionErrorTypeCode, ESeverity.error);
|
||||
|
||||
@@ -362,7 +361,7 @@ public class XMLValidator extends Validator {
|
||||
if (context.getFormat().equals("CII")) {
|
||||
|
||||
if (context.getGeneration().equals("2")
|
||||
&& (isBasic || isEN16931 || isXRechnung)) {
|
||||
&& (isBasic || isEN16931 || isXRechnung)) {
|
||||
//additionally validate against CEN
|
||||
validateSchematron(zfXML, "/xslt/en16931schematron/EN16931-CII-validation.xslt", 24, ESeverity.error);
|
||||
if (!disableNotices || XrechnungSeverity != ESeverity.notice) {
|
||||
@@ -376,7 +375,7 @@ public class XMLValidator extends Validator {
|
||||
throw er;
|
||||
} catch (final Exception e) {
|
||||
final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(22)
|
||||
.setPart(EPart.fx);
|
||||
.setPart(EPart.fx);
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw);
|
||||
e.printStackTrace(pw);
|
||||
@@ -388,8 +387,8 @@ public class XMLValidator extends Validator {
|
||||
final long endTime = Calendar.getInstance().getTimeInMillis();
|
||||
|
||||
context.addCustomXML("<info><version>" + ((context.getGeneration() != null) ? context.getGeneration() : "invalid")
|
||||
+ "</version><profile>" + ((context.getProfile() != null) ? context.getProfile() : "invalid") +
|
||||
"</profile><validator version=\"" + XMLValidator.class.getPackage().getImplementationVersion() + "\"></validator><rules><fired>" + firedRules + "</fired><failed>" + failedRules + "</failed></rules>" + "<duration unit=\"ms\">" + (endTime - startXMLTime) + "</duration></info>");
|
||||
+ "</version><profile>" + ((context.getProfile() != null) ? context.getProfile() : "invalid") +
|
||||
"</profile><validator version=\"" + XMLValidator.class.getPackage().getImplementationVersion() + "\"></validator><rules><fired>" + firedRules + "</fired><failed>" + failedRules + "</failed></rules>" + "<duration unit=\"ms\">" + (endTime - startXMLTime) + "</duration></info>");
|
||||
|
||||
}
|
||||
|
||||
@@ -434,7 +433,7 @@ public class XMLValidator extends Validator {
|
||||
final SchematronOutputType sout;
|
||||
try {
|
||||
sout = aResSCH
|
||||
.applySchematronValidationToSVRL(new StreamSource(new StringReader(xml)));
|
||||
.applySchematronValidationToSVRL(new StreamSource(new StringReader(xml)));
|
||||
} catch (final Exception e) {
|
||||
throw new IrrecoverableValidationError(e.getMessage());
|
||||
}
|
||||
@@ -471,7 +470,7 @@ public class XMLValidator extends Validator {
|
||||
if (defaultSeverity == ESeverity.notice) {
|
||||
severity = defaultSeverity;
|
||||
} else if (currentFailNode.getAttributes().getNamedItem("flag") != null
|
||||
&& currentFailNode.getAttributes().getNamedItem("flag").getNodeValue().equals("warning")) {
|
||||
&& currentFailNode.getAttributes().getNamedItem("flag").getNodeValue().equals("warning")) {
|
||||
// the XR issues warnings with flag=warning
|
||||
severity = ESeverity.warning;
|
||||
} else {
|
||||
@@ -493,8 +492,8 @@ public class XMLValidator extends Validator {
|
||||
LOGGER.info("FailedAssert ", thisFailText);
|
||||
|
||||
context.addResultItem(new ValidationResultItem(severity, thisFailText + thisFailIDStr + " from " + xsltFilename + ")")
|
||||
.setLocation(thisFailLocation).setCriterion(thisFailTest).setSection(section).setID(thisFailID)
|
||||
.setPart(EPart.fx));
|
||||
.setLocation(thisFailLocation).setCriterion(thisFailTest).setSection(section).setID(thisFailID)
|
||||
.setPart(EPart.fx));
|
||||
failedRules++;
|
||||
|
||||
}
|
||||
@@ -525,7 +524,7 @@ public class XMLValidator extends Validator {
|
||||
|
||||
if (firedRules == 0) {
|
||||
context.addResultItem(new ValidationResultItem(ESeverity.error, "No rules matched, XML to minimal?").setSection(26)
|
||||
.setPart(EPart.fx));
|
||||
.setPart(EPart.fx));
|
||||
|
||||
}
|
||||
// for (String currentString : sout.getText()) {
|
||||
|
||||
Reference in New Issue
Block a user