Ho bisogno di analizzare file XML di grandi dimensioni, di cui lo schema mi è già stato fornito in diversi file XSD, quindi il binding XML è molto favorito. Mi piacerebbe sapere se posso usare JAXB per analizzare il file in blocchi e se sì, come.JAXB può analizzare file XML di grandi dimensioni in blocchi
risposta
Questo è dettagliato nel user guide. Il download JAXB da http://jaxb.java.net/ include un esempio di come analizzare un blocco alla volta.
Quando un documento è di grandi dimensioni, è solito perché c'è ripetitivo parti in esso. Forse è un acquisto ordine con un ampio elenco di elementi pubblicitari, o forse si tratta di un file di registro XML con numero elevato di voci di registro.
Questo tipo di XML è adatto per l'elaborazione di blocchi ; l'idea principale è di utilizzare l'API StAX, eseguire un ciclo e singoli pezzi unmarshal separatamente. Il tuo programma agisce su un singolo pezzo e poi lo getta via. In questo modo manterrai solo il numero di in memoria, il che consente a di elaborare documenti di grandi dimensioni.
Vedi l' esempio di streaming-unmarshalling e la esempio parziale unmarshalling nella distribuzione JAXB RI per di più su come fare questo. L'esempio streaming unmarshalling ha un vantaggio di poter gestire blocchi a livello di nido arbitrario, ma richiede ad affrontare con il modello push --- JAXB unmarshaller sarà "push" nuova pezzo a voi e voi' Avrai bisogno di processarli subito lì.
Al contrario, il esempio parziale deserializzazione lavora in un modello pull (che solito rende il trattamento più semplice), ma questo approccio ha alcune limitazioni in porzioni associazione dati diversi dal ripetuti parte.
Poiché il codice è importante, ecco un PartialUnmarshaller
che legge un grosso file in blocchi. Può essere utilizzato in questo modo new PartialUnmarshaller<YourClass>(stream, YourClass.class)
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.*;
import java.io.InputStream;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static javax.xml.stream.XMLStreamConstants.*;
public class PartialUnmarshaller<T> {
XMLStreamReader reader;
Class<T> clazz;
Unmarshaller unmarshaller;
public PartialUnmarshaller(InputStream stream, Class<T> clazz) throws XMLStreamException, FactoryConfigurationError, JAXBException {
this.clazz = clazz;
this.unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
this.reader = XMLInputFactory.newInstance().createXMLStreamReader(stream);
/* ignore headers */
skipElements(START_DOCUMENT, DTD);
/* ignore root element */
reader.nextTag();
/* if there's no tag, ignore root element's end */
skipElements(END_ELEMENT);
}
public T next() throws XMLStreamException, JAXBException {
if (!hasNext())
throw new NoSuchElementException();
T value = unmarshaller.unmarshal(reader, clazz).getValue();
skipElements(CHARACTERS, END_ELEMENT);
return value;
}
public boolean hasNext() throws XMLStreamException {
return reader.hasNext();
}
public void close() throws XMLStreamException {
reader.close();
}
void skipElements(int... elements) throws XMLStreamException {
int eventType = reader.getEventType();
List<Integer> types = asList(elements);
while (types.contains(eventType))
eventType = reader.next();
}
}
Ho bisogno di utilizzare XMLStreamConstants.START_DOCUMENT e così via affinché funzioni. –
@MatthiasWuttke è possibile aggiungerli come importazione statica. importazione statica javax.xml.stream.XMLStreamConstants. *; –
Potrebbe anche essere necessario Ints.asList di Guava o in java8 IntStream.of (elementi) .boxed(). Collect (Collectors.toList()); –
risposta di Yves Amsellem è piuttosto buona, ma funziona solo se tutti gli elementi sono esattamente dello stesso tipo. Altrimenti l'unmarshall genererà un'eccezione, ma il lettore avrà già consumato i byte, quindi non sarebbe possibile ripristinarli. Invece, dovremmo seguire il consiglio di Skaffman e guardare l'esempio dal barattolo JAXB.
Per spiegare come funziona:
- Creare un unmarshaller JAXB.
- Aggiungi un listener allo Unmarshaller per intercettare gli elementi appropriati. Questo viene fatto "hacking" da ArrayList per garantire che gli elementi non vengano archiviati in memoria dopo essere stati eliminati.
- Creare un parser SAX. Questo è dove avviene lo streaming.
- Utilizzare unmarshaller per generare un gestore per il parser SAX.
- Stream!
Ho modificato la soluzione in modo generico *. Tuttavia, ha richiesto un po 'di riflessione. Se questo non è OK, si prega di guardare gli esempi di codice nei barattoli JAXB.
ArrayListAddInterceptor.java
import java.lang.reflect.Field;
import java.util.ArrayList;
public class ArrayListAddInterceptor<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
private AddInterceptor<T> interceptor;
public ArrayListAddInterceptor(AddInterceptor<T> interceptor) {
this.interceptor = interceptor;
}
@Override
public boolean add(T t) {
interceptor.intercept(t);
return false;
}
public static interface AddInterceptor<T> {
public void intercept(T t);
}
public static void apply(AddInterceptor<?> interceptor, Object o, String property) {
try {
Field field = o.getClass().getDeclaredField(property);
field.setAccessible(true);
field.set(o, new ArrayListAddInterceptor(interceptor));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Main.java
public class Main {
public void parsePurchaseOrders(AddInterceptor<PurchaseOrder> interceptor, List<File> files) {
try {
// create JAXBContext for the primer.xsd
JAXBContext context = JAXBContext.newInstance("primer");
Unmarshaller unmarshaller = context.createUnmarshaller();
// install the callback on all PurchaseOrders instances
unmarshaller.setListener(new Unmarshaller.Listener() {
public void beforeUnmarshal(Object target, Object parent) {
if (target instanceof PurchaseOrders) {
ArrayListAddInterceptor.apply(interceptor, target, "purchaseOrder");
}
}
});
// create a new XML parser
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler(unmarshaller.getUnmarshallerHandler());
for (File file : files) {
reader.parse(new InputSource(new FileInputStream(file)));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
* Questo codice non è stato testato ed è solo a scopo illustrativo.
- 1. Elaborazione di file xml di grandi dimensioni
- 2. Analisi di file pseudo-xml di grandi dimensioni in python
- 3. creazione di file xml di grandi dimensioni in rubino
- 4. Come analizzare un file XML di grandi dimensioni in Haskell con una quantità limitata di risorse?
- 5. Visualizzazione di file XML di grandi dimensioni in eclissi?
- 6. Come analizzare file XML molto grandi in C#?
- 7. Come eseguire lo streaming di file di grandi dimensioni utilizzando JAXB Marshaller?
- 8. File JSON di grandi dimensioni
- 9. Oracle: caricamento di un file xml di grandi dimensioni?
- 10. Leggi file di grandi dimensioni in parallelo?
- 11. Come convalidare file XML di grandi dimensioni (> 100 MB)
- 12. Lettura di documenti XML di grandi dimensioni in .net
- 13. Scompattiamo file di grandi dimensioni con gzip in PHP
- 14. Lettura di file molto grandi (~ 1 TB) in blocchi sequenziali
- 15. xmlstarlet sel su file di grandi dimensioni
- 16. Memorizzazione di XML di grandi dimensioni in MongoDB
- 17. Come analizzare in modo efficiente file di testo di grandi dimensioni in Ruby
- 18. Supporto file di grandi dimensioni in C++
- 19. Leggere file di grandi dimensioni in Java
- 20. Come analizzare il file XML in RapidXML
- 21. JAXB Java - Scrittura di file XML con logica di riavvio
- 22. Impossibile analizzare il messaggio XML con JAXB org.springframework.oxm.UnmarshallingFailureException
- 23. Pdf RDF di grandi dimensioni in Python
- 24. Trova e sostituisci in un file di grandi dimensioni
- 25. Analisi di file XML di grandi dimensioni e marshalling su oggetti Java
- 26. PyInstaller dimensioni file molto grandi
- 27. Come organizzare file di grandi dimensioni?
- 28. elaborazione JAXB di sequenze XML
- 29. analisi di file xml di grandi dimensioni con Python - errore etree.parse
- 30. PDFbox caricamento di file di grandi dimensioni
Sì, questo è uno dei siti che ho trovato durante la ricerca di questo, ma non sono riuscito a trovare gli esempi di "streaming-unmarshalling" e "partial-unmarshalling" a cui si fa riferimento nella sezione 4.4.1. –
Dispari. Dove stai guardando? Ho appena scaricato il JAR da jaxb.dev.java.net/2.1.12, decompresso, e lì sotto "samples" è "partial-unmarshalling" e "stream-unmarshalling". – skaffman