Sono stato alla ricerca di soluzioni a questo problema per troppo tempo considerando quanto sia facile sembrare così sono venuto per un po 'di aiuto.Convalida con uno schema con JAXB
Ho uno schema XML che ho usato con xjc per creare il mio binding JAXB. Funziona bene quando l'XML è ben formato. Sfortunatamente non si lamenta anche quando l'XML non è ben formato. Non riesco a capire come fare una corretta validazione completa contro lo schema quando provo a decomprimere un file XML.
Sono riuscito a utilizzare un ValidationEventCollector per gestire gli eventi, che funziona per errori di analisi XML come tag non corrispondenti ma non genera alcun evento quando c'è un tag richiesto ma completamente assente.
Da quello che ho visto la convalida può essere eseguita di nuovo sullo schema, ma è necessario conoscere il percorso dello schema per passarlo nel metodo setSchema(). Il problema che ho è che il percorso dello schema è memorizzato nell'intestazione XML e non posso knwo in fase di esecuzione in cui lo schema sarà. Quale è il motivo per cui è memorizzato nel file XML:
<?xml version="1.0" encoding="utf-8"?>
<DDSSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://stackoverflow.com/a/big/long/path/to/a/schema/file/DDSSettings.xsd">
<Field1>1</Field1>
<Field2>-1</Field2>
... ecc
Ogni esempio che vedo utilizza setValidating (vero), che ora è deprecato, quindi genera un'eccezione.
Questo è il codice Java che ho finora, che sembra di fare solo la validazione XML, senza schema di convalida:
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);
}
Allora, qual è il modo corretto di fare questa convalida? Mi aspettavo che ci fosse un metodo validate() sulle classi generate da JAXB, ma immagino che sarebbe troppo semplice per Java.
Interessante, non lo sapevo. Mi sono permesso di aggiungere alcune informazioni alla tua risposta, per riferimento futuro. – skaffman
Invece di specificare esplicitamente l'URL XMLSchema, per javadocs, utilizzare il valore appropriato da XMLConstants come specificato qui: http://docs.oracle.com/javase/6/docs/api/index.html?javax/xml/validation /Schema.html – icfantv
@icfantv, abbiamo ragione, io utilizzo: Schema schema = SchemaFactory.newInstance (XMLConstants.W3C_XML_SCHEMA_NS_URI) .newSchema(); // ma il riferimento era: http://docs.oracle.com/javase/6/docs/api/index.html?javax/xml/validation/Schema.html - Inoltre la cosa che non ho capito di questa soluzione è che l'url è costante: non si riferisce alla posizione del nostro schema (non era ovvio per me) – pdem