Course
Python XML Tutorial mit ElementTree: Leitfaden für Anfänger
Führe den Code aus diesem Tutorial online aus und bearbeite ihn
Code ausführenAls 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.
- Du lernst mehr über XML und bekommst eine Einführung in das Python-Paket
ElementTree
. - Dann erfährst du, wie du mit Hilfe von
ElementTree
Funktionen, for-Schleifen und XPath-Ausdrücken XML-Bäume erkunden kannst, um die Daten, mit denen du arbeitest, besser zu verstehen. - Als Nächstes erfährst du, wie du eine XML-Datei ändern kannst; und
- Du verwendest xpath-Ausdrücke, um XML-Dateien zu füllen.
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:
Erfahre mehr über Python
Course
Intermediate Python
Course