我看到了多个与使用 woodstox 和 JAXB 解析 xml 相关的问题,以使用
XMLStreamReader
解组并根据模式进行验证。尽管阅读它们并没有帮助。我需要的是使用本地 DTD 验证传入的 xml,并将整个内容解析为对象表示形式。传入的 xml 可以具有包含 DTD 的 DOCTYPE。这需要被跳过并需要使用本地 DTD。实施应该非常快。预计< 1ms to do the validation and parsing. I could manage to parse alone using the following in 5ms. Incorporating validation doesn't work with setting the schema (commented lines of code)
xmlif = XMLInputFactory2.newInstance();
xmlif.setProperty(XMLInputFactory2.SUPPORT_DTD, false);
JAXBContext ucontext;
ucontext = JAXBContext.newInstance(XMLOuterElementClass.class);
unmarshaller = ucontext.createUnmarshaller();
/*SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.XML_DTD_NS_URI);
Schema schema = sf.newSchema(new File("c:/resources/schma.dtd"));
unmarshaller.setSchema(schema);*/
XMLStreamReader xsr = xmlif
.createXMLStreamReader(new StringReader(xml));
//xsr = new StreamReaderDelegate(xsr);
long start = System.currentTimeMillis();
try {
while (xsr.hasNext()) {
if (xsr.isStartElement()
&& xsr.getLocalName() == "XMLOuterElementClass") {
break;
}
xsr.next();
}
JAXBElement<XMLOuterElementClass> jb = unmarshaller.unmarshal(xsr,
XMLOuterElementClass.class);
System.out.println("Total time taken in ms :" + (end - start));
} finally {
xsr.close();
}
有多种方法可以实现;获得更深入答案的最佳方法是在 Woodstox 用户列表上询问(请参阅 https://groups.google.com/g/woodstox-user)。
但需要注意的一件事是,JAXB 对 Stax2 一无所知(Woodstox/Aalto 对基本 Stax 的扩展),因此您需要通过 Stax2 API 访问它,而不是 JAXB。因此,要启用“外部”验证,您需要调用:
xmlStreamReader2.validateAgainst(schemaFromDTD);
您可以在构建流读取器后立即执行此操作(需要转换为
XMLStreamReader2
,或至少转换为Validatable
)。
请注意,您可以在读取或写入时进行验证,两者的工作原理类似(在后一种情况下,您可以通过XMLStreamWriter
启用它)。
另一种可能性是定义
XMLResolver
属性(参见 XMLInputFactory.RESOLVER
)。
当尝试读取外部 dtd 时,即当 DOCTYPE 包含对外部文件的引用时,它会被调用。然后,自定义 XMLResolver
可以重定向此读取以使用其他来源。
请注意,第一种方法(您开始使用的方法)可能更有效,因为它只需要读取和解析架构一次,假设您读取一次并随后重用。 验证本身应该很快,如果解析需要 4 毫秒,则不应超过 1 毫秒;特别是如果您在 4 毫秒内包含 JAXB 处理(这在技术上是数据绑定,高于较低级别的解析)。