arquivo XML enorme: Do que eu li uma “página” e processá-lo cada vez?

StackOverflow https://stackoverflow.com/questions/1913551

  •  19-09-2019
  •  | 
  •  

Pergunta

Eu preciso para processar um arquivo XML grande, 4G. Eu costumava dom4j SAX, mas escrevi o meu próprio DefaultElementHandler. framework de código como abaixo:

SAXParserFactory sf = SAXParserFactory.newInstance();   
SAXParser sax = sf.newSAXParser();   
sax.parse("english.xml", new DefaultElementHandler("page"){   
public void processElement(Element element) { 
// process the element
}
});    

Eu pensei que estava processando a enorme arquivo "página" por "página". Mas não parece, como eu sempre tive o erro de memória outof. Eu perdi alguma coisa importante? Obrigado. Eu sou novo para processo XML.

Foi útil?

Solução

Seus DefaultElement aparência de implementação confuso para mim. Parece que tudo está se acumulando em sBuilder e nunca fica limpo até encontrar o fim do elemento raiz, ou, mais provavelmente, ficar sem memória.

Como ler no texto elemento depende de que tipo de xml que você precisa para analisar. Cada elemento pode ter texto e pode ser intercalada com elementos filhos. Geralmente não é o tipo de xml que você vê em serviços web e arquivos de configuração, onde todo o elemento de texto está nos elementos da folha, em seguida, há casos, como XHTML, onde a coisa intercalando está acontecendo.

Se a forma como o esquema da sua xml funciona é que todas as informações do texto está nos elementos da folha, então você pode tamponar o texto que se começando com startElement, e usar o texto acumulado em endElement, em seguida, limpar o buffer.

Aqui está um bom artigo sobre SAX: http: //www.javaworld.com/javaworld/jw-08-2000/jw-0804-sax.html

Outras dicas

Bem, você realmente não processar XML pela página, no entanto, se você estender XMLFilterImpl vez de usar o DefaultElementHandler (qualquer que seja), então você pode simplesmente processar os elementos XML como eles vêm. Você vai ser streaming assim não haverá nenhum caso quando todo o documento está na memória (como uma questão prática).

Você essencialmente obter chamado para o elemento evento, no início do elemento, para os atributos, para o texto dentro, e depois no final do elemento (olhada nos métodos na interface ContentHandler). Com base nessas chamadas você faz o seu processamento (você provavelmente precisará ter algumas estruturas de dados onde se acumulam os elementos dentro de sua "página" elemento. Observe também que não há garantia de que você vai ter apenas uma chamada para o texto (é até o analisador).

Será que isso ajuda torná-lo mais claro?

Eu acho que ele só ler todo o conteúdo dentro do elemento, como eu apenas segui o exemplo online ...

classe abstrata pública DefaultElementHandler estende DefaultHandler { boolean privados começar; tagName private String; privado StringBuilder sBuilder;

public DefaultElementHandler(String tagName) {
    this.tagName = tagName;
    this.begin = false;
    this.sBuilder = new StringBuilder();
}

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    if (qName.equals(tagName)||begin){
        sBuilder.append("<");
        sBuilder.append(qName);
        sBuilder.append(" ");
        int attrCount = attributes.getLength();
        for (int i=0; i<attrCount; i++) {
            sBuilder.append(attributes.getQName(i));
            sBuilder.append("=\"");
            sBuilder.append(attributes.getValue(i));
            sBuilder.append("\" ");
        }
        sBuilder.append(">");
        begin = true;
    }
}

public void characters(char[] ch, int start, int length) throws SAXException{       
    StringBuilder sb = new StringBuilder();
    for(int i=0; i < length; i++) {
        sb.append(convertSpecialChar(ch[start+i]));
    }

    String text = sb.toString().trim();      
    //String text = new String(convertSpecialChar(ch), start, length);
    if (text.trim().equals("")) return;
    if (begin) sBuilder.append(text);
}

public void endElement(String uri, String localName, String qName) throws SAXException {
    String stag = "</" + tagName + ">";   
    String ntag = "</" + qName + ">";   
    if (stag.equals(ntag) || begin) {   
        sBuilder.append(ntag);   
        if (stag.equals(ntag)) {   
            begin = false;   
            try {   
                Document doc = DocumentHelper.parseText(sBuilder.toString());   
                Element element = doc.getRootElement();   
                this.processElement(element);   
            } catch (DocumentException e) {   
                e.printStackTrace();  
                System.exit(1);
            }   
            sBuilder.setLength(0);   
        }   
    }   
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top