Python: iterativní parsování XML

Tento článek je pouze krátkým rozšířením předchozího článku o parsování XML dumpu Wikipedie. Ukáži kousek kódu, který umožní iterativní načítání XML za použití modulu ElementTree, který je nyní již standardní součástí Pythonu.

Proč iterativní parsování?

Třeba proto, že přestože máte hodně paměti, stále je konečná. Například v předchozím článku zmíněná hranice 20GB na XML dump je postačující, pokud komprimovaný dump má velikost kolem stovek MB, nicméně tento dump v anglické Wikipedii má 2.7GB zabaleného XML. A to už v běžné paměti neuchováme naráz. Proto je potřeba XML parsovat iterativně. Nicméně, aby nebylo třeba úplně měnit kód z předchozího článku, použijeme opět ElementTree a funkci iterparse().

Jak na to

Funkce iterparse() je zajímavý hybrid mezi SAXem a stromově orientovaným ElementTree. Prakticky dokáže reportovat, že začal vytvářet podstrom XML stromu patřící nějakému elementu a že tuto práci skončil. iterparse() vrátí generátor, který postupně vrací páry událost, element. Vrácené elementy je důležité zpracovávat vždy až s událostí end, kdy je podstrom XML dokumentu již kompletně vytvořen (což při startu být nemusí).

XML strom lze přitom během parsování modifikovat, takže již zpracované elementy lze ze stromu odstranit a tím zásadně ušetříme paměť (viz řádek elem.clear(), který vymaže celý podstrom a v tomto případě ponechá pouze prázdný element page).

A nyní již kód:

def parse_dump(xml_fn):
    with bz2.BZ2File(xml_fn, 'r') as fr:
        for event, elem in ET.iterparse(fr):
            if event == 'end' and elem.tag == '{0}page'.format(MW_NS):
                text = elem.find('{0}revision/{0}text'.format(MW_NS))
    
                title = elem.find('{0}title'.format(MW_NS)).text

                yield title, text.text
                elem.clear()

Rozhraní se oproti předchozí verzi parse_dump() nezměnilo, je vidět, že po vytvoření podstromu lze používat i dotazy metodou find(). Dále kromě události end, lze využít i další jako start, start-ns a end-ns.

Výše uvedený kód využívá určité apriorní znalosti o struktuře výsledného XML, pokud by však v XML byly rekurzivně zanořené elementy page, pak by již nutné bylo pomocí událostí start a end držet cestu (zanoření elementů) pro každý aktuálně zpracovávaný element.

Závěr

Ukázaný kód by měl sloužit ne jako vodítko, jak velké XML soubory zpracovávat, ale jako určité počáteční nakopnutí tím správným směrem. Při potřebě nějakého komplexnějšího chování jistě najdete více na webu a fórech.

Napsat komentář