1

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:

  1. I am a bit confused about what else I need to do to make this continue working. Can someone please provide some suggestions?

  2. 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

6
  • Have you tried to specify it like this? schemaLocation="global.xsd" Commented Dec 13, 2022 at 9:20
  • @SimonMartinelli Thanks for your response. Yes, I tried that even that did not work for me <xsd:import namespace="urn:global:xsd:1" schemaLocation="global.xsd"/> so I found that we need to provide schemaFactory.setResourceResolver() with our own resolver and tried that as well which is also not working for me. I even tried to provide a path for all my XSD files using maven-jaxb2-plugin even that did not work for me. Commented Dec 13, 2022 at 9:37
  • Are you not getting beyond the first error in any of the schemas or not beyond any error in the sample instance document? If you want to output all errors in the schemas I think you need to set up an error handler as well on the schema factory. Commented Dec 14, 2022 at 12:57
  • For what it's worth: I have set up a sample project based on the original sample you linked to, first using the built-in JRE 8 Validator github.com/martin-honnen/ValidationHandlerTest1, then using Apache Xerces 2.12 github.com/martin-honnen/ValidationHandlerTest1/tree/… and finally using Saxon EE 11.4 github.com/martin-honnen/ValidationHandlerTest1/tree/UseSaxon, all three find the two errors in the sample instance document and don't abandon after the first error. Commented Dec 15, 2022 at 12:19
  • @MartinHonnen Thanks a lot for the response and for taking the time to create 3 projects. But I have a small doubt. Maybe due lack of my understanding I am unable to make any differences between the 3 created projects. All 3 projects seem to have the same ErrorHandler and TestMain classes and all have the same code and come from the same library. Is there any difference? Also, I am thinking to use the Moxy as it has been used in one of the dependent projects. Commented Dec 15, 2022 at 14:50

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.