2011-10-12 10 views
6

Ho il seguente problema: Ho file XML molto grandi (come 300+ Meg), e ho bisogno di analizzarli per aggiungere alcuni dei loro valori al db. Anche la struttura di questi file è molto complessa. Voglio usare Stax Parser in quanto offre la possibilità di eseguire il pull-parsing (e quindi l'elaborazione) solo di parti del file XML alla volta, e quindi non caricare l'intera cosa in memoria, ma d'altra parte ottenere i valori con Stax (almeno su questi file XML) è ingombrante, ho bisogno di scrivere una tonnellata di codice. Da quest'ultimo punto di vista mi sarà di grande aiuto se potessi eseguire il marshalling del file XML su oggetti Java (come fa JAX-B), tuttavia questo caricherà tutto il file più una tonnellata di istanze Object in memoria tutte in una volta.Analisi di file XML di grandi dimensioni e marshalling su oggetti Java

La mia domanda è, c'è un modo per analizzare (o analizzare solo parzialmente) il file in modo sequenziale e quindi eseguire il marshalling solo di quelle parti sugli oggetti Java in modo che possa gestirle facilmente senza impattare sulla memoria?

risposta

2

Beh, prima di tutto voglio ringraziare i due persone rispondere alle mie domande, ma alla fine ho finito per non usare quelle proposizioni in parte perché queste tecnologie proposte sono un po 'lontano dalla Java di lasciare diciamo "standard XML parsing" e sembra strano andare così lontano quando c'è già uno strumento simile presente in Java e in parte anche perché in effetti ho trovato una soluzione che utilizza solo le API Java per ottenere questo risultato.

Non descriverò troppo la soluzione che ho trovato, perché ho già completato l'implementazione, ed è un bel pezzo di codice da inserire qui (io uso Spring Batch in cima a tutto, con una tonnellata di configurazione e roba).

Io comunque fare un piccolo commento su quello che ho finalmente finito per fare:

La grande idea qui è il fatto che se si dispone di un documento XML ed è corrispondente schema XSD, è possibile analizzare & marshall con JAXB, e puoi farlo in blocchi, e detti blocchi possono essere letti con un parser pari come STAX e quindi passati al Marshaller JAXB.

Questo praticamente significa che devi prima decidere dove si trova un buon posto nel tuo file XML dove puoi dire "questa parte qui ha MOLTA struttura ripetitiva, tratterò quelle ripetizioni una alla volta". Quelle parti ripetitive sono in genere lo stesso tag (figlio) ripetuto molto all'interno di un tag padre. Quindi tutto ciò che devi fare è creare un listener di eventi nel parser STAX che viene attivato all'inizio di ciascuno di questi tag figlio, quindi eseguire lo streaming su JAXB del contenuto di tale tag figlio, eseguirlo con JAXB ed elaborarlo.

molto l'idea è ottimamente descritta in questo articolo, che ho seguito (vero, è dal 2006, ma si tratta di JDK 1.6, che a quel tempo era abbastanza nuovo, quindi la versione-saggio non è che il vecchio a tutti):

http://www.javarants.com/2006/04/30/simple-and-efficient-xml-parsing-using-jaxb-2-0/

+0

Buono a sapersi risolvere il problema. Mi chiedo solo come è questo (soln in questo post) diverso da quello che ho postato? – Kashyap

+0

Beh, onestamente era parte della paura di grandi quadri, in parte pigrizia :) (entrambi sono cattivi e deplorevoli). Prima di tutto, dalla documentazione EMF sembra una struttura abbastanza coinvolta, non è solo per l'elaborazione XML ma per un sacco di altre cose, e cerco sempre di evitare quadri così pesanti quando possibile (questa è solo una preferenza personale, non lo sono dire è male farlo in generale). In secondo luogo, sono pigro e l'EMF utilizza API di analisi XML non standard che non conosco, anche per questo motivo ho preferito la soluzione con le API Java XML standard. –

+1

Infatti, che ti piacesse o meno l'EMF, ti ho raccomandato di NON usarlo ("** perché EMF è un martello troppo grande per un problema così piccolo. **") a meno che tu non abbia scelta. E a parte il parser, per citare di nuovo "così ** basta analizzare usando quello che vuoi **, creare uno StringStream o qualcosa per ogni in un ciclo e ** passare a JAX-B o EMF. **" – Kashyap

5

Vorrei raccomandare Eclipse EMF. Ma ha lo stesso problema, se gli dai il nome del file, analizzerebbe il tutto. Sebbene ci siano alcune opzioni per ridurre quanto viene caricato, ma non mi sono preoccupato molto di come eseguiamo su macchine con 96 GB di RAM. :)

In ogni caso, se il formato XML è ben definito, una soluzione è ingannare l'EMF suddividendo l'intero file in diversi frammenti XML più piccoli (ma ancora ben definiti). Quindi alimenta ogni frammento uno dopo l'altro. Non conosco JAX-B, ma forse la stessa soluzione alternativa può essere applicata anche lì. Che consiglierei, perché EMF è un martello troppo grande per un problema così piccolo.

Tanto per elaborare un po 'se il vostro XML è simile al seguente:

<tag1> 
    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 

    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 
............ 
    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 
</tag1> 

allora può essere suddiviso in uno XML ciascuna partendo <tag2> e termina con </tag2>. E in Java la maggior parte dei parser accetta un flusso, quindi analizza solo quello che vuoi, crea uno StringStream o qualcosa per ogni <tag2> in un ciclo e passa a JAX-B o EMF.

HTH

+0

Questo è qualcosa che suona alla grande e che cercherò prima cosa domani (è mezzanotte qui :)). Grazie per il suggerimento, sembra promettente –

+1

@thekashyap. Posso avere una di quelle macchine, per favore? Solo uno! –

+0

Hehe .. Queste sono le nostre macchine di prova, a casa lavoro su un laptop Win7 con 4GB come tutti gli altri .. :) – Kashyap

1

proiezione documento potrebbe essere la risposta qui. Saxon e una serie di altri processori XQuery offrono questo come opzione. Se si dispone di una query ragionevolmente semplice che seleziona una piccola quantità di dati da un documento di grandi dimensioni, il processore di query analizza la query per determinare quali parti dell'albero devono essere disponibili per la query e quali possono essere eliminate durante l'elaborazione. L'albero risultante può spesso essere solo l'1% delle dimensioni del documento completo. Dettagli per Saxon qui:

http://saxonica.com/documentation/sourcedocs/projection.xml

Problemi correlati