Я искал решения этой проблемы слишком долго, учитывая, насколько легко это звучит, поэтому я пришла за помощью.
У меня есть XML-схема, которую я использовал с xjc для создания привязки JAXB. Это отлично работает, когда XML хорошо сформирован. К сожалению, он также не жалуется, когда XML не очень хорошо сформирован. Я не могу понять, как сделать правильную полную проверку против схемы, когда я пытаюсь разобрать XML файл.
Мне удалось использовать ValidationEventCollector для обработки событий, который работает для XML-анализа синтаксических ошибок, таких как несогласованные теги, но не вызывает никаких событий, когда есть тег, который требуется, но полностью отсутствует.
Из того, что я видел, проверка может быть проведена против схемы, но вы должны знать путь к схеме, чтобы передать ее в метод setSchema(). Проблема в том, что путь к схеме хранится в заголовке XML, и я не могу knwo во время выполнения, где будет схема. Вот почему он хранится в XML файле:
<?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>
... и т.д.
Каждый пример, который я вижу, использует setValidating (true), который теперь устарел, поэтому генерирует исключение.
Это код Java, который у меня есть до сих пор, который, похоже, выполняет только проверку XML, а не проверку схемы:
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);
}
Итак, каков правильный способ сделать эту проверку? Я ожидал, что будет существовать метод validate() на сгенерированных классах JAXB, но я думаю, это было бы слишком просто для Java.