Java Programming Tutorials

Java programming tutorials with many code examples!

Java XML validate using SchemaFactory

Java XML validate using SchemaFactory

There are a few ways to validate XML file in Java. In this post we show how to use SchemaFactory to validate XML against XSD Schema from file.

Java SchemaFactory has very nice features:

  1. XML documents don’t have to have any reference to schema that will be use to validate them.
  2. Schema language is configurable and can be changed, without affecting XML documents. So you can validate XML against XSD Schema and later change to, for example, Relax NG.

Validation with SchemaFactory

Creation of SchemaFactory is rather simple. It only requires configuration type of schema language being used for validation and the schema can be created. When we’ve got schema instance we can create a validator and perform validation of XML content:

SchemaFactory factory = SchemaFactory.newInstance(
        XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(
        new StreamSource(getInputStream(schemaFile)));

Validator validator = schema.newValidator();
validator.validate(new DOMSource(document));

Sample XSD Schema

In our example we will validate XML document against the following XSD Schema file. Let’s call it books.xsd:

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema attributeFormDefault="unqualified"
            elementFormDefault="qualified"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <!-- XML Schema types definitions -->
    <xsd:complexType name="LibraryType">
        <xsd:sequence>
            <xsd:element name="book" type="BookType"
                         minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="location" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="BookType">
        <xsd:sequence>
            <xsd:element name="title" type="xsd:string"
                         minOccurs="1" maxOccurs="1"/>
            <xsd:element name="price" type="xsd:decimal" />
        </xsd:sequence>
    </xsd:complexType>

    <!-- Definition of XML content -->
    <xsd:element name="library" type="LibraryType" />
</xsd:schema>

XML file to validate

Now, let’s suppose that we’ve got an XML file, named library-no-schema.xml, with the following content:

<?xml version="1.0" encoding="utf-8"?>
<library location="Cracow">
    <book>
        <title>Enterprise Integration Patterns</title>
        <price>50</price>
    </book>
    <book>
        <title>Effective Java</title>
        <price>no price, yet</price>
    </book>
</library>

According to the books.xsd schema the above file is invalid, because the price of the Effective Java book is not a number.

Complete Java example

In the following example we’ll validate above library-no-schema.xml using above books.xsd schema:

package com.farenda.javax.xml;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
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;

public class XmlValidatorWithSchemaFactory {

    public static void main(String[] args) throws Exception {
        String schemaFilename = "xml/books.xsd";
        String xmlFilename = "xml/library-no-schema.xml";

        XmlValidatorWithSchemaFactory validator
                = new XmlValidatorWithSchemaFactory();
        Document document = validator.loadXml(xmlFilename);

        try {
            validator.validate(document, schemaFilename);
            System.out.println("The file is valid!");
        } catch (Exception e) {
            System.err.println("The file is invalid! Reason:");
            System.err.println(e.getMessage());
        }
    }

    public void validate(Document document, String schemaFile)
            throws SAXException, IOException {
        SchemaFactory factory = SchemaFactory.newInstance(
                XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(
                new StreamSource(getInputStream(schemaFile)));

        Validator validator = schema.newValidator();
        validator.validate(new DOMSource(document));
    }

    private DocumentBuilder createDocumentBuilder()
            throws ParserConfigurationException {
        DocumentBuilderFactory builderFactory
                = DocumentBuilderFactory.newInstance();
        builderFactory.setNamespaceAware(true);
        return builderFactory.newDocumentBuilder();
    }

    private Document loadXml(String xmlToValidate) throws Exception {
        DocumentBuilder builder = createDocumentBuilder();
        return builder.parse(getInputStream(xmlToValidate));
    }

    private InputStream getInputStream(String filename) {
        return getClass().getClassLoader().getResourceAsStream(filename);
    }
}

When run the above program prints the following message:

The file is invalid! Reason:
cvc-datatype-valid.1.2.1: 'no price, yet' is not a valid value for 'decimal'.

Now, if we correct the price in the second book, making the XML file valid, the program will print:

The file is valid!
Share with the World!