Direkt zum Inhalt
HeimAnleitungenPython

Python XML Tutorial mit ElementTree: Leitfaden für Anfänger

Lerne, wie du XML-Dateien mit dem Python-Paket ElementTree, for-Schleifen und XPath-Ausdrücken parsen, untersuchen, verändern und auffüllen kannst.
Aktualisierte 11. Sept. 2024  · 19 Min. lesen

Führe den Code aus diesem Tutorial online aus und bearbeite ihn

Code ausführen

Als Datenwissenschaftler/in wirst du feststellen, dass das Verständnis von XML sowohl für das Web-Scraping als auch für die allgemeine Praxis des Parsens eines strukturierten Dokuments sehr nützlich ist.

Meistere deine Datenkenntnisse mit DataCamp

Erlerne die Fähigkeiten, die du brauchst, in deinem eigenen Tempo - von den Grundlagen der Nicht-Programmierung bis hin zu Data Science und maschinellem Lernen.

Was ist XML?

XML steht für "Extensible Markup Language". Es wird hauptsächlich in Webseiten verwendet, wo die Daten eine bestimmte Struktur haben und vom XML-Framework dynamisch verstanden werden.

XML erzeugt eine baumartige Struktur, die leicht zu interpretieren ist und eine Hierarchie unterstützt. Wann immer eine Seite XML folgt, kann sie als XML-Dokument bezeichnet werden.

  • XML-Dokumente haben Abschnitte, die Elemente genannt werden und durch ein Anfangs- und ein End-Tag definiert sind. Ein Tag ist ein Markup-Konstrukt, das mit < beginnt und mit > endet. Die Zeichen zwischen dem Start-Tag und dem End-Tag, sofern vorhanden, sind der Inhalt des Elements. Elemente können Markup enthalten, darunter auch andere Elemente, die als "Kindelemente" bezeichnet werden.
  • Das größte, oberste Element wird als Wurzel bezeichnet, die alle anderen Elemente enthält.
  • Attribute sind Name-Wert-Paare, die sich innerhalb eines Start-Tags oder eines Leerelement-Tags befinden. Ein XML-Attribut kann nur einen einzigen Wert haben und jedes Attribut kann in jedem Element höchstens einmal vorkommen.

Um dies etwas besser zu verstehen, schau dir die folgende (gekürzte) XML-Datei an:

<?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>

Aus dem, was du oben gelesen hast, kannst du erkennen, dass

  • ist das einzige Wurzelelement: Es enthält alle anderen Elemente, wie oder , die die untergeordneten Elemente oder Unterelemente sind. Wie du sehen kannst, sind diese Elemente verschachtelt.

Beachte, dass diese untergeordneten Elemente auch als Eltern fungieren und ihre eigenen untergeordneten Elemente enthalten können, die dann "untergeordnete Elemente" genannt werden.

  • Du wirst sehen, dass zum Beispiel das Element eine Reihe von "Attributen" enthält, wie favorite title, die noch mehr Informationen liefern!

Mit dieser kurzen Einführung in XML-Dateien im Kopf bist du bereit, mehr über ElementTree zu erfahren!

Einführung in ElementTree

Die XML-Baumstruktur macht das Navigieren, Ändern und Entfernen programmtechnisch relativ einfach. Python hat eine eingebaute Bibliothek, ElementTree, die Funktionen zum Lesen und Verarbeiten von XML-Dateien (und anderen ähnlich strukturierten Dateien) enthält.

Importiere zunächst ElementTree. Es ist eine gängige Praxis, den Alias ET zu verwenden:

import xml.etree.ElementTree as ET

Parsen von XML-Daten

In der mitgelieferten XML-Datei ist eine grundlegende Sammlung von Filmen beschrieben. Das einzige Problem ist, dass die Daten ein Chaos sind! Es gab viele verschiedene Kuratoren für diese Sammlung und jeder hat seine eigene Art, Daten in die Datei einzugeben. Das Hauptziel in diesem Lernprogramm ist es, die Datei mit Python zu lesen und zu verstehen - und dann die Probleme zu beheben.

Zuerst musst du die Datei mit ElementTree einlesen.

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

Jetzt, wo du den Baum initialisiert hast, solltest du dir das XML ansehen und Werte ausdrucken, um zu verstehen, wie der Baum strukturiert ist.

Jeder Teil eines Baums (einschließlich der Wurzel) hat ein Tag, das das Element beschreibt. Wie du in der Einführung gesehen hast, können Elemente außerdem Attribute haben, die zusätzliche Beschreibungen sind, die vor allem für die wiederholte Verwendung von Tags verwendet werden. Attribute helfen auch bei der Validierung von Werten, die für dieses Tag eingegeben werden, was wiederum zum strukturierten Format einer XML-Datei beiträgt.

