How do I validate XML against XSD in Java?

The javax.xml.validation package provides an API for XML documents validation. The validation process verify that an XML document is an instance of a specified XML schema file or XSD file. In this example we are going to validate if the records.xml file below ins an instance of the records.xsd schema. First we will create the following XML file and an XSD file it should follow.

The XML file:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <records>
        <record>
            <title>Brand New Eyes</title>
            <artist>Paramore</artist>
            <genre>Punk Rock</genre>
            <year>2011</year>
        </record>
        <record>
            <artist>Various Artist</artist>
            <genre>Rock</genre>
            <year/>
        </record>
    </records>
</root>

The XSD file:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified"
           elementFormDefault="qualified">
    <xs:element name="root" type="rootType">
    </xs:element>

    <xs:complexType name="rootType">
        <xs:sequence>
            <xs:element name="records" type="recordsType"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="recordsType">
        <xs:sequence>
            <xs:element name="record" type="recordType" maxOccurs="unbounded" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="recordType">
        <xs:sequence>
            <xs:element type="xs:string" name="title"/>
            <xs:element type="xs:string" name="artist"/>
            <xs:element type="xs:string" name="genre"/>
            <xs:element type="xs:short" name="year"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

The code snippet below will handle the validation process in the following steps. In the main() method we create the XMLValidator instance and call the validate() method and pass the XML file and the XSD file. Our validate() method start by creating an instance of SchemaFactory. The SchemaFactory.newInstance() method return an instance of SchemaFactory. In this example we are creating a W3C XML Schema.

The next step is to create a Schema object by calling the schemaFactory.newSchema() and pass the schema / XSD file. The Schema object will allow us to create an instance of javax.xml.validation.Validator by calling the schema.newValidator() method. And finally to validate if the XML is valid we call validator.validate() method and pass the XML file to be validated. If the XML is not valid, this validate() method will throw exceptions.

The Java code:

package org.kodejava.xml;

import org.xml.sax.SAXException;

import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Objects;

public class XMLValidator {
    public static final String XML_FILE = "records.xml";
    public static final String SCHEMA_FILE = "records.xsd";

    public static void main(String[] args) {
        XMLValidator XMLValidator = new XMLValidator();
        boolean valid = XMLValidator.validate(XML_FILE, SCHEMA_FILE);

        System.out.printf("%s validation = %b.", XML_FILE, valid);
    }

    private boolean validate(String xmlFile, String schemaFile) {
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        try {
            Schema schema = schemaFactory.newSchema(new File(getResource(schemaFile)));

            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(getResource(xmlFile))));
            return true;
        } catch (SAXException | IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    private String getResource(String filename) throws FileNotFoundException {
        URL resource = getClass().getClassLoader().getResource(filename);
        Objects.requireNonNull(resource);

        return resource.getFile();
    }
}