Ga naar hoofdinhoud

Python XML-tutorial met ElementTree: gids voor beginners

Leer hoe je XML-bestanden kunt parsen, verkennen, aanpassen en vullen met het Python-pakket ElementTree, for-loops en XPath-expressies.
Bijgewerkt 2 jun 2026  · 10 min lezen

Voer de code uit deze tutorial online uit en pas 'm aan.

Code uitvoeren

Als data scientist merk je al snel dat inzicht in XML krachtig is voor zowel webscraping als het parsen van gestructureerde documenten in het algemeen.

  • Je leert meer over XML en maakt kennis met het Python-pakket ElementTree.
  • Daarna ontdek je hoe je XML-bomen kunt verkennen om je data beter te begrijpen met behulp van ElementTree-functies, for-loops en XPath-expressies.
  • Vervolgens leer je hoe je een XML-bestand kunt aanpassen.
  • Je gebruikt ook xpath-expressies om XML-bestanden te vullen.

Wat is XML?

XML staat voor "Extensible Markup Language". Het wordt vooral gebruikt op webpagina's, waar data een specifieke structuur heeft en dynamisch wordt begrepen door het XML-framework.

XML creëert een boomstructuur die makkelijk te interpreteren is en hiërarchie ondersteunt. Wanneer een pagina XML volgt, kun je die een XML-document noemen.

  • XML-documenten hebben secties genaamd elementen, die worden gedefinieerd door een begin- en een eind-tag. Een tag is een markup-constructie die begint met < en eindigt met >. De tekens tussen de start- en eindtag, als die er zijn, vormen de inhoud van het element. Elementen kunnen ook markup bevatten, waaronder andere elementen, die "child elements" (kinderen) worden genoemd.
  • Het grootste element op het hoogste niveau heet de root en bevat alle andere elementen.
  • Attributen zijn naam–waardeparen die bestaan binnen een starttag of een lege-element-tag. Een XML-attribuut kan slechts één waarde hebben en elk attribuut mag per element hoogstens één keer voorkomen.

Om dit wat beter te begrijpen, bekijk het volgende (ingekorte) XML-bestand:

<?xml version="1.0"?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back 2 the Future">
               <format multiple="False">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    </genre>

    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="Yes">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

Uit wat je hierboven hebt gelezen, zie je dat

  • <collection> het enige root-element is: het bevat alle andere elementen, zoals <genre> of <movie>, die de kindelementen of subelementen zijn. Zoals je ziet, zijn deze elementen genest.

Let op dat deze kindelementen ook als ouder kunnen fungeren en hun eigen kindelementen kunnen bevatten, die dan "sub-kindelementen" worden genoemd.

  • Je ziet bijvoorbeeld dat het element <movie> een aantal "attributen" bevat, zoals favorite title die nog meer informatie geven!

Met deze korte intro tot XML-bestanden ben je klaar om meer te leren over ElementTree!

Introductie tot ElementTree

De XML-boomstructuur maakt navigeren, aanpassen en verwijderen programmatisch relatief eenvoudig. Python heeft een ingebouwde bibliotheek, ElementTree, met functies om XML's (en andere vergelijkbaar gestructureerde bestanden) te lezen en te manipuleren.

Importeer eerst ElementTree. Het is gebruikelijk om de alias ET te gebruiken:

import xml.etree.ElementTree as ET

XML-gegevens parsen

Het meegeleverde XML-bestand beschrijft een eenvoudige collectie films. Het enige probleem is dat de data een rommeltje is! Er zijn veel verschillende beheerders van deze collectie geweest en iedereen heeft zo z'n eigen manier om data in te voeren. Het hoofddoel in deze tutorial is om het bestand te lezen en te begrijpen met Python en vervolgens de problemen op te lossen.

Eerst moet je het bestand lezen met ElementTree.

tree = ET.parse('movies.xml')
root = tree.getroot()

Nu je de boom hebt geïnitialiseerd, moet je naar de XML kijken en waarden afdrukken om te begrijpen hoe de boom is opgebouwd.