Du wirst später in diesem Tutorial sehen, dass Attribute ziemlich mächtig sein können, wenn sie in einer XML-Datei enthalten sind!

root.tag
'collection'

Auf der obersten Ebene siehst du, dass diese XML im collection Tag verwurzelt ist.

root.attrib
{}

Die Wurzel hat also keine Attribute.

For-Schleifen

Mit einer einfachen "for"-Schleife kannst du ganz einfach über die Unterelemente (auch "Kinder" genannt) in der Wurzel iterieren.

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

Jetzt weißt du, dass die Kinder der Wurzel collection alle genre sind. Um das Genre zu bezeichnen, verwendet die XML das Attribut category. Es gibt Action-, Thriller- und Komödienfilme nach dem genre Element.

Normalerweise ist es hilfreich, alle Elemente im gesamten Baum zu kennen. Eine nützliche Funktion dafür ist root.iter(). Du kannst diese Funktion in eine "for"-Schleife einbauen und sie durchläuft den gesamten Baum.

[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']

Dies gibt eine allgemeine Vorstellung davon, wie viele Elemente du hast, aber es zeigt nicht die Attribute oder Ebenen im Baum.

Es gibt eine hilfreiche Möglichkeit, das ganze Dokument zu sehen. Jedes Element hat eine .tostring() Methode. Wenn du die Wurzel an die Methode .tostring() übergibst, kannst du das gesamte Dokument zurückgeben. Innerhalb von ElementTree (wir erinnern uns: ET) nimmt .tostring() eine etwas seltsame Form an.

Da ElementTree eine leistungsstarke Bibliothek ist, die mehr als nur XML interpretieren kann, musst du sowohl die Kodierung als auch die Dekodierung des Dokuments angeben, das du als String anzeigst. Für XMLs verwendest du 'utf8' - das ist der typische Dokumentenformattyp für ein 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>

Du kannst die Funktion iter() erweitern, um bestimmte Elemente von Interesse zu finden. root.iter() listet alle Unterelemente unter der Wurzel auf, die dem angegebenen Element entsprechen. Hier listest du alle Attribute des Elements movie im Baum auf:

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'}

Du kannst bereits sehen, wie die movies auf unterschiedliche Weise eingegeben wurden. Mach dir darüber vorerst keine Sorgen, du wirst später in diesem Tutorial die Gelegenheit bekommen, einen der Fehler zu beheben.

XPath-Ausdrücke

Oft haben Elemente keine Attribute, sondern nur einen Textinhalt. Mit dem Attribut .text kannst du diesen Inhalt ausdrucken.

Drucke nun alle Beschreibungen der Filme aus.

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

Das Ausdrucken der XML-Datei ist hilfreich, aber XPath ist eine Abfragesprache, mit der man schnell und einfach eine XML-Datei durchsuchen kann. XPath steht für XML Path Language und verwendet, wie der Name schon sagt, eine "pfadähnliche" Syntax, um Knoten in einem XML-Dokument zu identifizieren und zu navigieren.

Das Verständnis von XPath ist für das Scannen und Auffüllen von XMLs von entscheidender Bedeutung. ElementTree hat eine .findall() Funktion, die die unmittelbaren Kinder des referenzierten Elements durchläuft. Du kannst XPath-Ausdrücke verwenden, um nützlichere Suchen zu definieren.

Hier durchsuchst du den Baum nach Filmen, die im Jahr 1992 herauskamen:

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

Die Funktion .findall() beginnt immer bei dem angegebenen Element. Diese Art von Funktion ist extrem leistungsstark für das "Suchen und Ersetzen". Du kannst sogar nach Attributen suchen!

Jetzt druckst du nur die Filme aus, die in mehreren Formaten verfügbar sind (ein Attribut).

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

Überlege dir, warum die Druckanweisung in diesem Fall die "Ja"-Werte von multiple zurückgibt. Denke darüber nach, wie die "for"-Schleife definiert ist. Könntest du diese Schleife so umschreiben, dass sie stattdessen die Filmtitel ausgibt? Probiere es unten aus:

Tipp: Verwende '...' innerhalb von XPath, um das übergeordnete Element des aktuellen Elements zurückzugeben.

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'}

Ändern einer XML-Datei

Früher waren die Filmtitel ein absolutes Chaos. Drucke sie jetzt noch einmal aus:

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'}

Repariere die "2" in Zurück in die Zukunft. Das sollte ein Problem beim Suchen und Ersetzen sein. Schreibe einen Code, um den Titel "Back 2 the Future" zu finden und ihn als Variable zu speichern:

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

Beachte, dass die Methode .find() ein Element des Baums zurückgibt. Meistens ist es sinnvoller, den Inhalt eines Elements zu bearbeiten.

Ändere das title Attribut der Back 2 the Future Elementvariable so, dass es "Back to the Future" lautet. Drucke dann die Attribute deiner Variablen aus, um deine Änderung zu sehen. Das kannst du ganz einfach tun, indem du auf das Attribut eines Elements zugreifst und ihm dann einen neuen Wert zuweist:

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

Schreibe deine Änderungen in die XML-Datei zurück, damit sie dauerhaft im Dokument verankert sind. Drucke deine Filmattribute noch einmal aus, um sicherzustellen, dass deine Änderungen funktioniert haben. Verwende dazu die 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'}

Attribute fixieren

Das Attribut multiple ist an einigen Stellen falsch. Verwende ElementTree, um den Bezeichner festzulegen, je nachdem, in wie vielen Formaten der Film vorliegt. Drucke zunächst das Attribut format und den Text aus, um zu sehen, welche Teile korrigiert werden müssen.

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

Es gibt noch einiges zu tun an diesem Tag.

Du kannst Regex verwenden, um Kommas zu finden - das sagt dir, ob das multiple Attribut "Ja" oder "Nein" sein soll. Das Hinzufügen und Ändern von Attributen kann ganz einfach mit der Methode .set() erfolgen.

Hinweis: re ist der Standard-Regex-Interpreter für Python. Wenn du mehr über reguläre Ausdrücke wissen willst, schau dir dieses Tutorial an.

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

Bewegende Elemente

Einige der Daten wurden in das falsche Jahrzehnt eingeordnet. Nutze das, was du über XML und ElementTree gelernt hast, um die Fehler in den Dekadendaten zu finden und zu beheben.

Es ist sinnvoll, sowohl die decade Tags als auch die year Tags im Dokument auszudrucken.

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 

Die beiden Jahre, die im falschen Jahrzehnt liegen, sind die Filme aus den 2000er Jahren. Finde heraus, welche Filme das sind, indem du einen XPath-Ausdruck verwendest.

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

Du musst ein neues Jahrzehnt-Tag, die 2000er Jahre, zum Action-Genre hinzufügen, um die X-Men-Daten zu verschieben. Die Methode .SubElement() kann verwendet werden, um dieses Tag am Ende der XML-Datei hinzuzufügen.

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>

Füge nun den X-Men-Film zu den 2000er Jahren hinzu und entferne ihn aus den 1990er Jahren, indem du .append() bzw. .remove() benutzt.

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-Dokumente erstellen

Schön, du hast es also geschafft, einen ganzen Film in ein neues Jahrzehnt zu verschieben. Speichere deine Änderungen wieder in der XML-Datei.

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>

Fazit

Es gibt einige wichtige Dinge, die du über XML und die Verwendung von ElementTree wissen solltest.

Tags bilden die Baumstruktur und geben an, welche Werte dort beschrieben werden sollen. Eine intelligente Strukturierung kann das Lesen und Schreiben einer XML-Datei erleichtern. Tags brauchen immer öffnende und schließende Klammern, um die Beziehungen zwischen Eltern und Kindern zu zeigen.

Attribute beschreiben außerdem, wie ein Tag validiert werden kann oder ermöglichen boolesche Bezeichnungen. Attribute nehmen in der Regel ganz bestimmte Werte an, damit der XML-Parser (und der Benutzer) die Attribute zur Überprüfung der Tag-Werte verwenden kann.

ElementTree ist eine wichtige Python-Bibliothek, mit der du ein XML-Dokument parsen und navigieren kannst. Die Verwendung von ElementTree gliedert das XML-Dokument in eine Baumstruktur, mit der man leicht arbeiten kann. Im Zweifelsfall drucke es aus (print(ET.tostring(root, encoding='utf8').decode('utf8'))) - verwende diese hilfreiche Druckanweisung, um das gesamte XML-Dokument auf einmal zu sehen. Es hilft bei der Überprüfung, wenn du eine XML-Datei bearbeitest, hinzufügst oder entfernst.

Jetzt bist du in der Lage, XML zu verstehen und mit dem Parsen zu beginnen!

Referenzen:

Themen

Erfahre mehr über Python

Zertifizierung verfügbar

Course

Einführung in Python

4 hr
5.5M
Beherrsche die Grundlagen der Datenanalyse mit Python in nur vier Stunden. Dieser Online-Kurs führt in die Python-Schnittstelle ein und stellt beliebte Pakete vor.
See DetailsRight Arrow
Start Course
Mehr anzeigenRight Arrow