Чтение большого XML-файла с использованием stax и dom - PullRequest
11 голосов
/ 21 февраля 2012

Мне нужно прочитать несколько больших (200–500 МБ) XML-файлов, поэтому я хочу использовать StaX. В моей системе два модуля - один для чтения файла (со StaX); другой модуль (модуль 'parser') предполагает получить единственную запись этого XML и проанализировать ее с помощью DOM. Мои XML-файлы не имеют определенной структуры - поэтому я не могу использовать JaxB. Как я могу передать модулю 'parser' определенную запись, которую я хочу проанализировать? Например:

<Items>
   <Item>
        <name> .... </name>
        <price> ... </price>
   </Item>
   <Item>
        <name> .... </name>
        <price> ... </price>
   </Item>
</Items>

Я хочу использовать StaX для анализа этого файла, но каждая запись 'item' будет передана в модуль 'parser'.

Edit:
После небольшого прочтения - я думаю, что мне нужна библиотека, которая читает XML-файл с использованием потока - но анализирует каждую запись с использованием DOM. Есть ли такая вещь?

Ответы [ 3 ]

18 голосов
/ 21 февраля 2012

Вы можете использовать синтаксический анализатор StAX (javax.xml.stream) и преобразовать (javax.xml.transform) каждый раздел в узел DOM (org.w3c.dom):

import java.io.*;
import javax.xml.stream.*;
import javax.xml.transform.*;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.dom.DOMResult;
import org.w3c.dom.*

public class Demo {

    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        xsr.nextTag(); // Advance to statements element

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) {
            DOMResult result = new DOMResult();
            t.transform(new StAXSource(xsr), result);
            Node domNode = result.getNode();
        }
    }

}

Также см .:

2 голосов
/ 19 декабря 2018

Ответ Блэза Дафана не ясен в чистой Java 7 и 8 из-за https://bugs.openjdk.java.net/browse/JDK-8016914

java.lang.NullPointerException
at com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.setXmlVersion(CoreDocumentImpl.java:860)
at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2DOM.setDocumentInfo(SAX2DOM.java:144)

Забавная вещь: если вы используете jaxb unmarshaller, вы не получите NPE:

package com.common.config;

import java.io.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.*;

import org.w3c.dom.*;

public class Demo {


    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        xsr.nextTag(); // Advance to root element
        xsr.next(); // Advance to first item or EOD

        final JAXBContext jaxbContext = JAXBContext.newInstance();
        final Unmarshaller unm = jaxbContext.createUnmarshaller();
        while(true) {
            // previous unmarshal() already did advance to next element or whitespace
            if (xsr.getEventType() == XMLStreamReader.START_ELEMENT) {
                JAXBElement<Object> jel = unm.unmarshal(xsr, Object.class);
                Node domNode = (Node)jel.getValue();
                System.err.println(domNode.getNodeName());
            } else if (!xsr.hasNext()) {
                    break;
            } else {
                xsr.next();
            }
        }
    }

}

Причина: com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXConnector$1 не реализует Locator2, поэтому у него нет getXMLVersion().

0 голосов
/ 21 февраля 2012

вы можете попробовать XMLDog из JLibs.

Он оценивает xpath в документе xml с использованием SAX (т.е. без загрузки всего xml в память). и возвращает dom-узлы для узлов при их попадании.

Таким образом, вы можете оценить xpath / Items / Item в вашем толстом XML-документе. Вы будете уведомлены, когда каждый узел Item будет проанализирован. Вы можете обработать текущий узел Item и продолжить.

Таким образом, он подходит для оценки xpaths для больших документов

...