Elk onderdeel van een boom (inclusief de root) heeft een tag die het element beschrijft. Bovendien kunnen elementen, zoals je in de introductie hebt gezien, attributen hebben: extra beschrijvingen die vooral worden gebruikt bij herhaald gebruik van tags. Attributen helpen ook om waarden voor die tag te valideren en dragen zo bij aan het gestructureerde formaat van een XML.

Je zult later in deze tutorial zien dat attributen behoorlijk krachtig kunnen zijn wanneer ze in een XML zijn opgenomen!

root.tag
'collection'

Op het hoogste niveau zie je dat deze XML is geworteld in de tag collection.

root.attrib
{}

De root heeft dus geen attributen.

For-loops

Je kunt eenvoudig itereren over subelementen (vaak "children" genoemd) in de root met een simpele for-loop.

for child in root:
    print(child.tag, child.attrib)
genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}

Nu weet je dat de children van de root collection allemaal genre zijn. Om het genre aan te duiden, gebruikt de XML het attribuut category. Er zijn volgens het element genre films in de categorieën Action, Thriller en Comedy.

Het is vaak handig om alle elementen in de hele boom te kennen. Een nuttige functie hiervoor is root.iter(). Je kunt deze functie in een for-loop zetten en die zal over de hele boom itereren.

