Reputation: 3530
Is there a way I can validate my XML against my XSD COMPLETELY, meaning that I want the file to continue validating even after it has found an error so I can get the complete error messages rather than just 1 or the first error message?
Currently, the execution stops when it finds the first error, prints it, and does not continue any further. I want to know if it's possible to achieve this. I tried the method mentioned here and did the same but still it's not working as expected and execution stops.
Following is the code I have:
XsdErrorHandler.class
:
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
public class XsdErrorHandler implements ErrorHandler {
@lombok.Getter
private java.util.List<SAXParseException> exceptions;
public XsdErrorHandler() {
this.exceptions = new java.util.ArrayList<>();
}
@Override
public void warning(final SAXParseException exception) throws org.xml.sax.SAXException {
handleError(exception);
}
@Override
public void error(final SAXParseException exception) throws org.xml.sax.SAXException {
handleError(exception);
}
@Override
public void fatalError(final SAXParseException exception) throws org.xml.sax.SAXException {
handleError(exception);
}
public void handleError(SAXParseException e) throws org.xml.sax.SAXException {
// Do nothing. This will allow the validation to continue even if there are errors.
this.exceptions.add(e);
}
}
Following is my schema validator:
Main.class
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMain {
public static void main(String[] args) throws SAXException, IOException {
final String xsdPath = "/xsd/myXSD.xsd";
final String xmlPath = "/myXml.xml";
listParsingExceptions(xsdPath, xmlPath);
}
private static Validator initValidator(final String xsdPath) throws SAXException {
final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Source schemaFile = new StreamSource(TestMain.class.getResourceAsStream(xsdPath));
final Schema schema = factory.newSchema(schemaFile);
return schema.newValidator();
}
public static List<SAXParseException> listParsingExceptions(final String xsdPath, final String xmlPath) throws IOException, SAXException {
final InputStream inputStream = TestMain.class.getResourceAsStream(xmlPath);
final XsdErrorHandler xsdErrorHandler = new XsdErrorHandler();
final Validator validator = initValidator(xsdPath);
validator.setErrorHandler(xsdErrorHandler);
try {
validator.validate(new StreamSource(inputStream));
} catch (SAXParseException e)
{
// ...
}
System.out.println("ERRORS : ");
xsdErrorHandler.getExceptions().forEach(e -> System.out.println(e.getMessage()));
return xsdErrorHandler.getExceptions();
}
}
Issues:
I am a bit confused about what else I need to do to make this continue working. Can someone please provide some suggestions?
Also, my XSD contains many imports and references to other XSD. When I give a relative path, then it won't work, but when I give an absolute path, then it works. Is there a way I can make it work with a relative path?
Following fails:
<xsd:import namespace="urn:global:xsd:1" schemaLocation="./global.xsd"/>
Following works:
<xsd:import namespace="urn:global:xsd:1" schemaLocation="/Users/username/project/validation/src/main/resources/xsd/global.xsd"/>
I tried to provide the path for XSD file using maven-jaxb2-plugin
something like this but this also did not work for me
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${basedir}/src/main/resources/xsd</schemaDirectory>
</configuration>
</plugin>
</plugins>
</build>
I tried to write my own ClasspathResourceResolver
by referencing here and added to my schemaFactory
using schemaFactory.setResourceResolver(new ClasspathResourceResolver());
but that also did not work for me.
All my files are present in the XSD folder and I would like to reference using the relative path something like this ./xsdName.xsd
Upvotes: 1
Views: 436