Validating against a Schema with JAXB

Posted by fwgx on Stack Overflow See other posts from Stack Overflow or by fwgx
Published on 2010-03-22T11:41:37Z Indexed on 2010/03/22 12:31 UTC
Read the original article Hit count: 321

Filed under:
|
|
|
|

I've been looking for solutions to this problem for far too long considering how easy it sounds so I've come for some help.

I have an XML Schema which I have used with xjc to create my JAXB binding. This works fine when the XML is well formed. Unfortunately it also doesn't complain when the XML is not well formed. I cannot figure out how to do proper full validation against the schema when I try to unmarshall an XML file.

I have managed to use a ValidationEventCollector to handle events, which works for XML parsing errors such as mismatched tags but doesn't raise any events when there is a tag that is required but is completely absent.

From what I have seen validation can be done againsta schema, but you must know the path to the schema in order to pass it into the setSchema() method. The problem I have is that the path to the schema is stored in the XML header and I can't knwo at run time where the schema is going to be. Which is why it's stored in the XML file:

<?xml version="1.0" encoding="utf-8"?>
<DDSSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="/a/big/long/path/to/a/schema/file/DDSSettings.xsd">
<Field1>1</Field1>
<Field2>-1</Field2>

...etc

Every example I see uses setValidating(true), which is now deprecated, so throws an exception.

This is the Java code I have so far, which seems to only do XML validation, not schema validation:

try
{
JAXBContext jc = new JAXBContext()
{
private final JAXBContext jaxbContext = JAXBContext.newInstance("blah");

@Override
public Unmarshaller createUnmarshaller() throws JAXBException
{
 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
 ValidationEventCollector vec = new ValidationEventCollector()
 {
  @Override
  public boolean handleEvent(ValidationEvent event) throws RuntimeException
  {
   ValidationEventLocator vel = event.getLocator();
   if (event.getSeverity() == event.ERROR || event.getSeverity() == event.FATAL_ERROR)
   {
    String error = "XML Validation Exception:  " + event.getMessage() + " at row: " + vel.getLineNumber() + " column: " + vel.getColumnNumber();
    System.out.println(error);
   }
   m_unmarshallingOk = false;
   return false;
  }
 };
 unmarshaller.setEventHandler(vec);

 return unmarshaller;
}

@Override
public Marshaller createMarshaller() throws JAXBException
{
 throw new UnsupportedOperationException("Not supported yet.");
}

@Override
@SuppressWarnings("deprecation")
public Validator createValidator() throws JAXBException
{
 throw new UnsupportedOperationException("Not supported yet.");
}

};

    Unmarshaller unmarshaller = jc.createUnmarshaller();
   m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));
}
catch (UnmarshalException ex)
{
    Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
   Level.SEVERE,
   null, ex);
}
catch (JAXBException ex)
{
    Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
   Level.SEVERE,
   null, ex);
}

So what is the proper way to do this validation? I was expecting there to be a validate() method on the JAXB generated classes, but I guess that would be too simple for Java.

© Stack Overflow or respective owner

Related posts about Xml

Related posts about schema