Direkt zum Inhalt

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

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

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 von strukturierten Dokumenten wichtig ist.

  • Du lernst mehr über XML und bekommst eine Einführung in das Python-Paket ElementTree.
  • Dann erfährst du, wie du XML-Bäume untersuchen kannst, um die Daten, mit denen du arbeitest, mit Hilfe von ElementTree Funktionen, for-Schleifen und XPath-Ausdrücken besser zu verstehen.
  • Als Nächstes lernst du, wie du eine XML-Datei ändern kannst.
  • Du wirst auch xpath-Ausdrücke verwenden, um XML-Dateien aufzufüllen.

Python von Grund auf lernen

Beherrsche Python für Data Science und erwerbe gefragte Fähigkeiten.

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 einen Anfangs- und einen Endtag 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

Die mitgelieferte XML-Datei beschreibt eine einfache Sammlung von Filmen. 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. In diesem Lernprogramm geht es vor allem darum, die Datei mit Python zu lesen und zu verstehen und dann die Probleme zu beheben.

Zuerst musst du die Datei mit ElementTree lesen.

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, also zusätzliche Beschreibungen, 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.

Für 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. Du musst sowohl die Kodierung als auch die Dekodierung des Dokuments angeben, das du als Zeichenfolge anzeigst. Verwende für XMLs 'utf8' - Das ist das typische Dokumentformat für 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 erst einmal keine Gedanken. Du wirst später in diesem Lernprogramm die Möglichkeit haben, 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 Attribut multiple "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 dem falschen Jahrzehnt zugeordnet. 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>

Was ist neu in ElementTree?

Hier findest du einen Überblick über neue Funktionen und Verbesserungen der ElementTree-Bibliothek in neueren Python-Versionen:

1. Unterstützung von XPath 1.0 (Python 3.8): Ab Python 3.8 bietet ElementTree mit den Methoden find() und findall() volle XPath 1.0-Unterstützung und ermöglicht so umfangreichere und komplexere XML-Abfragen. Beispiel:

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

2. Verbesserungen bei Namespaces (Python 3.8+): Verbesserte Unterstützung für XML-Namespaces, die eine einfachere Interaktion mit XML-Dateien ermöglicht, die vorangestellte oder Standard-Namespaces verwenden. Beispiel:

# 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-Verbesserungen (Python 3.9): Bessere Parsing-Fehlermeldungen erleichtern die Fehlersuche in fehlerhaften XML-Dateien.

4. Neue Funktion indent() (Python 3.9): Die Funktion xml.etree.ElementTree.indent() wurde hinzugefügt, um XML-Dokumente durch Einrücken ihrer Elemente hübsch auszudrucken. Beispiel:

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

5. Effizientes Parsing mit iterparse (Python 3.10): Optimiert für Speichereffizienz, besonders nützlich bei der Arbeit mit großen XML-Dateien.

6. Erweiterte Dokumentation (Laufende Aktualisierungen): Die Python-Dokumentation für ElementTree ist jetzt umfassender und enthält Best Practices und erweiterte Anwendungsfälle.

Veraltete Funktionen in ElementTree und Alternativen

1. write() mit xml_declaration in Python 3.8+: Der Parameter xml_declaration der Methode write() ist veraltet, wenn die Kodierung auf 'unicode' eingestellt ist.

  • Alternative: Verwenden Sie xml_declaration nur, wenn die Kodierung ausdrücklich als etwas anderes als 'unicode' definiert ist.
tree.write("output.xml", encoding="utf-8", xml_declaration=True)

2. html parser: Obwohl es nicht offiziell veraltet ist, wird von der Verwendung von ElementTree für das Parsen von HTML abgeraten, da es nur begrenzt in der Lage ist, nicht wohlgeformtes HTML zu verarbeiten.

  • Alternative: Verwende Bibliotheken, die speziell für das Parsen von HTML entwickelt wurden, wie z.B. BeautifulSoup aus dem Paket bs4.
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser')

3. Workarounds für die Handhabung von Namensräumen: Ältere Methoden zur manuellen Handhabung von Namespaces (z. B. die Verkettung von Namespace-URIs mit Element-Tags) werden mit der Einführung der robusten Namespace-Unterstützung in neueren Versionen weniger empfohlen.

  • Alternative: Verwende die eingebauten Methoden und Funktionen, die den Namensraum berücksichtigen.
ET.register_namespace('', 'http://example.com/namespace') movies = root.findall(".//{http://example.com/namespace}movie")

4. Manuelles Schöndrucken: Manuelle Techniken zur Einrückung und Formatierung von XML sind durch die neue Funktion indent() (Python 3.9) überflüssig geworden.

  • Alternative: Verwende ET.indent() für die automatische XML-Formatierung.
ET.indent(root, space=" ")

5. Direkte Verwendung von _ElementInterface: Interne Klassen wie _ElementInterface sind nicht für den direkten Gebrauch gedacht und könnten in zukünftigen Versionen kaputt gehen.

  • Alternative: Interagiere immer mit der dokumentierten öffentlichen API der ElementTree-Bibliothek.

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!

Werde ein Python-Entwickler

Erwerbe die Programmierkenntnisse, die alle Python-Entwickler/innen brauchen.

Steph Howson's photo
Author
Steph Howson

FAQs

