使用Java中的StAX动态地动态拆分xml,替代方案?

时间:2016-01-11 09:03:28

标签: java xml inputstream stax

因为在有限(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>

... .. 。 有没有其他方法可以做类似的事情?

0 个答案:

没有答案