user2714602
user2714602

Reputation: 231

JAXB check if xml is valid for the declared xsd

I need to know if an xml is valid before calling the unmarshal method of the Unmarshaller.

Now I do this:

JAXBContext jaxbContext = JAXBContext.newInstance("package");

final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final File xsdFile = new File("pathtoxsd/file.xsd");
final Schema schema = schemaFactory.newSchema(xsdFile);

unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(new ValidationEventHandler() {
    @Override
    public boolean handleEvent(ValidationEvent arg0)
    {
            return false;
    }
});

final File xmlFile = new File("pathtoxml/fileName.xml");

final Object unmarshalled = unmarshaller.unmarshal(xmlFile);

But I want to do not be forced to know where is the xsd. The xsd path should be only declared by the xml inside of it and the marshaller should follow the path declared by the xml.

Upvotes: 2

Views: 1205

Answers (1)

bdoughan
bdoughan

Reputation: 148977

You could do something like the following:

  1. Parse the XML document with a StAX parser.
  2. Advance to the root element.
  3. Grab the schemaLocation attribute (you may also need to handle the noNamespaceSchemaLocation attribute).
  4. Grab the path to the XSD from that value (part after the space).
  5. Create the Schema based on that value.
  6. Set the Schema on the Unmarshaller.
import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource xml = new StreamSource("src/forum21317146/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);
        xsr.next();

        JAXBContext jc = JAXBContext.newInstance(Foo.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();

        String schemaLocation = xsr.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "schemaLocation");
        if(null != schemaLocation) {
            String xsd = schemaLocation.substring(schemaLocation.lastIndexOf(' ') + 1);
            SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema = schemaFactory.newSchema(new StreamSource(xsd));
            unmarshaller.setSchema(schema);
        }

        unmarshaller.unmarshal(xsr);

    }

}

Upvotes: 1

Related Questions