因为在有限(RAM)环境中处理大型xml文件可能是一个问题,特别是使用java并强制使用Jsoup作为解析器,我决定使用SAX和StAX进行“即时处理”:经过多次尝试我最后我的代码到目前为止我在互联网上找不到,因为它非常通用。
这个想法很简单,你有一个已经解压缩的inputStream,它包含一个XML文件,你需要将这个xml文件中的一个特定对象与它的内部XML代码分开或(chunk)并给出这个字符串到其他一些解析器(比如Jsoup)。
当然我的第一次尝试是使用Jsoup本机inputStream阅读器,但它实际上下载了完整的XML文件,然后使用大量的RAM解析它。
所以我的代码看起来像这样,我的单元测试工作得很完美,一切都接触到我好,但问题是,有时候,在其他服务器中使用某些XML只能提取(ODD)对象< / strong>,所以第1和第3等等,但不是(偶数)。
public int xmlStreamProcess(HandlerAPI productHandler, ...//some instructions) throws CupoHttpException {
int total = 0;
String element = ... // CSS selector for the element to take
String[] parameters = ... // instructions what to do with that element
XMLInputFactory factory = XMLInputFactory.newInstance();
try {
XMLStreamReader streamReader = factory.createXMLStreamReader(retrieveFileStream());
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty("omit-xml-declaration","yes"); // I tried this options didn't have difference
t.setOutputProperty("standalone","no"); // nothing changed
while (streamReader.hasNext()) {
int eventType = streamReader.next();
switch (eventType) {
case XMLStreamReader.START_ELEMENT:
String elementName = streamReader.getLocalName();
if (element.equals(elementName)) {
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
t.transform(new StAXSource(streamReader), result); // this is the only point where I loose information
String strResult = writer.toString(); // and here is the piece of XML ready to parse.
if (productHandler.apiHandle(Parser.map2Object(Parser.parseElement(Jsoup.parseBodyFragment(strResult), parameters))
)) {
total++;
}
}
default:
break;
}
streamReader.close();
}
} catch (Exception e) {
throw new CupoHttpException("Error in stream process", e);
} finally {
try {
disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
return total;
}
遗憾的是,我无法提供真正有效的xml示例,但正如您所看到的那样,它应适用于任何一个。
示例:输入=选择器“A_object”
<?xml version="1.0" encoding="UTF-8"?>
<example>
<one_level>
<A_object id=1>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
<A_object id=2>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
<A_object id=3>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
<A_object id=4>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
<A_object id=5>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
</one_level>
</example>
示例:输出
首先:
<A_object id=1>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
第二:
<A_object id=2>
<content_of_a>
</stuff>
</stuff>
</stuff>
</content_of_a>
</A_object>
... .. 。 有没有其他方法可以做类似的事情?