2009-01-25 21 views
9

Ich bin auf der Suche nach einer großen XML-Datei in kleinere Bits zu teilen. Ich möchte die Datei nach einem bestimmten Tag durchsuchen, dann alle Informationen zwischen und dann in eine Datei speichern und dann durch den Rest der Datei weitergehen.Teilen einer großen XML-Datei in Python

Mein Problem versucht, eine saubere Art und Weise zu finden, den Anfang und das Ende der Tags zu beachten, so dass ich den Text nach innen greifen kann, wie ich mit „für Zeile in f“ durch die Datei scannen

I‘ Ich verwende keine Sentinel-Variablen. Gibt es einen pythischen Weg, um das zu erreichen?

Die Datei ist zu groß, um sie in den Speicher einzulesen.

+1

Versuchen http://stackoverflow.com/search?q=iterparse – jfs

+0

wenn Sie jython und 64-Bit-JVM verwenden, können Sie erweiterte vtd-xml verwenden Splitting zu tun, die eleganteste/simple/effiziente Art –

Antwort

6

Sie könnten die Funktion ElementTree iterparse für diese Situation verwenden.

+0

ElementTree ist in stdlib – jfs

+1

Dank Jeff - nicht nur dies zähmte ein Speicher Schwein, aber ich habe jetzt 3 Zeilen Code anstelle von 20 –

9

Es gibt zwei gebräuchliche Methoden zum Umgang mit XML-Daten.

Einer heißt DOM, was für Document Object Model steht. Diese Art des XML-Parsens ist wahrscheinlich das, was Sie bei der Betrachtung der Dokumentation gesehen haben, da sie das gesamte XML in den Speicher liest, um das Objektmodell zu erstellen.

Die zweite heißt SAX, was eine Streaming-Methode ist. Der Parser beginnt mit dem Lesen der XML und sendet Signale an Ihren Code über bestimmte Ereignisse, z. wenn ein neues Start-Tag gefunden wird.

So SAX ist eindeutig, was Sie für Ihre Situation brauchen. Sax Parser können in der Python-Bibliothek unter xml.sax und xml.parsers.expat gefunden werden.

+0

+1: SAX Dekomposition von großen XML-Dokumenten. –

+0

vtd-xml ist viel besser als entweder dom oder sax –

+1

Es sieht für mich wie vtd-xml ist DOM.Man kann es "random-access" oder "Document-centric" nennen, aber das ist immer noch DOM. Es sieht so aus, als hätte vtd-xml eine starke Analyse und Indexierung, aber es ist immer noch DOM. –

1

Wie zufällig! Will Larson hat gerade einen guten Beitrag über Handling Very Large CSV and XML File in Python gemacht.

Die wichtigsten takeaways scheinen zu sein, das xml.sax Modul zu verwenden, wie Van erwähnte, und einige Makrofunktionen zu machen, um die Details der Low-Level-SAX-API zu abstrahieren.

6

Ich hatte Erfolg mit der Methode cElementTree.iterparse, um eine ähnliche Aufgabe zu erledigen.

Ich hatte eine große XML-Dokument mit wiederholten 'Einträge' mit dem Tag 'ResFrame' und ich wollte Einträge für eine bestimmte ID herausfiltern. Hier ist der Code, den ich für sie verwendet:

Quelldokument hatte diese Struktur

<snapDoc> 
    <bucket>....</bucket> 
    <bucket>....</bucket> 
    <bucket>....</bucket> 
    ... 
    <resFrame><id>234234</id>.....</resFrame> 
    <frame><id>344234</id>.....</frame> 
    <resFrame>...</resFrame> 
    <frame>...</frame> 
</snapDoc> 

ich das folgende Skript verwendet, um einen kleineren doc zu erstellen, die die gleiche Struktur hatte, Eimer Einträge und nur resFrame Einträge mit einem spezifische ID

#!/usr/bin/env python2.6 

import xml.etree.cElementTree as cElementTree 
start = '''<?xml version="1.0" encoding="UTF-8"?> 
<snapDoc>''' 

def main(): 
    print start 
    context = cElementTree.iterparse('snap.xml', events=("start", "end")) 
    context = iter(context) 
    event, root = context.next() # get the root element of the XML doc 

    for event, elem in context: 
     if event == "end": 
      if elem.tag == 'bucket': # i want to write out all <bucket> entries 
       elem.tail = None 
       print cElementTree.tostring(elem) 
      if elem.tag == 'resFrame': 
       if elem.find("id").text == ":4:39644:482:-1:1": # i only want to write out resFrame entries with this id 
        elem.tail = None 
        print cElementTree.tostring(elem) 
      if elem.tag in ['bucket', 'frame', 'resFrame']: 
       root.clear() # when done parsing a section clear the tree to safe memory 
    print "</snapDoc>" 

main() 
0

Dies ist ein alter, aber sehr guter Artikel von Uche Ogbuji ist auch sehr gut Python & XML-Spalte. Er deckt Ihre genaue Frage ab und verwendet das Standard-Sax-Modul, wie es die andere Antwort vorgeschlagen hat. Decomposition, Process, Recomposition

Verwandte Themen