我一直在寻找这个问题的解决方案,考虑到它听起来有多么容易,所以我来寻求帮助。
我有一个XML Schema,我和xjc一起用来创建我的JAXB绑定。当XML格式正确时,这很好用。不幸的是,当XML格式不正确时,它也不会抱怨。当我尝试解组XML文件时,我无法弄清楚如何对模式进行适当的完全验证。
我设法使用ValidationEventCollector来处理事件,这些事件适用于XML解析错误,例如不匹配的标记,但是当有标记需要但完全不存在时,不会引发任何事件。
从我所看到的,验证可以针对模式进行,但您必须知道模式的路径才能将其传递给setSchema()方法。我遇到的问题是架构的路径存储在XML头中,我不能在架构运行时知道。这就是它存储在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);
}
那么进行此验证的正确方法是什么?我期待在JAXB生成的类上有一个validate()方法,但我想这对Java来说太简单了。
答案 0 :(得分:15)
好的,我找到了解决方案。使用模式工厂创建模式,但不指定模式文件使其可以使用XML文件中指定的noNamespaceSchemaLocation。
所以上面的代码添加了这个:
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema(schema);
m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));
在24小时内最好的部分找到答案的耻辱!
SchemaFactory.newSchema()
的javadoc说:
对于XML Schema,此方法创建一个 执行验证的架构对象 通过使用中指定的位置提示 文档。
返回的Schema对象假设 如果文件引用相同的话 它们是架构位置提示中的URL 将始终解析为相同的架构 文献。这个问题允许 重用解析的实现 架构文档的结果如此 针对相同的多次验证 架构运行得更快。
答案 1 :(得分:1)
据我所知,您只需将Marshaller.setSchema()架构设置为DDSSettings.xsd
中由SchemaFactory创建的架构。这将打开验证。