com.crabshue.commons.xml.validation.XmlValidator Maven / Gradle / Ivy
package com.crabshue.commons.xml.validation;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
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.apache.commons.io.FileUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import com.crabshue.commons.exceptions.ApplicationException;
import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.exceptions.ValidationException;
import com.crabshue.commons.file.exceptions.FileErrorContext;
import com.crabshue.commons.file.exceptions.FileErrorType;
import com.crabshue.commons.xml.exceptions.XmlErrorContext;
import com.crabshue.commons.xml.exceptions.XmlErrorType;
import com.crabshue.commons.xml.schema.XmlSchemaUtils;
/**
* Utility class for XML validation.
*
*/
public class XmlValidator {
private static Logger logger = LoggerFactory.getLogger(XmlValidator.class);
/**
* Validate an {@link File XML file} against a given schema.
*
* @param xmlFile the XML file.
* @param schemaUrl the URL of the remote schema.
*/
public static void validateXmlAgainstSchema(final File xmlFile, final URL schemaUrl) {
Validate.notNull(xmlFile);
Validate.notNull(schemaUrl);
try (InputStream xmlIs = FileUtils.openInputStream(xmlFile)) {
final SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = schemaFactory.newSchema(schemaUrl);
final Validator validator = schema.newValidator();
validator.validate(new StreamSource(xmlIs));
} catch (SAXException e) {
throw new ValidationException(XmlErrorType.XML_INVALID_AGAINST_SCHEMA, "xml invalid against its schema", e)
.addContextValue(XmlErrorContext.XML_FILE, xmlFile);
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_READING_FILE, e)
.addContextValue(FileErrorContext.FILE, xmlFile);
}
}
/**
* Validate an {@link File XML file} against the schema declared in the XML file.
*
* The schema must be found in the current folder {@code new File(".")}
*
* @param xmlFile the XML file.
* @see #validateXml(File, File)
*/
public static void validateXml(final File xmlFile) {
validateXml(xmlFile, new File("."));
}
/**
* Validate an {@link File XML file} against the schema declared in the XML file.
*
* The schema must be found in the given schem folder
*
* @param xmlFile the XML file.
* @param schemaFolder the folder where to search for schemas.
* @throws ApplicationException if no schema is declared in the XML file.
* @see #validateXmlAgainstSchema(File, URL)
*/
public static void validateXml(final File xmlFile, final File schemaFolder) {
final URL schemaUrl = XmlSchemaUtils.extractSchemaUrl(xmlFile, schemaFolder);
// schema location is defined in XML ?
if (schemaUrl == null) {
throw new ApplicationException(XmlErrorType.NO_SCHEMA_FOUND, "Cannot find internal schema URL")
.addContextValue(XmlErrorContext.XML_FILE, xmlFile);
}
validateXmlAgainstSchema(xmlFile, schemaUrl);
logger.info("XML file [{}] is valid against its schema [{}]", xmlFile, schemaUrl);
}
}