import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;

import static java.util.Collections.unmodifiableList;
import static java.util.Locale.ENGLISH;
import static javax.xml.validation.SchemaFactory.newInstance;

public class Main {

    private final static String xsd = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
            +"<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"https://agebhar1.github.io/schema/Example\"\n"
            +"        elementFormDefault=\"qualified\">"
            +"\n"
            +"    <element name=\"root\">"
            +"        <complexType>"
            +"            <sequence>"
            +"                <element name=\"a\">"
            +"                    <complexType>"
            +"                        <simpleContent>"
            +"                            <extension base=\"string\">"
            +"                                <attribute name=\"enabled\" type=\"boolean\" use=\"required\"/>"
            +"                            </extension>"
            +"                        </simpleContent>"
            +"                    </complexType>"
            +"                </element>"
            +"            </sequence>"
            +"        </complexType>"
            +"    </element>"
            +"\n"
            +"</schema>";

    private final static String xml = "<e:root xmlns:e=\"https://agebhar1.github.io/schema/Example\">\n"
            +"    <e:a>string</e:a>\n"
            +"</e:root>";

    private static final Function<String, Source> toSource = (String it) -> new StreamSource(new StringReader(it));

    public static void main(String[] args) {
        Locale.setDefault(ENGLISH);
        var ex = validateXMLWithSchema(xsd.transform(toSource), xml.transform(toSource));
        assert ex.size() == 1;
    }

    public static List<SAXParseException> validateXMLWithSchema(final Source xsd, final Source xml) {
        final List<SAXParseException> exceptions = new ArrayList<>();
        try {
            final var factory = newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            final var schema = factory.newSchema(xsd);
            final var validator = schema.newValidator();
            validator.setErrorHandler(new ErrorHandler() {
                @Override
                public void warning(final SAXParseException exception) {
                    System.err.printf("Warning: %s%n", exception);
                    exceptions.add(exception);
                }

                @Override
                public void error(final SAXParseException exception) {
                    System.err.printf("Error: %s%n", exception);
                    exceptions.add(exception);
                }

                @Override
                public void fatalError(final SAXParseException exception) {
                    System.err.printf("Fatal: %s%n", exception);
                    exceptions.add(exception);
                }
            });

            validator.validate(xml);

        } catch (final SAXException | IOException e) {
            System.err.printf("Exception: %s%n", e.getMessage());
        }
        return unmodifiableList(exceptions);
    }

} 