How to validate an XML document using a RELAX NG schema and JAXP?

Avi Flax picture Avi Flax · Oct 9, 2009 · Viewed 8.1k times · Source

I would like to validate XML documents using RELAX NG schemata, and I would like to use the JAXP validation API.

From Googling around, it appeared that I could use Jing and the ISO RELAX JARV to JAXP Bridge. Unfortunately, after adding both to my classpath, I can't get it to work. SchemaFactory is just throwing an IllegalArgumentException as soon as it tries to instantiate a factory — I looked inside SchemaFactory, apparently SchemaFactoryFinder is returning a null result.

So I'd appreciate answers to either question:

  • How can I make this work with Jing and this bridge?
  • Is there a better/different set of libraries I should try?

I need this to work with Java 5 and Java 6.

Thanks!

Answer

ren waldura picture ren waldura · Jan 20, 2010

I resolved this very error on Java 1.6 with the following line:

// Specify you want a factory for RELAX NG "compact"
System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

This allows me to use Jing to validate an XML document against a Compact RELAX NG schema. Full example below. I didn't use the bridge or anything else. The runtime classpath only has jing.jar (20091111) and my own Validator class.

import java.io.File;
import java.io.IOException;

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 org.xml.sax.SAXException;

public class Validate
{

    public static void main(String[] args) throws SAXException, IOException
    {
        // Specify you want a factory for RELAX NG
        System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

        // Load the specific schema you want.
        // Here I load it from a java.io.File, but we could also use a
        // java.net.URL or a javax.xml.transform.Source
        File schemaLocation = new File(args[0]);

        // Compile the schema.
        Schema schema = factory.newSchema(schemaLocation);

        // Get a validator from the schema.
        Validator validator = schema.newValidator();

        for (int i = 1; i < args.length; i++)
        {
            String file = args[i];

            // Check the document
            try
            {
                validator.validate(new StreamSource(new File(file)));
                System.out.println(file + " is valid.");
            }
            catch (SAXException ex)
            {
                System.out.print(file + " is not valid because: " + ex.getMessage());
            }
        }
    }

}

Once again, I've only tested this ion Java 1.6.

$ java -version
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)