Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java解析大型XML文档_Java_Xml - Fatal编程技术网

Java解析大型XML文档

Java解析大型XML文档,java,xml,Java,Xml,我试图解析并替换一个大xml文件中的值,每个文件大约45MB。我这样做的方式是: private void replaceData(File xmlFile, File out) { DocumentBuilderFactory df = DocumentBuilderFactory.newInstance(); DocumentBuilder db = df.newDocumentBuilder(); Document xmlDoc = db.parse(xmlFile

我试图解析并替换一个大xml文件中的值,每个文件大约45MB。我这样做的方式是:

private void replaceData(File xmlFile, File out)
{
    DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = df.newDocumentBuilder();
    Document xmlDoc = db.parse(xmlFile);
    xmlDoc.getDocumentElement().normalize();

    Node allData = xmlDoc.getElementsByTagName("Data").item(0);
    Element ctrlData = getSubElement(allData, "ctrlData");
    NodeList subData = ctrlData.getElementsByTagName("SubData");

    int len = subData.getLength();

    for (int logIndex = 0; logIndex < len; logIndex++) {

        Node log = subData.item(logIndex);
        Element info = getSubElement(log, "info");
        Element value = getSubElement(info, "dailyInfo");
        Node valueNode = value.getElementsByTagName("value").item(0);
        valueNode.setTextContent("blah");               
    }

    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer t = tf.newTransformer();
    DOMSource s = new DOMSource(xmlDoc);
    StreamResult r = new StreamResult(out);
    t.transform(s, r);

    } catch (TransformerException | ParserConfigurationException | SAXException | IOException e) {
         throw e;
    }
}

private static Element getSubElement(Node node, String elementName)
{
        return (Element)((Element)node).getElementsByTagName(elementName).item(0);
}
private void replaceData(文件xmlFile,文件out)
{
DocumentBuilderFactory df=DocumentBuilderFactory.newInstance();
DocumentBuilder db=df.newDocumentBuilder();
文档xmlDoc=db.parse(xmlFile);
xmlDoc.getDocumentElement().normalize();
节点allData=xmlDoc.getElementsByTagName(“数据”).item(0);
元素ctrlData=getSubElement(所有数据,“ctrlData”);
NodeList subData=ctrlData.getElementsByTagName(“子数据”);
int len=subData.getLength();
对于(int-logIndex=0;logIndex
我注意到,当我沿着for循环走得更远时,它所花费的时间就越长,而对于平均100k节点,它需要2个多小时,而如果我只是用1k的手来分解更小的块,则需要大约10秒。该文档的解析方式是否存在效率低下的问题

----编辑----

基于对此的评论和回答,我转而使用Sax和XmlStreamWriter。此处的参考/示例:


在使用SAX之后,replaceData函数的内存使用不会扩展到XML文件的大小,XML文件处理时间平均约为18秒。

正如人们在评论中提到的,将整个
DOM
加载到内存中,特别是对于大型XML,效率可能非常低,因此更好的方法是使用消耗恒定内存的
SAX
解析器。缺点是,您无法获得将整个DOM存储在内存中的流畅API,如果您希望在嵌套节点中执行复杂的回调逻辑,那么可见性非常有限

如果您感兴趣的只是解析特定的节点和节点族,而不是解析整个XML,那么有一个更好的解决方案,它可以让您充分利用这两个方面的优势,并且已经得到了广泛的应用。它基本上是SAX解析器之上的一个非常轻巧的包装器,您可以在其中注册感兴趣的XML元素,并且在获得回调时,可以使用相应的部分DOM到XPath


通过这种方式,您可以在保持复杂性不变的情况下(扩展到上面博客中记录的超过1GB的XML文件),同时保持XPath的流畅性,并对您感兴趣的XML元素的DOM进行处理。

当XSLT是为这项任务设计的时,为什么要在Java中这样做

45Mb是一个可以保存在内存中的大文件,但仍然可行。好的XSLT处理器(如Saxon)使用的树模型比通用DOM(例如,因为它们是只读的)更高效(在存储空间和搜索速度方面)。XSLT还有更大的范围来优化代码


我不能从代码中逆向工程您的规范,但我在您的描述中没有看到任何本质上非线性的东西。我看不出有任何理由说明在撒克逊这样做需要10分钟左右。

dimensionValue
是从哪里来的?它去哪里了?与
维度相同
。啊,很抱歉,在简化代码时忘记编辑该维度。这些值是数组(int[])查找。如果我有类似的问题,我会使用一个简单的方法:让代码在调试器中运行,并经常随机停止它。它最常停的地方是最慢的。非常简单,效率很高。玩得开心。使用SAXAPI而不是将整个DOM加载到内存中会更有效率。诚然,代码可能不那么可读……我没有看到使用SAX解析器替换xml值的方法。在这一点上,这不就等同于仅仅使用字符串缓冲区读取xml文件并逐行替换值吗?谢谢,我使用下面的示例切换到使用SAX和XmlStreamWriter:。对于同一组数据,读取/替换/写入时间现在缩短到18秒。