Was sind häufige Anwendungsfälle für die Verwendung von XML in der Datenwissenschaft?

XML wird in der Datenwissenschaft häufig für den Datenaustausch zwischen Systemen, Web Scraping, Konfigurationsdateien und den Umgang mit Daten mit einer komplexen, hierarchischen Struktur verwendet. Sie ist besonders nützlich, wenn du mit APIs arbeitest, die XML-Daten zurückgeben.

Kann ElementTree große XML-Dateien effizient verarbeiten?

ElementTree eignet sich für den Umgang mit mittelgroßen XML-Dateien, aber für sehr große Dateien solltest du Bibliotheken wie lxml oder xml.sax zu verwenden, die speichereffizienter sind und das Streaming von großen Dateien bewältigen können.

Wie schneidet ElementTree im Vergleich zu anderen XML-Parsing-Bibliotheken wie lxml oder minidom ab?

ElementTree ist Teil der Python-Standardbibliothek und für grundlegende XML-Parsing-Aufgaben einfach zu verwenden. lxml ist leistungsfähiger und schneller und bietet zusätzliche Funktionen wie XPath 2.0-Unterstützung. minidomElementTree, eine weitere Standardbibliothek, basiert auf dem Document Object Model (DOM) und ist bei großen Dokumenten weniger effizient.

Was sind XPath-Ausdrücke und wie nützlich sind sie beim XML-Parsing?

XPath-Ausdrücke sind Abfragesprachen zur Auswahl von Knoten in einem XML-Dokument. Sie sind nützlich, um durch Elemente und Attribute in XML-Dokumenten zu navigieren und ermöglichen eine präzise Datenabfrage und -manipulation.

Wie kann ich ein XML-Dokument validieren, bevor ich es mit ElementTree parse?

XML-Dokumente können mithilfe einer XML Schema Definition (XSD) oder einer Document Type Definition (DTD) validiert werden. Python-Bibliotheken wie lxml bieten integrierte Unterstützung für die Validierung gegen diese Standards.

Welche Best Practices gibt es für das Ändern von XML-Daten mit ElementTree?

Zu den besten Praktiken gehört es, an einer Kopie der XML-Daten zu arbeiten, um versehentliche Datenverluste zu vermeiden, XPath-Ausdrücke für eine präzise Navigation zu verwenden und sicherzustellen, dass bei allen Änderungen die Wohlgeformtheit des XML-Dokuments erhalten bleibt.

Kann ElementTree verwendet werden, um XML-Daten in JSON zu konvertieren?

ElementTree selbst bietet zwar keine direkte XML-zu-JSON-Konvertierung, aber du kannst die XML-Daten mit ElementTree in ein Python-Wörterbuch parsen und das Wörterbuch dann mit dem Python json Modul.

Wie behandelt man XML-Namespaces mit ElementTree?

ElementTree kann XML-Namensräume verarbeiten, indem es das Präfix{namespace} in Tag-Namen verwendet . Du kannst auch Namespaces mit ET.register_namespace() registrieren, um die Handhabung von XML mit Namespaces zu erleichtern.

Was soll ich tun, wenn ich in ElementTree einen XML-Parsing-Fehler erlebe?

Überprüfe auf häufige Probleme wie fehlerhaftes XML, nicht unterstützte Kodierungen oder falsche Dateipfade. Nutze die Fehlerbehandlungsmechanismen von Python (try-except blocks), um Parsing-Fehler zu diagnostizieren und zu verwalten.

Ist es möglich, ein XML-Dokument mithilfe von ElementTree hübsch zu drucken?

ElementTree unterstützt Pretty-Printing nicht direkt, aber du kannst mit xml.dom.minidom verwenden, um den XML-String zu parsen und dann mit der toprettyxml() Methode verwenden, um die XML-Zeichenfolge für die Lesbarkeit zu formatieren.

Themen

Erfahre mehr über Python

Kurs

Introduction to Python

4 hr
5.9M
Master the basics of data analysis with Python in just four hours. This online course will introduce the Python interface and explore popular packages.
Siehe DetailsRight Arrow
Kurs starten
Mehr anzeigenRight Arrow
Verwandt

Der Blog

Die 20 besten Snowflake-Interview-Fragen für alle Niveaus

Bist du gerade auf der Suche nach einem Job, der Snowflake nutzt? Bereite dich mit diesen 20 besten Snowflake-Interview-Fragen vor, damit du den Job bekommst!
Nisha Arya Ahmed's photo

Nisha Arya Ahmed

20 Min.

Der Blog

Die 32 besten AWS-Interview-Fragen und Antworten für 2024

Ein kompletter Leitfaden zur Erkundung der grundlegenden, mittleren und fortgeschrittenen AWS-Interview-Fragen, zusammen mit Fragen, die auf realen Situationen basieren. Es deckt alle Bereiche ab und sorgt so für eine abgerundete Vorbereitungsstrategie.
Zoumana Keita 's photo

Zoumana Keita

30 Min.

Der Blog

Top 30 Generative KI Interview Fragen und Antworten für 2024

Dieser Blog bietet eine umfassende Sammlung von Fragen und Antworten zu generativen KI-Interviews, die von grundlegenden Konzepten bis hin zu fortgeschrittenen Themen reichen.
Hesam Sheikh Hassani's photo

Hesam Sheikh Hassani

15 Min.

See MoreSee More