[elem.tag for elem in root.iter()]
['collection',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description']

Dit geeft een algemeen beeld van hoeveel elementen je hebt, maar laat geen attributen of niveaus in de boom zien.

Er is een handige manier om het hele document te zien. Elk element heeft een methode .tostring(). Als je de root doorgeeft aan de methode .tostring(), kun je het hele document terugkrijgen. Binnen ElementTree (onthoud de alias ET) neemt .tostring() een iets vreemde vorm aan.

Omdat ElementTree een krachtige bibliotheek is die meer kan interpreteren dan alleen XML, moet je zowel de codering als de decodering van het document dat je als string weergeeft, specificeren. Voor XML's gebruik je 'utf8' - dit is het gebruikelijke documentformaat voor een XML.

print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back 2 the Future">
               <format multiple="False">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    </genre>

    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="Yes">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

    <genre category="Comedy">
        <decade years="1960s">
            <movie favorite="False" title="Batman: The Movie">
                <format multiple="Yes">DVD,VHS</format>
                <year>1966</year>
                <rating>PG</rating>
                <description>What a joke!</description>
            </movie>
        </decade>
        <decade years="2010s">
            <movie favorite="True" title="Easy A">
                <format multiple="No">DVD</format>
                <year>2010</year>
                <rating>PG--13</rating>
                <description>Emma Stone = Hester Prynne</description>
            </movie>
            <movie favorite="True" title="Dinner for SCHMUCKS">
                <format multiple="Yes">DVD,digital,Netflix</format>
                <year>2011</year>
                <rating>Unrated</rating>
                <description>Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.
                 </description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="False" title="Ghostbusters">
                <format multiple="No">Online,VHS</format>
                <year>1984</year>
                <rating>PG</rating>
                <description>Who ya gonna call?</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Robin Hood: Prince of Thieves">
                <format multiple="No">Blu_Ray</format>
                <year>1991</year>
                <rating>Unknown</rating>
                <description>Robin Hood slaying</description>
            </movie>
        </decade>
    </genre>
</collection>

Je kunt het gebruik van de functie iter() uitbreiden om specifieke elementen van belang te vinden. root.iter() zal alle subelementen onder de root opsommen die overeenkomen met het opgegeven element. Hier som je alle attributen van het element movie in de boom op:

for movie in root.iter('movie'):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

Je ziet nu al hoe de movies op verschillende manieren zijn ingevoerd. Maak je daar nu nog geen zorgen over. Later in deze tutorial krijg je de kans om een van de fouten te herstellen.

XPath-expressies

Vaak hebben elementen geen attributen en alleen tekstinhoud. Met het attribuut .text kun je deze inhoud afdrukken.

Druk nu alle beschrijvingen van de films af.

for description in root.iter('description'):
    print(description.text)
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'

None provided.
Marty McFly
Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.
NA.
WhAtEvER I Want!!!?!
"""""""""
Funny movie about a funny guy
psychopathic Bateman
What a joke!
Emma Stone = Hester Prynne
Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.

Who ya gonna call?
Robin Hood slaying

Het afdrukken van de XML is handig, maar XPath is een querytaal die wordt gebruikt om snel en gemakkelijk door een XML te zoeken. XPath staat voor XML Path Language en gebruikt, zoals de naam al suggereert, een "pad-achtige" syntaxis om knooppunten in een XML-document te identificeren en te navigeren.

Inzicht in XPath is cruciaal voor het scannen en vullen van XML's. ElementTree heeft een functie .findall() die de directe children van het genoemde element doorloopt. Je kunt XPath-expressies gebruiken om nuttigere zoekopdrachten te specificeren.

Hier zoek je in de boom naar films die in 1992 uitkwamen:

for movie in root.findall("./genre/decade/movie/[year='1992']"):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}

De functie .findall() begint altijd bij het opgegeven element. Dit soort functie is extreem krachtig voor een "zoeken en vervangen". Je kunt zelfs op attributen zoeken!

Druk nu alleen de films af die in meerdere formaten beschikbaar zijn (een attribuut).

for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
    print(movie.attrib)
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}

Bedenk waarom in dit geval de print-instructie de "Yes"-waarden van multiple retourneert. Denk na over hoe de for-loop is gedefinieerd. Kun je deze loop herschrijven om in plaats daarvan de filmtitels af te drukken? Probeer het hieronder:

Tip: gebruik '...' binnen XPath om het ouder-element van het huidige element te retourneren.

for movie in root.findall("./genre/decade/movie/format[@multiple='Yes']..."):
    print(movie.attrib)
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}

Een XML aanpassen

Eerder waren de filmtitels een complete chaos. Druk ze nu opnieuw af:

for movie in root.iter('movie'):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

Repareer de '2' in Back 2 the Future. Dat is een zoek-en-vervang-probleem. Schrijf code om de titel 'Back 2 the Future' te vinden en sla die op als variabele:

b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)
<Element 'movie' at 0x10ce00ef8>

Merk op dat het gebruik van de methode .find() een element van de boom retourneert. Vaak is het nuttiger om de inhoud binnen een element te bewerken.

Wijzig het attribuut title van de Back 2 the Future-variabele zodat er "Back to the Future" staat. Druk vervolgens de attributen van je variabele af om je wijziging te zien. Je kunt dit eenvoudig doen door het attribuut van een element te benaderen en er dan een nieuwe waarde aan toe te wijzen:

b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)
{'favorite': 'False', 'title': 'Back to the Future'}

Schrijf je wijzigingen terug naar de XML zodat ze permanent in het document zijn vastgelegd. Druk je filmattributen opnieuw af om te controleren of je wijzigingen zijn doorgevoerd. Gebruik hiervoor de methode .write():

tree.write("movies.xml")

tree = ET.parse('movies.xml')
root = tree.getroot()

for movie in root.iter('movie'):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back to the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

Attributen repareren

Het attribuut multiple is op sommige plaatsen onjuist. Gebruik ElementTree om de aanduiding te corrigeren op basis van het aantal formaten waarin de film beschikbaar is. Druk eerst het attribuut en de tekst van format af om te zien welke onderdelen moeten worden gerepareerd.

for form in root.findall("./genre/decade/movie/format"):
    print(form.attrib, form.text)
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'False'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'Yes'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'No'} Online,VHS
{'multiple': 'No'} Blu_Ray

Er is wat werk nodig aan deze tag.

Je kunt regex gebruiken om komma's te vinden - dat geeft aan of het attribuut multiple "Yes" of "No" moet zijn. Attributen toevoegen en wijzigen kan eenvoudig met de methode .set().

Let op: re is de standaard regex-interpreter voor Python. Als je meer wilt weten over reguliere expressies, bekijk dan deze tutorial.

import re

for form in root.findall("./genre/decade/movie/format"):
    # Search for the commas in the format text
    match = re.search(',',form.text)
    if match:
        form.set('multiple','Yes')
    else:
        form.set('multiple','No')

# Write out the tree to the file again
tree.write("movies.xml")

tree = ET.parse('movies.xml')
root = tree.getroot()

for form in root.findall("./genre/decade/movie/format"):
    print(form.attrib, form.text)
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'No'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'No'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'Yes'} Online,VHS
{'multiple': 'No'} Blu_Ray

Elementen verplaatsen

Sommige data is in de verkeerde decade geplaatst. Gebruik wat je hebt geleerd over XML en ElementTree om de fouten in de decadedata te vinden en te corrigeren.

Het is handig om zowel de tags decade als de tags year in het hele document af te drukken.

for decade in root.findall("./genre/decade"):
    print(decade.attrib)
    for year in decade.findall("./movie/year"):
        print(year.text, '\n')
{'years': '1980s'}
1981 

1984 

1985 

{'years': '1990s'}
2000 

1992 

1992 

{'years': '1970s'}
1979 

{'years': '1980s'}
1986 

2000 

{'years': '1960s'}
1966 

{'years': '2010s'}
2010 

2011 

{'years': '1980s'}
1984 

{'years': '1990s'}
1991 

De twee jaren die in de verkeerde decade staan, zijn de films uit de jaren 2000. Bepaal welke films dat zijn met een XPath-expressie.

for movie in root.findall("./genre/decade/movie/[year='2000']"):
    print(movie.attrib)
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}

Je moet een nieuwe decade-tag, de jaren 2000, toevoegen aan het genre Action om de X-Men-data te verplaatsen. De methode .SubElement() kan worden gebruikt om deze tag aan het einde van de XML toe te voegen.

action = root.find("./genre[@category='Action']")
new_dec = ET.SubElement(action, 'decade')
new_dec.attrib["years"] = '2000s'

print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back to the Future">
               <format multiple="No">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    <decade years="2000s" /></genre>

Voeg nu de X-Men-film toe aan de jaren 2000 en verwijder die uit de jaren 1990, met respectievelijk .append() en .remove().

xmen = root.find("./genre/decade/movie[@title='X-Men']")
dec2000s = root.find("./genre[@category='Action']/decade[@years='2000s']")
dec2000s.append(xmen)
dec1990s = root.find("./genre[@category='Action']/decade[@years='1990s']")
dec1990s.remove(xmen)

print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back to the Future">
               <format multiple="No">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    <decade years="2000s"><movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            </decade></genre>

XML-documenten opbouwen

Mooi, je hebt in feite een hele film naar een nieuwe decade kunnen verplaatsen. Sla je wijzigingen terug op in de XML.

tree.write("movies.xml")

tree = ET.parse('movies.xml')
root = tree.getroot()

print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back to the Future">
               <format multiple="No">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    <decade years="2000s"><movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            </decade></genre>

    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="No">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

    <genre category="Comedy">
        <decade years="1960s">
            <movie favorite="False" title="Batman: The Movie">
                <format multiple="Yes">DVD,VHS</format>
                <year>1966</year>
                <rating>PG</rating>
                <description>What a joke!</description>
            </movie>
        </decade>
        <decade years="2010s">
            <movie favorite="True" title="Easy A">
                <format multiple="No">DVD</format>
                <year>2010</year>
                <rating>PG--13</rating>
                <description>Emma Stone = Hester Prynne</description>
            </movie>
            <movie favorite="True" title="Dinner for SCHMUCKS">
                <format multiple="Yes">DVD,digital,Netflix</format>
                <year>2011</year>
                <rating>Unrated</rating>
                <description>Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.
                 </description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="False" title="Ghostbusters">
                <format multiple="Yes">Online,VHS</format>
                <year>1984</year>
                <rating>PG</rating>
                <description>Who ya gonna call?</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Robin Hood: Prince of Thieves">
                <format multiple="No">Blu_Ray</format>
                <year>1991</year>
                <rating>Unknown</rating>
                <description>Robin Hood slaying</description>
            </movie>
        </decade>
    </genre>
</collection>

Wat is er nieuw in ElementTree?

Hier is een overzicht van nieuwe features en verbeteringen aan de ElementTree-bibliotheek in nieuwere Python-versies:

1. XPath 1.0-ondersteuning (Python 3.8): Sinds Python 3.8 bevat ElementTree volledige XPath 1.0-ondersteuning met de methoden find() en findall(), waardoor rijkere en complexere XML-queries mogelijk zijn. Voorbeeld:

# Finding all movies with a specific attribute using XPath
for movie in root.findall(".//movie[@favorite='True']"):
    print(movie.attrib)

2. Verbeteringen aan namespaces (Python 3.8+): Verbeterde ondersteuning voor XML-namespaces, waardoor interactie met XML-bestanden met voorvoegsels of standaard-namespaces eenvoudiger wordt. Voorbeeld:

# Register a namespace and find elements using it
ET.register_namespace('', 'http://example.com/namespace')
movies = root.findall(".//{http://example.com/namespace}movie")

3. Parser-verbeteringen (Python 3.9): Beter leesbare parsefoutmeldingen maken het eenvoudiger om malformeerde XML-bestanden te debuggen.

4. Nieuwe functie indent() (Python 3.9): De functie xml.etree.ElementTree.indent() is toegevoegd om XML-documenten netjes op te maken door elementen in te laten springen. Voorbeeld:

ET.indent(root, space="  ", level=0)
ET.dump(root)

5. Efficiënt parsen met iterparse (Python 3.10): Geoptimaliseerd voor geheugenefficiëntie, vooral handig bij het werken met grote XML-bestanden.

6. Uitgebreide documentatie (Doorlopende updates): De Python-documentatie voor ElementTree is nu completer, inclusief best practices en geavanceerde use-cases.

Verouderde features in ElementTree en alternatieven

1. write() met xml_declaration in Python 3.8+: De parameter xml_declaration van de methode write() is verouderd wanneer de encoding is ingesteld op 'unicode'.

  • Alternatief: Gebruik xml_declaration alleen wanneer de encoding expliciet is gedefinieerd als iets anders dan 'unicode'.
tree.write("output.xml", encoding="utf-8", xml_declaration=True)

2. html-parser: Hoewel niet officieel verouderd, wordt het gebruik van ElementTree voor HTML-parsing afgeraden omdat het beperkt is in het verwerken van niet-well-formed HTML.

  • Alternatief: Gebruik libraries die specifiek zijn ontworpen voor HTML-parsing, zoals BeautifulSoup uit het pakket bs4.
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser')

3. Workarounds voor namespace-afhandeling: Oudere methoden om namespaces handmatig af te handelen (bijv. namespace-URI's met elementtags concatenëren) worden minder aanbevolen sinds de introductie van robuuste namespace-ondersteuning in nieuwere versies.

  • Alternatief: Gebruik de ingebouwde, namespace-bewuste methoden en functies.
ET.register_namespace('', 'http://example.com/namespace') movies = root.findall(".//{http://example.com/namespace}movie")

4. Handmatig netjes opmaken: Handmatige technieken voor inspringen en formatteren van XML zijn overbodig geworden door de nieuwe functie indent() (Python 3.9).

  • Alternatief: Gebruik ET.indent() voor automatische XML-opmaak.
ET.indent(root, space=" ")

5. Direct gebruik van _ElementInterface: Interne klassen zoals _ElementInterface zijn niet bedoeld voor direct gebruik en kunnen in toekomstige versies stukgaan.

  • Alternatief: Werk altijd met de gedocumenteerde publieke API van de ElementTree-bibliotheek.

Conclusie

Er zijn een paar kernpunten om te onthouden over XML's en het gebruik van ElementTree.

Tags bouwen de boomstructuur op en geven aan welke waarden daar moeten worden vastgelegd. Slimme structurering kan het lezen en schrijven van een XML eenvoudig maken. Tags hebben altijd openings- en sluittags nodig om de ouder-kindrelaties aan te geven.

Attributen beschrijven verder hoe je een tag valideert of maken booleaanse aanduidingen mogelijk. Attributen nemen doorgaans zeer specifieke waarden aan, zodat de XML-parser (en de gebruiker) de attributen kan gebruiken om de tagwaarden te controleren.

ElementTree is een belangrijke Python-bibliotheek waarmee je een XML-document kunt parsen en navigeren. Met ElementTree wordt het XML-document opgedeeld in een boomstructuur die gemakkelijk mee te werken is. Twijfel je, print het dan uit (print(ET.tostring(root, encoding='utf8').decode('utf8'))) - gebruik deze handige printinstructie om het hele XML-document in één keer te bekijken. Dat helpt bij het controleren tijdens het bewerken, toevoegen of verwijderen in een XML.

Nu ben je uitgerust om XML te begrijpen en te beginnen met parsen!


Steph Howson's photo
Author
Steph Howson

FAQs

Wat zijn veelvoorkomende use-cases voor het gebruik van XML in data science?

XML wordt in data science vaak gebruikt voor gegevensuitwisseling tussen systemen, webscraping, configuratiebestanden en het verwerken van data met een complexe, hiërarchische structuur. Het is vooral nuttig bij het werken met API's die XML-data teruggeven.

Kan ElementTree grote XML-bestanden efficiënt verwerken?

ElementTree is geschikt voor het verwerken van middelgrote XML-bestanden, maar voor zeer grote bestanden kun je overwegen om libraries te gebruiken zoals lxml of xml.sax die geheugen-efficiënter zijn en streaming van grote bestanden aankunnen.

Hoe verhoudt ElementTree zich tot andere XML-parsingbibliotheken zoals lxml of minidom?

ElementTree maakt deel uit van de standaardbibliotheek van Python en is eenvoudig te gebruiken voor basis-XML-parsingtaken. lxml is krachtiger en sneller, met extra features zoals XPath 2.0-ondersteuning. minidom, een andere standaardbibliotheek, is gebaseerd op het Document Object Model (DOM) en minder efficiënt voor grote documenten.

Wat zijn XPath-expressies en hoe zijn ze nuttig bij XML-parsing?

XPath-expressies zijn querytalen voor het selecteren van knooppunten uit een XML-document. Ze zijn nuttig voor het navigeren door elementen en attributen in XML-documenten en maken nauwkeurige gegevensopvraging en -manipulatie mogelijk.

Hoe kan ik een XML-document valideren voordat ik het met ElementTree parse?

XML-documenten kunnen worden gevalideerd met een XML Schema Definition (XSD) of een Document Type Definition (DTD). Python-bibliotheken zoals lxml bieden ingebouwde ondersteuning voor validatie tegen deze standaarden.

Wat zijn best practices voor het wijzigen van XML-data met ElementTree?

Best practices zijn onder meer werken op een kopie van de XML-data om accidenteel dataverlies te voorkomen, XPath-expressies gebruiken voor nauwkeurige navigatie en ervoor zorgen dat alle wijzigingen de well-formedness van het XML-document behouden.

Kan ElementTree worden gebruikt om XML-data naar JSON te converteren?

ElementTree biedt zelf geen directe XML-naar-JSON-conversie, maar je kunt de XML-data met ElementTree parsen naar een Python-dictionary en die vervolgens met Pythons json module naar JSON converteren.

Hoe ga je om met XML-namespaces met ElementTree?

ElementTree kan XML-namespaces afhandelen met het {namespace} prefix in tagnamen. Je kunt ook namespaces registreren met ET.register_namespace() voor eenvoudiger omgaan met XML met namespaces.

Wat moet ik doen als ik een XML-parsefout tegenkom in ElementTree?

Controleer op veelvoorkomende problemen zoals malformeerde XML, niet-ondersteunde encodings of onjuiste bestandspaden. Gebruik de foutafhandeling van Python (try-except blokken) om parsefouten netjes te diagnosticeren en af te handelen.

Is het mogelijk om een XML-document netjes op te maken (pretty-print) met ElementTree?

ElementTree ondersteunt geen pretty-printing direct, maar je kunt xml.dom.minidom gebruiken om de XML-string te parsen en vervolgens de methode toprettyxml() te gebruiken om de XML leesbaar te formatteren.

Onderwerpen

Leer meer over Python

Cursus

Introductie tot Python

4 Hr
6.9M
Leer de basis van data-analyse met Python in 4 uur. Deze online cursus laat je kennismaken met de Python-interface en populaire pakketten.
Bekijk detailsRight Arrow
Begin met de cursus
Meer zienRight Arrow
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer zienMeer zien