我已经看到了多个问题,这些问题与使用woodstox和JAXB解析xmls使用XMLStreamReader
解组并验证模式有关。尽管它们没有帮助。我需要的是使用本地DTD验证传入的xml并将整个内容解析为对象表示。传入的xml可以具有包含DTD的DOCTYPE。这需要被跳过,需要使用本地DTD。实施应该非常快。预期< 1ms进行验证和解析。我可以设法在5ms内使用以下内容单独解析。合并验证不适用于设置架构(注释的代码行)
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();
}
答案 0 :(得分:3)
有多种方法可以做到;获得更深入答案的最佳方式是在Woodstox用户列表中询问此问题(参见http://xircles.codehaus.org/projects/woodstox/lists)。
但有一点需要注意的是,JAXB对Stax2(基本Stax上的Woodstox / Aalto扩展)一无所知,因此您需要通过Stax2 API而不是JAXB来访问它。因此,要启用“外部”验证,您需要调用:
xmlStreamReader2.validateAgainst(schemaFromDTD);
您可以在构建流阅读器之后立即执行此操作(需要转换为XMLStreamReader2
,或至少转换为Validatable
)。
请注意,您可以在阅读或写作时进行验证,两者的工作方式类似(在后一种情况下,您通过XMLStreamWriter
启用它。)
另一种可能性是定义XMLResolver
属性(参见XMLInputFactory.RESOLVER
)。
它在尝试读取外部dtd时被调用,也就是说,当DOCTYPE包含对外部文件的引用时。然后,自定义XMLResolver
可以重定向此读取以使用其他来源。
请注意,第一种方法(您开始使用的方法)可能更有效,因为它只需要读取和解析一次Schema,假设您只读取一次并在之后重用。 验证本身应该很快,如果解析需要4毫秒,则不应超过1毫秒;特别是如果你在4毫秒内包含JAXB处理(这在技术上是数据绑定,在低级解析之上)。