Analisar muito grandes documentos XML (e um pouco mais) em java

votos
18

(Todos os seguintes deve ser escrito em Java)

Eu tenho que criar um aplicativo que irá levá documentos XML como entrada que são, potencialmente, muito grande. O documento é criptografado - não com XMLsec, mas com algoritmo de criptografia preexistente do meu cliente - serão processados ​​em três fases:

Em primeiro lugar, o fluxo vai ser descriptografado de acordo com o algoritmo acima mencionado.

Em segundo lugar, uma classe de extensão (escrito por um terceiro para uma API que eu estou fornecendo) vai ler uma parte do arquivo. A quantidade que é lido não é previsível - em especial, não é garantido para ser no cabeçalho do arquivo, mas pode ocorrer em qualquer ponto do XML.

Por último, outra classe de extensão (a mesma coisa) vai subdividir o XML de entrada em documentos subconjunto 1..N. É possível que estes vontade em alguma parte se sobrepõem a parte do documento tratado pela segunda operação, ou seja: Eu acredito que vou precisar para rebobinar qualquer mecanismo que estou usando para lidar com esse objeto.

Aqui está a minha pergunta:

Existe uma maneira de fazer isso sem nunca ler toda a parte de dados na memória de uma só vez? Obviamente, eu posso implementar a descriptografia como um filtro de fluxo de entrada, mas não tenho certeza se é possível analisar XML da maneira que eu estou descrevendo; andando por cima tanto do documento é necessária para reunir as informações do segundo passo, e em seguida, rebobinando o documento e, passando-o novamente para dividi-lo em postos de trabalho, idealmente liberando todas as partes do documento que não estão mais em uso após eles foram passados.

Publicado 10/12/2008 em 13:41
fonte usuário
Em outras línguas...                            


6 respostas

votos
3

Você pode usar uma BufferedInputStreamcom um tamanho muito grande tampão e utilizar mark()antes da classe de extensão funciona e reset()depois.

Se as peças da classe de extensão precisa é muito longe para o arquivo, em seguida, isso pode tornar-se extremamente intensivo de memória, 'embora.

A solução mais geral seria escrever seu próprio BufferedInputStream-workalike que buffers para o disco se os dados que está a ser tamponado excede algum limiar predefinido.

Respondeu 10/12/2008 em 13:59
fonte usuário

votos
1

Você pode estar interessado por XOM :

XOM é bastante singular na medida em que é um streaming / API dupla baseada em árvore. nós individuais na árvore pode ser processado enquanto o documento ainda está sendo construída. O permite que programas XOM para operar quase tão rápido quanto o analisador subjacente pode fornecer dados. Você não precisa esperar para o documento a ser completamente analisado antes que você possa começar a trabalhar com ele.

XOM é muito eficiente de memória. Se você ler um documento inteiro na memória, XOM usa tão pouco de memória possível. Mais importante, XOM permite filtrar documentos como eles são construídos para que você não tem que construir as partes da árvore que você não está interessado. Por exemplo, você pode pular nós de texto edifício que representam apenas espaço em branco fronteira, se tal espaço em branco não é significativo em sua aplicação. Você pode até mesmo processar um pedaço documento por peça e jogar fora cada peça quando você está feito com ele. XOM foi usado para processar documentos que são gigabytes de tamanho.

Respondeu 10/12/2008 em 14:21
fonte usuário

votos
7

Isso soa como um trabalho para StAX ( JSR 173 ). StAX é um analisador pull, o que significa que ele funciona mais ou menos como um analisador baseado em eventos como SAX, mas que você tem mais controle sobre quando parar de leitura, que elementos de puxar, ...

A usabilidade desta solução vai depender muito do que suas classes de extensão estão realmente fazendo, se você tem o controle sobre a sua implementação, etc ...

O ponto principal é que, se o documento é muito grande, você provavelmente vai querer usar um analisador de evento com base e não uma árvore baseado, assim você não vai usar um monte de memória.

Implementações de StAX pode ser encontrado a partir SUN ( SJSXP ), Codehaus ou alguns outros fornecedores.

Respondeu 10/12/2008 em 14:24
fonte usuário

votos
12

Stax é o caminho certo. Eu recomendaria olhando para Woodstox

Respondeu 10/12/2008 em 14:41
fonte usuário

votos
3

Eu ia escrever uma implementação personalizada do InputStreamque decifra o bytes no arquivo e, em seguida, usar SAX para analisar o XML resultante como ele sai do córrego.

SAXParserFactory.newInstance().newSAXParser().parse(
  new DecryptingInputStream(), 
  new MyHandler()
);
Respondeu 10/12/2008 em 14:57
fonte usuário

votos
0

Olhe para o XOM biblioteca. O exemplo que você está procurando é StreamingExampleExtractor.javano diretório de exemplos da distribuição fonte. Isso mostra uma técnica para a realização de uma análise de streaming de um documento XML grande só a construção de nós específicos, processá-los e descartá-los. É muito semelhante a uma abordagem sax, mas tem muito mais capacidade de análise incorporada, para uma análise de streaming pode ser alcançado facilmente.

Se você deseja trabalhar em nível superior olhar para NUX . Isso proporciona um alto nível de streaming XPath API que só lê a quantidade de dados na memória necessários para avaliar o XPath.

Respondeu 10/03/2011 em 22:16
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more