Kursus
Jalankan dan edit kode dari tutorial ini secara online.
Jalankan kodeSebagai data scientist, Anda akan menemukan bahwa memahami XML sangat berguna baik untuk web-scraping maupun praktik umum dalam mem-parsing dokumen terstruktur.
- Anda akan mempelajari lebih lanjut tentang XML, dan Anda akan diperkenalkan pada paket Python
ElementTree. - Lalu, Anda akan menemukan cara menjelajahi pohon XML untuk memahami data yang Anda kerjakan lebih baik dengan bantuan fungsi
ElementTree, for loop, dan ekspresi XPath. - Berikutnya, Anda akan mempelajari cara memodifikasi file XML.
- Anda juga akan menggunakan ekspresi xpath untuk mengisi file XML.
Apa itu XML?
XML adalah singkatan dari "Extensible Markup Language". Bahasa ini terutama digunakan di halaman web, di mana data memiliki struktur spesifik dan dipahami secara dinamis oleh kerangka kerja XML.
XML membuat struktur seperti pohon yang mudah diinterpretasikan dan mendukung hierarki. Setiap kali sebuah halaman mengikuti XML, itu dapat disebut sebagai dokumen XML.
- Dokumen XML memiliki bagian-bagian yang disebut elemen, yang didefinisikan oleh tag pembuka dan penutup. Tag adalah konstruksi markup yang dimulai dengan
<dan diakhiri dengan>. Karakter di antara tag pembuka dan penutup, jika ada, adalah konten elemen. Elemen dapat berisi markup, termasuk elemen lain, yang disebut "elemen anak". - Elemen terbesar di tingkat teratas disebut root, yang memuat semua elemen lainnya.
- Atribut adalah pasangan nama–nilai yang ada di dalam tag pembuka atau tag elemen kosong. Atribut XML hanya dapat memiliki satu nilai dan setiap atribut hanya boleh muncul paling banyak sekali pada setiap elemen.
Untuk memahaminya dengan lebih baik, lihat file XML (yang dipersingkat) berikut:
<?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>
Dari yang Anda baca di atas, Anda melihat bahwa
<collection>adalah elemen root tunggal: ini memuat semua elemen lain, seperti<genre>, atau<movie>, yang merupakan elemen anak atau subelemen. Seperti yang Anda lihat, elemen-elemen ini bersarang.
Catatan bahwa elemen anak ini juga dapat bertindak sebagai induk dan memiliki elemen anak mereka sendiri, yang kemudian disebut "sub-child elements".
- Anda akan melihat bahwa, misalnya, elemen
<movie>berisi beberapa "atribut", sepertifavoritetitleyang memberikan informasi lebih lanjut!
Dengan pengantar singkat tentang file XML ini, Anda siap mempelajari lebih lanjut tentang ElementTree!
Pengantar ElementTree
Struktur pohon XML membuat navigasi, modifikasi, dan penghapusan relatif sederhana secara terprogram. Python memiliki pustaka bawaan, ElementTree, yang memiliki fungsi untuk membaca dan memanipulasi XML (dan file berstruktur serupa lainnya).
Pertama, impor ElementTree. Merupakan praktik umum menggunakan alias ET:
import xml.etree.ElementTree as ET
Mem-parsing Data XML
File XML yang disediakan menggambarkan kumpulan film dasar. Masalahnya hanya satu: datanya berantakan! Koleksi ini telah dikurasi oleh banyak orang berbeda, dan masing-masing memiliki cara sendiri untuk memasukkan data ke dalam file. Tujuan utama dalam tutorial ini adalah membaca dan memahami file dengan Python lalu memperbaiki masalahnya.
Pertama, Anda perlu membaca file dengan ElementTree.
tree = ET.parse('movies.xml')
root = tree.getroot()
Sekarang setelah Anda menginisialisasi pohon, Anda sebaiknya melihat XML dan mencetak nilai untuk memahami bagaimana struktur pohonnya.
Setiap bagian dari pohon (termasuk root) memiliki tag yang menjelaskan elemen tersebut. Selain itu, seperti yang Anda lihat pada pengantar, elemen mungkin memiliki atribut, yang merupakan deskriptor tambahan yang digunakan terutama untuk penggunaan tag berulang. Atribut juga membantu memvalidasi nilai yang dimasukkan untuk tag tersebut, sekali lagi berkontribusi pada format terstruktur XML.
Anda akan melihat nanti di tutorial ini bahwa atribut bisa sangat kuat ketika disertakan dalam XML!
root.tag
'collection'
Di tingkat teratas, Anda melihat bahwa XML ini berakar pada tag collection.
root.attrib
{}
Jadi, root tidak memiliki atribut.
For loop
Anda dapat dengan mudah beriterasi pada subelemen (umumnya disebut "anak") di root dengan menggunakan for loop sederhana.
for child in root:
print(child.tag, child.attrib)
genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}
Sekarang Anda tahu bahwa anak dari root collection semuanya adalah genre. Untuk menetapkan genre, XML menggunakan atribut category. Ada film Action, Thriller, dan Comedy menurut elemen genre.
Biasanya akan membantu untuk mengetahui semua elemen dalam seluruh pohon. Salah satu fungsi yang berguna untuk melakukan itu adalah root.iter(). Anda dapat menempatkan fungsi ini ke dalam for loop dan itu akan beriterasi pada seluruh pohon.
[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']
Ini memberi gambaran umum tentang berapa banyak elemen yang Anda miliki, tetapi tidak menampilkan atribut atau level dalam pohon.
Ada cara yang membantu untuk melihat seluruh dokumen. Elemen apa pun memiliki metode .tostring(). Jika Anda memberikan root ke dalam metode .tostring(), Anda dapat mengembalikan seluruh dokumen. Di dalam ElementTree (ingat dialias sebagai ET), .tostring() mengambil bentuk yang sedikit tidak lazim.
Karena ElementTree adalah pustaka yang kuat yang dapat menginterpretasikan lebih dari sekadar XML. Anda harus menentukan baik encoding maupun decoding dari dokumen yang Anda tampilkan sebagai string. Untuk XML, gunakan 'utf8' - Ini adalah format dokumen yang umum untuk 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>
Anda dapat memperluas penggunaan fungsi iter() untuk membantu menemukan elemen tertentu yang menarik. root.iter() akan mencantumkan semua subelemen di bawah root yang cocok dengan elemen yang ditentukan. Di sini, Anda akan mencantumkan semua atribut elemen movie dalam pohon:
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'}
Anda sudah dapat melihat bagaimana movies dimasukkan dengan berbagai cara. Jangan khawatir tentang itu sekarang. Anda akan mendapat kesempatan memperbaiki salah satu kesalahan nanti di tutorial ini.
Ekspresi XPath
Sering kali elemen tidak memiliki atribut, hanya memiliki konten teks. Dengan menggunakan atribut .text, Anda dapat mencetak konten ini.
Sekarang, cetak semua deskripsi film.
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
Mencetak XML itu membantu, tetapi XPath adalah bahasa kueri yang digunakan untuk mencari di XML dengan cepat dan mudah. XPath adalah singkatan dari XML Path Language dan, seperti namanya, menggunakan sintaks "mirip jalur" untuk mengidentifikasi dan menavigasi node dalam dokumen XML.
Memahami XPath sangat penting untuk memindai dan mengisi XML. ElementTree memiliki fungsi .findall() yang akan melintasi anak langsung dari elemen yang direferensikan. Anda dapat menggunakan ekspresi XPath untuk menentukan pencarian yang lebih bermanfaat.
Di sini, Anda akan mencari film-film dalam pohon yang dirilis pada 1992:
for movie in root.findall("./genre/decade/movie/[year='1992']"):
print(movie.attrib)
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
Fungsi .findall() selalu dimulai pada elemen yang ditentukan. Jenis fungsi ini sangat kuat untuk "find and replace". Anda bahkan dapat mencari berdasarkan atribut!
Sekarang, cetak hanya film yang tersedia dalam beberapa format (sebuah atribut).
for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
print(movie.attrib)
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
Pikirkan mengapa, dalam kasus ini, pernyataan print mengembalikan nilai "Yes" dari multiple. Pikirkan bagaimana for loop didefinisikan. Bisakah Anda menulis ulang loop ini untuk mencetak judul film sebagai gantinya? Coba di bawah ini:
Tips: gunakan '...' di dalam XPath untuk mengembalikan elemen induk dari elemen saat ini.
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'}
Memodifikasi XML
Sebelumnya, judul film benar-benar berantakan. Sekarang, cetak lagi:
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'}
Perbaiki '2' pada Back 2 the Future. Itu seharusnya masalah find-and-replace. Tulis kode untuk menemukan judul 'Back 2 the Future' dan simpan sebagai variabel:
b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)
<Element 'movie' at 0x10ce00ef8>
Perhatikan bahwa menggunakan metode .find() mengembalikan elemen dari pohon. Sering kali, akan lebih berguna untuk mengedit konten di dalam sebuah elemen.
Ubah atribut title dari variabel elemen Back 2 the Future menjadi "Back to the Future". Lalu, cetak atribut variabel Anda untuk melihat perubahannya. Anda dapat dengan mudah melakukannya dengan mengakses atribut dari sebuah elemen lalu menetapkan nilai baru padanya:
b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)
{'favorite': 'False', 'title': 'Back to the Future'}
Tuliskan perubahan Anda kembali ke XML agar diperbaiki secara permanen dalam dokumen. Cetak kembali atribut film Anda untuk memastikan perubahan berhasil. Gunakan metode .write() untuk melakukan ini:
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'}
Memperbaiki Atribut
Atribut multiple salah di beberapa tempat. Gunakan ElementTree untuk memperbaiki penanda berdasarkan berapa banyak format yang dimiliki film tersebut. Pertama, cetak atribut dan teks format untuk melihat bagian mana yang perlu diperbaiki.
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
Ada beberapa pekerjaan yang perlu dilakukan pada tag ini.
Anda dapat menggunakan regex untuk menemukan koma - itu akan memberi tahu apakah atribut multiple harus "Yes" atau "No." Menambahkan dan memodifikasi atribut dapat dilakukan dengan mudah dengan metode .set().
Catatan: re adalah interpreter regex standar untuk Python. Jika Anda ingin tahu lebih banyak tentang regular expression, pertimbangkan tutorial ini.
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
Memindahkan Elemen
Beberapa data ditempatkan pada dekade yang salah. Gunakan apa yang telah Anda pelajari tentang XML dan ElementTree untuk menemukan dan memperbaiki kesalahan data dekade.
Akan berguna untuk mencetak baik tag decade maupun tag year di seluruh dokumen.
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
Dua tahun yang berada pada dekade yang salah adalah film dari tahun 2000-an. Cari tahu film apa saja itu menggunakan ekspresi XPath.
for movie in root.findall("./genre/decade/movie/[year='2000']"):
print(movie.attrib)
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}
Anda harus menambahkan tag dekade baru, 2000-an, ke genre Action untuk memindahkan data X-Men. Metode .SubElement() dapat digunakan untuk menambahkan tag ini ke akhir XML.
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>
Sekarang tambahkan film X-Men ke 2000-an dan hapus dari 1990-an, masing-masing menggunakan .append() dan .remove().
xmen = root.find("./genre/decade/movie[@title='X-Men']")
dec2000s = root.find("./genre[@category='Action']/decade[@years='2000s']")
dec2000s.append(xmen)
dec1990s = root.find("./genre[@category='Action']/decade[@years='1990s']")
dec1990s.remove(xmen)
print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back to the Future">
<format multiple="No">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
<decade years="2000s"><movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
</decade></genre>
Membangun Dokumen XML
Bagus, Anda berhasil memindahkan satu film secara keseluruhan ke dekade baru. Simpan perubahan Anda kembali ke XML.
tree.write("movies.xml")
tree = ET.parse('movies.xml')
root = tree.getroot()
print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back to the Future">
<format multiple="No">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
<decade years="2000s"><movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
</decade></genre>
<genre category="Thriller">
<decade years="1970s">
<movie favorite="False" title="ALIEN">
<format multiple="No">DVD</format>
<year>1979</year>
<rating>R</rating>
<description>"""""""""</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="True" title="Ferris Bueller's Day Off">
<format multiple="No">DVD</format>
<year>1986</year>
<rating>PG13</rating>
<description>Funny movie about a funny guy</description>
</movie>
<movie favorite="FALSE" title="American Psycho">
<format multiple="No">blue-ray</format>
<year>2000</year>
<rating>Unrated</rating>
<description>psychopathic Bateman</description>
</movie>
</decade>
</genre>
<genre category="Comedy">
<decade years="1960s">
<movie favorite="False" title="Batman: The Movie">
<format multiple="Yes">DVD,VHS</format>
<year>1966</year>
<rating>PG</rating>
<description>What a joke!</description>
</movie>
</decade>
<decade years="2010s">
<movie favorite="True" title="Easy A">
<format multiple="No">DVD</format>
<year>2010</year>
<rating>PG--13</rating>
<description>Emma Stone = Hester Prynne</description>
</movie>
<movie favorite="True" title="Dinner for SCHMUCKS">
<format multiple="Yes">DVD,digital,Netflix</format>
<year>2011</year>
<rating>Unrated</rating>
<description>Tim (Rudd) is a rising executive
who “succeeds” in finding the perfect guest,
IRS employee Barry (Carell), for his boss’ monthly event,
a so-called “dinner for idiots,” which offers certain
advantages to the exec who shows up with the biggest buffoon.
</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="False" title="Ghostbusters">
<format multiple="Yes">Online,VHS</format>
<year>1984</year>
<rating>PG</rating>
<description>Who ya gonna call?</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Robin Hood: Prince of Thieves">
<format multiple="No">Blu_Ray</format>
<year>1991</year>
<rating>Unknown</rating>
<description>Robin Hood slaying</description>
</movie>
</decade>
</genre>
</collection>
Apa yang Baru di ElementTree?
Berikut ikhtisar fitur dan peningkatan baru pada pustaka ElementTree di versi Python yang lebih baru:
1. Dukungan XPath 1.0 (Python 3.8): Mulai Python 3.8, ElementTree mencakup dukungan lengkap XPath 1.0 dengan metode find() dan findall(), memungkinkan kueri XML yang lebih kaya dan kompleks. Contoh:
# Finding all movies with a specific attribute using XPath
for movie in root.findall(".//movie[@favorite='True']"):
print(movie.attrib)
2. Peningkatan namespaces (Python 3.8+): Dukungan yang ditingkatkan untuk XML namespace, memungkinkan interaksi yang lebih mudah dengan file XML yang menggunakan namespace berawalan atau default. Contoh:
# Register a namespace and find elements using it
ET.register_namespace('', 'http://example.com/namespace')
movies = root.findall(".//{http://example.com/namespace}movie")
3. Peningkatan parser (Python 3.9): Pesan kesalahan parsing yang lebih baik memudahkan debugging file XML yang tidak valid.
4. Fungsi indent() baru (Python 3.9): Fungsi xml.etree.ElementTree.indent() ditambahkan untuk melakukan pretty-print dokumen XML dengan menjorokkan elemennya. Contoh:
ET.indent(root, space=" ", level=0)
ET.dump(root)
5. Parsing Efisien dengan iterparse (Python 3.10): Dioptimalkan untuk efisiensi memori, sangat berguna saat bekerja dengan file XML besar.
6. Dokumentasi yang diperluas (Pembaruan berkelanjutan): Dokumentasi Python untuk ElementTree kini lebih komprehensif, termasuk praktik terbaik dan use case lanjutan.
Fitur yang Didepresiasi di ElementTree dan Alternatifnya
1. write() dengan xml_declaration di Python 3.8+: Parameter xml_declaration pada metode write() didepresiasi ketika encoding diatur ke 'unicode'.
- Alternatif: Gunakan
xml_declarationhanya ketika encoding secara eksplisit ditetapkan selain'unicode'.
tree.write("output.xml", encoding="utf-8", xml_declaration=True)
2. html parser: Meskipun tidak secara resmi didepresiasi, penggunaan ElementTree untuk parsing HTML tidak disarankan karena terbatas dalam menangani HTML yang tidak well-formed.
- Alternatif: Gunakan pustaka yang dirancang khusus untuk parsing HTML, seperti
BeautifulSoupdari paketbs4.
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser')
3. Solusi sementara penanganan namespace: Metode lama untuk menangani namespace secara manual (misalnya, menggabungkan URI namespace dengan tag elemen) kurang direkomendasikan dengan hadirnya dukungan namespace yang lebih andal di versi baru.
- Alternatif: Gunakan metode dan fungsi bawaan yang sadar namespace.
ET.register_namespace('', 'http://example.com/namespace') movies = root.findall(".//{http://example.com/namespace}movie")
4. Pretty-print manual: Teknik manual untuk indentasi dan pemformatan XML menjadi usang oleh fungsi indent() yang baru (Python 3.9).
- Alternatif: Gunakan
ET.indent()untuk pemformatan XML otomatis.
ET.indent(root, space=" ")
5. Penggunaan langsung _ElementInterface: Kelas internal seperti _ElementInterface tidak dimaksudkan untuk penggunaan langsung dan mungkin rusak di versi mendatang.
- Alternatif: Selalu berinteraksi dengan API publik terdokumentasi dari pustaka ElementTree.
Kesimpulan
Ada beberapa hal kunci yang perlu diingat tentang XML dan penggunaan ElementTree.
Tag membangun struktur pohon dan menetapkan nilai apa yang harus diuraikan di sana. Menggunakan penataan yang cerdas dapat memudahkan pembacaan dan penulisan XML. Tag selalu membutuhkan tanda kurung pembuka dan penutup untuk menunjukkan hubungan induk dan anak.
Atribut lebih lanjut menjelaskan bagaimana memvalidasi tag atau memungkinkan penandaan boolean. Atribut biasanya mengambil nilai yang sangat spesifik sehingga parser XML (dan pengguna) dapat menggunakan atribut untuk memeriksa nilai tag.
ElementTree adalah pustaka Python penting yang memungkinkan Anda mem-parsing dan menavigasi dokumen XML. Menggunakan ElementTree memecah dokumen XML dalam struktur pohon yang mudah digunakan. Jika ragu, cetak saja (print(ET.tostring(root, encoding='utf8').decode('utf8'))) - gunakan pernyataan print yang membantu ini untuk melihat seluruh dokumen XML sekaligus. Ini membantu saat memeriksa saat mengedit, menambah, atau menghapus dari XML.
Sekarang, Anda siap memahami XML dan mulai mem-parsing!

FAQs
Apa saja use case umum penggunaan XML dalam data science?
XML sering digunakan dalam data science untuk pertukaran data antar sistem, web scraping, file konfigurasi, dan penanganan data dengan struktur hierarkis yang kompleks. Ini sangat berguna saat bekerja dengan API yang mengembalikan data XML.
Apakah ElementTree dapat menangani file XML besar secara efisien?
ElementTree cocok untuk menangani file XML berukuran sedang, tetapi untuk file yang sangat besar, Anda dapat mempertimbangkan menggunakan pustaka seperti lxml atau xml.sax yang lebih efisien memori dan dapat menangani streaming file besar.
Bagaimana perbandingan ElementTree dengan pustaka parsing XML lain seperti lxml atau minidom?
ElementTree adalah bagian dari pustaka standar Python dan mudah digunakan untuk tugas parsing XML dasar. lxml lebih kuat dan lebih cepat, menyediakan fitur tambahan seperti dukungan XPath 2.0. minidom, pustaka standar lainnya, berbasis Document Object Model (DOM) dan kurang efisien untuk dokumen besar.
Apa itu ekspresi XPath dan bagaimana kegunaannya dalam parsing XML?
Ekspresi XPath adalah bahasa kueri untuk memilih node dari dokumen XML. XPath berguna untuk menavigasi elemen dan atribut dalam dokumen XML, memungkinkan pengambilan dan manipulasi data secara presisi.
Bagaimana saya dapat memvalidasi dokumen XML sebelum mem-parsing-nya dengan ElementTree?
Dokumen XML dapat divalidasi menggunakan XML Schema Definition (XSD) atau Document Type Definition (DTD). Pustaka Python seperti lxml menawarkan dukungan bawaan untuk validasi terhadap standar tersebut.
Apa saja praktik terbaik untuk memodifikasi data XML menggunakan ElementTree?
Praktik terbaik meliputi bekerja pada salinan data XML untuk menghindari kehilangan data secara tidak sengaja, menggunakan ekspresi XPath untuk navigasi yang presisi, dan memastikan semua perubahan mempertahankan well-formedness dokumen XML.
Dapatkah ElementTree digunakan untuk mengonversi data XML ke JSON?
ElementTree sendiri tidak menyediakan konversi langsung XML-ke-JSON, tetapi Anda dapat mem-parsing data XML ke dalam dictionary Python menggunakan ElementTree lalu mengonversi dictionary tersebut ke JSON menggunakan modul Python json.
Bagaimana cara menangani XML namespace dengan ElementTree?
ElementTree dapat menangani XML namespace dengan menggunakan awalan {namespace} pada nama tag. Anda juga dapat mendaftarkan namespace dengan ET.register_namespace() untuk penanganan XML bernamespace yang lebih mudah.
Apa yang harus saya lakukan jika mengalami error parsing XML di ElementTree?
Periksa masalah umum seperti XML yang tidak valid, encoding yang tidak didukung, atau path file yang salah. Gunakan mekanisme penanganan error Python (try-except) untuk mendiagnosis dan menangani error parsing secara elegan.
Apakah memungkinkan melakukan pretty-print dokumen XML menggunakan ElementTree?
ElementTree tidak mendukung pretty-print secara langsung, tetapi Anda dapat menggunakan xml.dom.minidom untuk mem-parsing string XML lalu gunakan metode toprettyxml() untuk memformat XML agar mudah dibaca.
