Kurs
Bu eğitimdeki kodu çevrimiçi olarak çalıştırın ve düzenleyin
Kodu çalıştırBir veri bilimci olarak, XML'i anlamanın hem web kazıma hem de yapılandırılmış bir belgeyi ayrıştırma pratiği için güçlü olduğunu göreceksiniz.
- XML hakkında daha fazla bilgi edinecek ve Python
ElementTreepaketine giriş yapacaksınız. - Ardından, üzerinde çalıştığınız veriyi daha iyi anlamak için
ElementTreeişlevleri, for döngüleri ve XPath ifadelerinin yardımıyla XML ağaçlarını nasıl keşfedebileceğinizi göreceksiniz. - Sonraki adımda, bir XML dosyasını nasıl değiştirebileceğinizi öğreneceksiniz.
- Ayrıca, XML dosyalarını doldurmak için xpath ifadelerini kullanacaksınız.
XML nedir?
XML, "Genişletilebilir Biçimlendirme Dili"nin kısaltmasıdır. Verinin belirli bir yapıda olduğu ve XML çerçevesi tarafından dinamik olarak anlaşıldığı web sayfalarında ağırlıklı olarak kullanılır.
XML, yorumlaması kolay ve hiyerarşiyi destekleyen ağaç benzeri bir yapı oluşturur. Bir sayfa XML'i takip ettiğinde, buna XML belgesi denebilir.
- XML belgelerinde öğeler olarak adlandırılan bölümler bulunur ve bunlar bir başlangıç ve bitiş etiketi ile tanımlanır. Etiket,
<ile başlayan ve>ile biten bir biçimlendirme yapısıdır. Başlangıç ve bitiş etiketi arasındaki karakterler, varsa, öğenin içeriğidir. Öğeler, diğer öğeler de dahil olmak üzere biçimlendirme içerebilir; bunlara "alt öğeler" denir. - En büyük, en üst düzey öğe kök olarak adlandırılır ve diğer tüm öğeleri içerir.
- Öznitelikler, bir başlangıç etiketi veya boş öğe etiketi içinde bulunan ad–değer çiftleridir. Bir XML özniteliği yalnızca tek bir değere sahip olabilir ve her öznitelik her bir öğede en fazla bir kez görünebilir.
Bunu biraz daha iyi anlamak için aşağıdaki (kısaltılmış) XML dosyasına göz atın:
<?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>
Yukarıda okuduklarınıza göre şunları görüyorsunuz:
<collection>tek kök öğedir:<genre>veya<movie>gibi iç içe geçmiş alt öğeleri veya alt öğecikleri içerir.
Not: Bu alt öğeler aynı zamanda ebeveyn görevi de görebilir ve kendi alt öğelerini içerebilir; bunlara da "alt-alt öğeler" denir.
- Örneğin
<movie>öğesininfavoritetitlegibi daha fazla bilgi veren birkaç "özniteliği" olduğunu göreceksiniz!
XML dosyalarına kısa bu girişle, ElementTree hakkında daha fazlasını öğrenmeye hazırsınız!
ElementTree'ye Giriş
XML ağaç yapısı, programatik olarak gezinmeyi, değiştirmeyi ve kaldırmayı nispeten basit hale getirir. Python'da, XML'leri (ve benzer yapılı diğer dosyaları) okumak ve işlemek için işlevlere sahip yerleşik bir kütüphane olan ElementTree bulunur.
Önce ElementTree'yi içe aktarın. ET kısaltmasını kullanmak yaygın bir uygulamadır:
import xml.etree.ElementTree as ET
XML Verisini Ayrıştırma
Sağlanan XML dosyası temel bir film koleksiyonunu tanımlıyor. Tek sorun, verinin karmakarışık olması! Bu koleksiyonun birçok farklı küratörü olmuş ve herkes dosyaya veriyi girmenin kendi yolunu kullanmış. Bu eğitimdeki ana hedef, dosyayı Python ile okuyup anlamak ve ardından sorunları düzeltmek olacaktır.
Önce dosyayı ElementTree ile okumanız gerekir.
tree = ET.parse('movies.xml')
root = tree.getroot()
Artık ağacı başlattığınıza göre, ağacın nasıl yapılandığını anlamak için XML'e bakmalı ve değerleri yazdırmalısınız.
Bir ağacın her bölümünün (kök dahil) öğeyi tanımlayan bir etiketi vardır. Ayrıca, girişte gördüğünüz gibi, öğelerin özellikle yinelenen etiket kullanımında kullanılan ek tanımlayıcılar olan öznitelikleri olabilir. Öznitelikler, bir XML'in yapılandırılmış biçimine katkıda bulunarak, o etiket için girilen değerlerin doğrulanmasına da yardımcı olur.
Bu eğitimde daha sonra, özniteliklerin bir XML'e dahil edildiğinde oldukça güçlü olabileceğini göreceksiniz!
root.tag
'collection'
En üst düzeyde, bu XML'in collection etiketiyle köklendiğini görüyorsunuz.
root.attrib
{}
Yani, kökün öznitelikleri yok.
For döngüleri
Kökteki alt öğeler (genellikle "çocuklar" olarak adlandırılır) üzerinde basit bir "for" döngüsü kullanarak kolayca yineleme yapabilirsiniz.
for child in root:
print(child.tag, child.attrib)
genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}
Artık kök collection'ın çocuklarının hepsinin genre olduğunu biliyorsunuz. Türü belirtmek için XML, category özniteliğini kullanır. genre öğesine göre Aksiyon, Gerilim ve Komedi filmleri vardır.
Genellikle tüm ağaçtaki öğelerin tamamını bilmek faydalıdır. Bunu yapmak için kullanışlı bir işlev root.iter()'dır. Bu işlevi bir "for" döngüsüne koyabilir ve tüm ağaç üzerinde yineleme yapabilirsiniz.
[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']
Bu, kaç öğeniz olduğuna dair genel bir fikir verir ancak öznitelikleri veya ağaçtaki seviyeleri göstermez.
Tüm belgeyi görmenin yardımcı bir yolu vardır. Herhangi bir öğenin bir .tostring() yöntemi vardır. Kökü .tostring() yöntemine geçirirseniz tüm belgeyi döndürebilirsiniz. ElementTree içinde (ET olarak kısaltıldığını unutmayın), .tostring() biraz tuhaf bir biçim alır.
ElementTree, yalnızca XML'i değil daha fazlasını yorumlayabilen güçlü bir kütüphane olduğundan, görüntülediğiniz belgenin kodlamasını ve kod çözümlemesini belirtmelisiniz. XML'ler için 'utf8' kullanın - Bu, bir XML için tipik belge biçimidir.
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>
iter() işlevinin kullanımını, ilgi çekici belirli öğeleri bulmaya yardımcı olacak şekilde genişletebilirsiniz. root.iter(), belirtilen öğeyle eşleşen kök altındaki tüm alt öğeleri listeler. Burada, ağaçtaki movie öğesinin tüm özniteliklerini listeleyeceksiniz:
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'}
movies'ların farklı şekillerde girildiğini şimdiden görebilirsiniz. Şimdilik bunu dert etmeyin. Bu eğitimde daha sonra hatalardan birini düzeltme şansı bulacaksınız.
XPath ifadeleri
Çoğu zaman öğelerin öznitelikleri olmaz, yalnızca metin içerikleri olur. .text özniteliğini kullanarak bu içeriği yazdırabilirsiniz.
Şimdi, filmlerin tüm açıklamalarını yazdırın.
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
XML'i yazdırmak yardımcıdır, ancak XPath, bir XML'de hızlı ve kolay arama yapmak için kullanılan bir sorgu dilidir. XPath, XML Yol Dili anlamına gelir ve adından da anlaşılacağı gibi, bir XML belgesindeki düğümleri belirlemek ve gezinmek için "yol benzeri" bir sözdizimi kullanır.
XPath'i anlamak, XML'leri taramak ve doldurmak için kritik öneme sahiptir. ElementTree'nin .findall() işlevi, başvurulan öğenin doğrudan çocukları arasında dolaşır. Daha kullanışlı aramalar belirtmek için XPath ifadelerini kullanabilirsiniz.
Burada, 1992'de çıkan filmleri ağaçta arayacaksınız:
for movie in root.findall("./genre/decade/movie/[year='1992']"):
print(movie.attrib)
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
.findall() işlevi her zaman belirtilen öğeden başlar. Bu tür bir işlev, "bul ve değiştir" için son derece güçlüdür. Öznitelikler üzerinde bile arama yapabilirsiniz!
Şimdi, yalnızca birden fazla formatta mevcut olan (bir öznitelik) filmleri yazdırın.
for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
print(movie.attrib)
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
Bu durumda yazdırma ifadesinin multiple özniteliğinin "Yes" değerlerini neden döndürdüğünü düşünün. "for" döngüsünün nasıl tanımlandığını düşünün. Bu döngüyü film başlıklarını yazdıracak şekilde yeniden yazabilir misiniz? Aşağıda deneyin:
İpucu: Geçerli öğenin üst öğesini döndürmek için XPath içinde '...' kullanın.
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'}
Bir XML'i Değiştirme
Daha önce, film başlıkları tam bir karmaşaydı. Şimdi, bunları tekrar yazdırın:
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'}
Back 2 the Future'daki '2'yi düzeltin. Bu bir bul-ve-değiştir problemidir. 'Back 2 the Future' başlığını bulun ve bir değişkende saklayın:
b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)
<Element 'movie' at 0x10ce00ef8>
.find() yönteminin kullanılmasının ağaçtan bir öğe döndürdüğüne dikkat edin. Çoğu zaman, bir öğenin içindeki içeriği düzenlemek daha kullanışlıdır.
Back 2 the Future öğe değişkeninin title özniteliğini "Back to the Future" olacak şekilde değiştirin. Ardından, değişikliğinizi görmek için değişkeninizin özniteliklerini yazdırın. Bunu, bir öğenin özniteliğine erişip ona yeni bir değer atayarak kolayca yapabilirsiniz:
b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)
{'favorite': 'False', 'title': 'Back to the Future'}
Değişikliklerinizi XML'e geri yazın ki belgede kalıcı olarak düzelsin. Değişikliklerinizin çalıştığından emin olmak için film özniteliklerinizi tekrar yazdırın. Bunu yapmak için .write() yöntemini kullanın:
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'}
Öznitelikleri Düzeltme
multiple özniteliği bazı yerlerde hatalı. Filmin kaç formatta geldiğine göre belirteci düzeltmek için ElementTree'yi kullanın. Önce hangi kısımların düzeltilmesi gerektiğini görmek için format özniteliğini ve metnini yazdırın.
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
Bu etikette yapılması gereken bazı işler var.
Virgülleri bulmak için regex kullanabilirsiniz - bu, multiple özniteliğinin "Yes" mi yoksa "No" mu olması gerektiğini söyleyecektir. Öznitelik ekleme ve değiştirme, .set() yöntemiyle kolayca yapılabilir.
Not: re, Python için standart regex yorumlayıcısıdır. Düzenli ifadeler hakkında daha fazla bilgi almak isterseniz bu eğitimi göz önünde bulundurun.
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
Öğeleri Taşıma
Bazı veriler yanlış on yıla yerleştirilmiş. XML ve ElementTree hakkında öğrendiklerinizi kullanarak on yıl verisi hatalarını bulun ve düzeltin.
Belge genelinde hem decade hem de year etiketlerini yazdırmak faydalı olacaktır.
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
Yanlış on yılda olan iki yıl, 2000'lerden gelen filmler. Bunların hangi filmler olduğunu bir XPath ifadesi kullanarak bulun.
for movie in root.findall("./genre/decade/movie/[year='2000']"):
print(movie.attrib)
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}
X-Men verisini taşımak için Aksiyon türüne 2000'ler şeklinde yeni bir on yıl etiketi eklemeniz gerekiyor. Bu etiketi XML'in sonuna eklemek için .SubElement() yöntemi kullanılabilir.
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>
Şimdi X-Men filmini 2000'lere ekleyin ve 1990'lardan kaldırın; sırasıyla .append() ve .remove() kullanın.
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 Belgeleri Oluşturma
Güzel, böylece bir filmi temelde yeni bir on yıla taşıyabildiniz. Değişikliklerinizi XML'e kaydedin.
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>
ElementTree'de Neler Yeni?
İşte daha yeni Python sürümlerinde ElementTree kütüphanesine yönelik yeni özellikler ve iyileştirmelerin bir özeti:
1. XPath 1.0 desteği (Python 3.8): Python 3.8 ile birlikte, find() ve findall() yöntemleriyle ElementTree tam XPath 1.0 desteği sunar; bu da daha zengin ve karmaşık XML sorgularını mümkün kılar. Örnek:
# Finding all movies with a specific attribute using XPath
for movie in root.findall(".//movie[@favorite='True']"):
print(movie.attrib)
2. Ad alanlarında iyileştirmeler (Python 3.8+): Ön ekli veya varsayılan ad alanları kullanan XML dosyalarıyla daha kolay etkileşim sağlayan gelişmiş destek. Örnek:
# Register a namespace and find elements using it
ET.register_namespace('', 'http://example.com/namespace')
movies = root.findall(".//{http://example.com/namespace}movie")
3. Ayrıştırıcı iyileştirmeleri (Python 3.9): Daha iyi ayrıştırma hata iletileri, bozuk XML dosyalarında hata ayıklamayı kolaylaştırır.
4. Yeni indent() işlevi (Python 3.9): xml.etree.ElementTree.indent() işlevi, öğeleri girintileyerek XML belgelerini güzel biçimde yazdırmak için eklendi. Örnek:
ET.indent(root, space=" ", level=0)
ET.dump(root)
5. iterparse ile verimli ayrıştırma (Python 3.10): Özellikle büyük XML dosyalarıyla çalışırken bellek verimliliği için optimize edilmiştir.
6. Genişletilmiş dokümantasyon (Süregelen güncellemeler): ElementTree için Python dokümantasyonu artık en iyi uygulamalar ve ileri düzey kullanım senaryolarını da içerecek şekilde daha kapsamlıdır.
ElementTree'deki Kullanımdan Kaldırılan Özellikler ve Alternatifler
1. Python 3.8+ sürümlerinde xml_declaration ile write(): Kodlama 'unicode' olarak ayarlandığında write() yönteminin xml_declaration parametresi kullanımdan kaldırılmıştır.
- Alternatif:
xml_declaration'ı yalnızca kodlama açıkça'unicode'dışında bir şey olarak tanımlandığında kullanın.
tree.write("output.xml", encoding="utf-8", xml_declaration=True)
2. html ayrıştırıcı: Resmen kullanımdan kaldırılmamış olsa da, iyi biçimlendirilmemiş HTML'yi ele alma konusundaki sınırlamalar nedeniyle HTML ayrıştırma için ElementTree kullanılması önerilmez.
- Alternatif:
bs4paketindekiBeautifulSoupgibi HTML ayrıştırmaya özel tasarlanmış kütüphaneleri kullanın.
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser')
3. Ad alanı işleme geçici çözümleri: Ad alanlarını manuel olarak ele alan eski yöntemler (ör. ad alanı URI'larını öğe etiketleriyle birleştirmek), daha yeni sürümlerdeki sağlam ad alanı desteğiyle birlikte artık daha az önerilmektedir.
- Alternatif: Yerleşik, ad alanı farkında yöntemleri ve işlevleri kullanın.
ET.register_namespace('', 'http://example.com/namespace') movies = root.findall(".//{http://example.com/namespace}movie")
4. Elle güzel yazdırma: XML'i girintileme ve biçimlendirme için kullanılan manuel teknikler, yeni indent() işleviyle (Python 3.9) gereksiz hale gelmiştir.
- Alternatif: Otomatik XML biçimlendirme için
ET.indent()kullanın.
ET.indent(root, space=" ")
5. _ElementInterface'in doğrudan kullanımı: _ElementInterface gibi dahili sınıflar doğrudan kullanım için tasarlanmamıştır ve gelecekteki sürümlerde bozulabilir.
- Alternatif: Her zaman ElementTree kütüphanesinin belgelenmiş herkese açık API'siyle etkileşime geçin.
Sonuç
XML'ler ve ElementTree kullanımıyla ilgili akılda tutulması gereken bazı temel noktalar vardır.
Etiketler ağaç yapısını oluşturur ve orada hangi değerlerin belirtilmesi gerektiğini belirler. Akıllı bir yapılandırma kullanmak, bir XML'i okumayı ve yazmayı kolaylaştırabilir. Etiketlerin, ebeveyn ve çocuk ilişkilerini göstermek için her zaman açılış ve kapanış parantezlerine ihtiyacı vardır.
Öznitelikler, bir etiketi nasıl doğrulayacağınızı daha ayrıntılı olarak açıklar veya boole belirteçlerine izin verir. Öznitelikler genellikle çok belirli değerler alır, böylece XML ayrıştırıcı (ve kullanıcı) etiket değerlerini kontrol etmek için öznitelikleri kullanabilir.
ElementTree, bir XML belgesini ayrıştırmanıza ve gezinmenize olanak tanıyan önemli bir Python kütüphanesidir. ElementTree kullanmak, XML belgesini üzerinde çalışması kolay bir ağaç yapısına böler. Emin olmadığınızda, yazdırın (print(ET.tostring(root, encoding='utf8').decode('utf8'))) - tüm XML belgesini bir kerede görüntülemek için bu kullanışlı yazdırma ifadesini kullanın. Bir XML'i düzenlerken, eklerken veya kaldırırken kontrol etmeye yardımcı olur.
Artık XML'i anlamak ve ayrıştırmaya başlamak için hazırsınız!

SSS
Veri biliminde XML kullanmanın bazı yaygın kullanım alanları nelerdir?
XML, veri bilimi alanında sıklıkla sistemler arası veri değişimi, web kazıma, yapılandırma dosyaları ve karmaşık, hiyerarşik yapıya sahip verilerin ele alınması için kullanılır. Özellikle XML veri döndüren API'lerle çalışırken kullanışlıdır.
ElementTree büyük XML dosyalarını verimli şekilde işleyebilir mi?
ElementTree orta büyüklükteki XML dosyaları için uygundur ancak çok büyük dosyalar için akış halinde okumayı destekleyen ve daha bellek verimli olan lxml veya xml.sax kütüphanelerini düşünebilirsiniz.
ElementTree, lxml veya minidom gibi diğer XML ayrıştırma kütüphaneleriyle nasıl karşılaştırılır?
ElementTree, Python'un standart kütüphanesinin bir parçasıdır ve temel XML ayrıştırma görevleri için kullanımı kolaydır. lxml daha güçlü ve daha hızlıdır; XPath 2.0 desteği gibi ek özellikler sunar. minidom ise başka bir standart kütüphanedir, Belge Nesne Modeli (DOM) tabanlıdır ve büyük belgeler için daha az verimlidir.
XPath ifadeleri nedir ve XML ayrıştırmada nasıl faydalıdır?
XPath ifadeleri, bir XML belgesinden düğüm seçmek için kullanılan sorgu dilleridir. XML belgelerinde öğeler ve öznitelikler arasında gezinmek için kullanışlıdır; hassas veri alma ve işlemeye olanak tanır.
Bir belgeyi ElementTree ile ayrıştırmadan önce XML'i nasıl doğrulayabilirim?
XML belgeleri, XML Şema Tanımı (XSD) veya Belge Türü Tanımı (DTD) kullanılarak doğrulanabilir. Python kütüphaneleri arasında lxml bu standartlara karşı doğrulama için yerleşik destek sunar.
ElementTree kullanarak XML verisini değiştirirken en iyi uygulamalar nelerdir?
En iyi uygulamalar arasında, kazara veri kaybını önlemek için XML verisi üzerinde bir kopya ile çalışmak, kesin gezinme için XPath ifadeleri kullanmak ve tüm değişikliklerin XML belgesinin iyi biçimliliğini koruduğundan emin olmak bulunur.
ElementTree, XML verisini JSON'a dönüştürmek için kullanılabilir mi?
ElementTree doğrudan XML'den JSON'a dönüştürme sağlamaz, ancak ElementTree ile XML verisini bir Python sözlüğüne ayrıştırabilir ve ardından bu sözlüğü Python'un json modülünü kullanarak JSON'a dönüştürebilirsiniz.
ElementTree ile XML ad alanlarını nasıl ele alırsınız?
ElementTree, etikad adlarında {namespace} ön ekini kullanarak XML ad alanlarını ele alabilir. Ayrıca ad alanlarını daha kolay yönetmek için ET.register_namespace() kullanabilirsiniz.
ElementTree'de bir XML ayrıştırma hatasıyla karşılaşırsam ne yapmalıyım?
Bozuk XML, desteklenmeyen kodlamalar veya hatalı dosya yolları gibi yaygın sorunları kontrol edin. Python'un hata yakalama mekanizmalarını (try-except blokları) kullanarak ayrıştırma hatalarını zarifçe teşhis edin ve yönetin.
ElementTree kullanarak bir XML belgesini güzel biçimde yazdırmak mümkün mü?
ElementTree doğrudan güzel yazdırma (pretty-print) sağlamaz, ancak XML dizesini ayrıştırmak için xml.dom.minidom kullanabilir ve ardından okunabilirlik için toprettyxml() yöntemini kullanarak XML'i biçimlendirebilirsiniz.