XML(eXtensible Markup Language) Genişletilebilir Biçimlendirme Dili, hiyerarşik bir yapı ile oluşturulmuş , veri depolamayı ve aktarmayı kolaylaştırmayı sağlayan, hem insan hem de makine tarafından kolay okunabilir bir dildir.

Örnek bir XML dosyası formatı şu şekilde olabilir;

<?xml version="1.0" encoding="UTF-8"?>
<urunler kategori="Kırtasiye">
  <urun alt-kategori="Kalemler">
    <urun_adi>Rotring Tikky Versatil Kalem 0,9</urun_adi>
    <fiyat>27,99 TL.</fiyat>
    <aciklama>
      Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor. 
    </aciklama>
  </urun>
  <urun alt-kategori="Silgiler">
    <urun_adi>Faber-Castell 3'lü Büyük Beyaz Silgi</urun_adi>
    <fiyat>12,50 TL.</fiyat>
    <aciklama>
      PVC içermeyen, kalıntı bırakmayan, sınavlarda kullanıma uygun silgi seti.
    </aciklama>
  </urun>
  <urun alt-kategori="Silgiler">
    <urun_adi>Castellini Beyaz Tahta Silgisi</urun_adi>
    <fiyat>35,90 TL.</fiyat>
    <aciklama>
      Sınıflarda beyaz tahtalarda kullanıma uygun, kendinden manyetik yapışkanlı silgi.
    </aciklama>
  </urun>
  <urun alt-kategori="Defterler">
    <urun_adi>Gıpta Prizma Bloknot Kareli 100 Yaprak A4</urun_adi>
    <fiyat>19,90 TL.</fiyat>
    <aciklama>
      Gıpta Prizma Bloknot 
        * 60 Gr Kağıt 
        * Ofset Baskılı 
        * Spiralli Bloknot 
        * A4 - A5 boyutunda 100 yaprak kareli defter.
    </aciklama>
  </urun>
</urunler>

 

XML, web alanının değişmeyen standardı ve bir başka biçimlendirme dili olan HTML(HyperText Markup Language) ile benzerlikler gösterir. Ancak farklı amaçlar için geliştirilmişlerdir;

  • XML veri taşımak için geliştirildiğinden verinin ne olduğuna odaklanır
  • HTML veriyi görüntülemek için geliştirildiğinden verinin nasıl göründüğüne odaklanır
  • Yukarıda gördüğünüz <urun_adi>, <fiyat>, <aciklama> gibi XML etiketleri standart değildir ve dosyayı hazırlayan her kişi kendi etiketlerini oluşturabilir. Ancak <img>, <h1> gibi web sayfalarında kullanabileceğiniz HTML etiketleri her dosya için standart olarak önceden tanımlanmıştır.

XML, yalnızca veriyi taşımak için tasarlanmış bir dil olduğundan dolayı, bu veriyi kullanmak ya da görüntülemek için bir programlama dili kullanarak uygulama yazmalısınız. İşte biz de Python ile bunu nasıl yapabileceğimize değineceğiz.

 

XML Dosyalarını Okumak

Python’da XML dosyaları ile çalışmanızı kolaylaştırmak için ElementTree modülü mevcuttur. Bu modül XML ve benzer diğer yapılandırılmış metinleri okumanızı ve düzenlemenizi sağlar.

XML verileriyle çalışmak için ilk yapmamız gereken ElementTree modülünü eklemektir. Ancak isimlendirmesi uzun olduğu için daha önce modüller konusunda öğrendiğimiz şekilde bir takma ad ile kullanmak mantıklıdır;

import xml.etree.ElementTree as xml

Ben takma ad olarak anlamlı bulduğum için yine xml tercih ettim. Siz dilediğiniz kelimeyi kullanabilirsiniz.

Kod dosyamız ile aynı klasör içinde bulunan veriler.xml dosyasına erişerek içeriğini yine veriler isimli bir değişken de depolamak için;

veriler = xml.parse(“veriler.xml”)

kodunu kullanabiliriz. Burada kullandığımız parse() metodu harici veri dosyalarıyla çalışırken oldukça sık kullanacağımız bir metoddur.

XML ile çalışırken hiyerarşik yapılandırmayı bir ağacın dalları şeklinde düşündüğümüz de, en üst seviye yani kök olarak ifade edilen elemana ulaşmak ile işe başlayabiliriz;

kok = veriler.getroot()
print(kok.tag)

getroot() fonksiyonu ile kök elemanımızı bulup kok olarak isimlendirdiğim değişkene depoladıktan sonra, ElementTree modülünün metodlarıyula gerekli bilgileri edinebiliriz. Örneğin yukarıda kok.tag ile kök elemanın etiketinin XML dokümanını hazırlayan kişi tarafından nasıl isimlendirildiğini öğreniyoruz. kok.attrib metodu ile de bu kök elemanın herhangi bir açıklayıcı parametresi olup olmadığını öğrenebiliriz;

print(kok.attrib)

Eğer tüm XML dokümanını varolduğu biçimiyle görüntülemek isterseniz tostring() metoduyla metne çevirip ekrana yazdırabilirsiniz. Şimdi buraya kadar öğrendiğimiz kodlar ile XML dokümanını metin olarak görüntüleme işlemini beraber gerçekleştirip, nasıl çalıştığını görelim;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()
print(kok.tag)
# Parametresi var mı diye bakalım
print(kok.attrib)
print()

# XML dosyasını görüntüleyelim
print(xml.tostring(kok, encoding='utf8').decode('utf8'))
print()

Çıktı:

urunler
{'kategori': 'Kırtasiye'}

<?xml version='1.0' encoding='utf8'?>
<urunler kategori="Kırtasiye">
  <urun alt-kategori="Kalemler">
    <urun_adi>Rotring Tikky Versatil Kalem 0,9</urun_adi>
    <fiyat>27,99 TL.</fiyat>
    <aciklama>
      Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor. 
    </aciklama>
  </urun>
  <urun alt-kategori="Silgiler">
    <urun_adi>Faber-Castell 3'lü Büyük Beyaz Silgi</urun_adi>
    <fiyat>12,50 TL.</fiyat>
    <aciklama>
      PVC içermeyen, kalıntı bırakmayan, sınavlarda kullanıma uygun silgi seti.
    </aciklama>
  </urun>
  <urun alt-kategori="Defterler">
    <urun_adi>Gıpta Prizma Bloknot Kareli 100 Yaprak A4</urun_adi>
    <fiyat>19,90 TL.</fiyat>
    <aciklama>
      Gıpta Prizma Bloknot 
        * 60 Gr Kağıt 
        * Ofset Baskılı 
        * Spiralli Bloknot 
        * A4 - A5 boyutunda 100 yaprak kareli defter.
    </aciklama>
  </urun>
</urunler>

 

Burada en üst seviye ynai kök elemanın etiket adını tag() metoduyla ve kullandığı parametreleri attrib() metoduyla elde etmiştik. Daha alt seviyedeki dalların yani elemanların benzer bilgilerini de bir döngü kurarak elde edebiliriz;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Alt seviye XML etiketleri neler bulalım
for altseviye in kok:
  print(altseviye.tag,altseviye.attrib)
print()

Çıktı:

urun {'alt-kategori': 'Kalemler'}
urun {'alt-kategori': 'Silgiler'}
urun {'alt-kategori': 'Defterler'}

Gördüğünüz gibi kök elemanın alt seviyesinde urun olarak isimlendirilmiş bir alt seviye elemanlar mevcut ve bu elemanların aldıkları parametrelerden bir kırtasiye marketinin alt kategorilerine ait ürünler oldukları anlaşılıyor. Yukarıda da kök elemanın parametresi olan {‘kategori’: ‘Kırtasiye’} bize ürünler isimli üst elemanımızın ana kategorisinin ne olduğunu vermişti.

Eğer, tüm XML dosyasına açıp göz atmasak bile edindiğimiz bilgiler ışığında bu XML dosyasını oluşturan kişinin bir e-ticaret sitesinde yer alan ürünler ile ilgili bilgileri XML dosyası olarak tutup paylaştığını ve elimizdeki verilerin Kırtasiye kategorisinin alt kategorileri olan Kalemler, Silgiler ve Defterler kategorilerine ait ürünlerin bilgileri olduğunu söyleyebiliriz.

Öyleyse şimdi de XML dosyasında bu ürünler ile ilgili hangi bilgilerin yer aldığını öğrenelim;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Tüm alt seviye XML etiketlerini öğrenelim
for altseviyeler in kok.iter():
  print(altseviyeler.tag,altseviyeler.attrib)
print()

Çıktı:

urunler {'kategori': 'Kırtasiye'}
urun {'alt-kategori': 'Kalemler'}
urun_adi {}
fiyat {}
aciklama {}
urun {'alt-kategori': 'Silgiler'}
urun_adi {}
fiyat {}
aciklama {}
urun {'alt-kategori': 'Defterler'}
urun_adi {}
fiyat {}
aciklama {}

 

Burada kullandığımız iter() metodu bize en üst seviyeden başlamak üzere en alt seviyeye kadar ağacın hiyerarşik olarak tüm dallarına ulaşarak yardımcı oluyor.

Kod çıktısı girintiye sahip olmadığı için bize hiyerarşi olarak estetik görünmüyor ama tekrar eden örüntüyü gördüğümüz için XML dosyasından elde edebileceğimiz bilgileri biliyoruz. Bizim örneğimizde sizin de fark ettiğiniz üzere XML dosyası ürün adını, fiyatını ve açıklama metnini içeriyor. Şimdi bu bilgilere nasıl ulaşabileceğimizi görelim;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Belirli bir seviyeden bilgi edinelim
for urun in kok.iter("urun_adi"):
  print(urun.text)

Çıktı:

Rotring Tikky Versatil Kalem 0,9
Faber-Castell 3'lü Büyük Beyaz Silgi
Gıpta Prizma Bloknot Kareli 100 Yaprak A4

Yine iterasyon ile en alt seviyelere kadar ulaşılabilmesini sağlayan iter() metodunu kullanıyor ve bu kez parametre olarak ilgilendiğimiz bilgiye ait olan etiketi veriyoruz. Bu etiketin içeriğine de text() metodunu kullanarak ulaşıyoruz.

Buraya kadar edindiğimiz bilgileri daha önceki bilgilerimiz ile birlilkte kullanarak daha kompleks işlerin de üstesinden gelebiliriz. Örneğin attrib() metodunun bize elemanların parametrelerini sözlük formatında verdiğini, geçmiş konulardan sözlük verilerinde values() metodu ile sadece değerleri alabildiğimizi biliyoruz. Bu bilgileri döngüler ve koşullu ifadeler ile birlştirerek belirli bir kategorideki ürünlerin adlarını bulabiliriz;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Belirli bir kategorideki ürünlerin adını bulmak
for altseviye in kok:
  for altkategori in altseviye.attrib.values():
    if altkategori == "Silgiler":
      for urun in altseviye.iter("urun_adi"):
        print(urun.text)

Çıktı:

Faber-Castell 3'lü Büyük Beyaz Silgi
Castellini Beyaz Tahta Silgisi

 

Ya da tüm verileri okunabilir formatta elde edebiliriz;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Belirli bir kategorideki ürün bilgilerini almak
for altseviye in kok:
  for altkategori in altseviye.attrib.values():
    if altkategori == "Silgiler":
      for urundegiskenleri in ["urun_adi","fiyat","aciklama"]:
        for urunbilgileri in altseviye.iter(urundegiskenleri):
          print(urunbilgileri.text)

Çıktı:

Faber-Castell 3'lü Büyük Beyaz Silgi
12,50 TL.

   PVC içermeyen, kalıntı bırakmayan, sınavlarda kullanıma uygun silgi seti.


Castellini Beyaz Tahta Silgisi
35,90 TL.

   Sınıflarda beyaz tahtalarda kullanıma uygun, kendinden manyetik yapışkanlı silgi.

 

Filtreleme olmaksızın tüm verileri ekrana yazdırmak için de yine bir döngü kurabiliriz;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Tüm verileri ekrana yazdırmak
i = 0
while i < len(kok):
  for urun in kok[i]:
    print(urun.text)
  i += 1

Çıktı:

Rotring Tikky Versatil Kalem 0,9
27,99 TL.

  Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor. 

Faber-Castell 3'lü Büyük Beyaz Silgi
12,50 TL.

  PVC içermeyen, kalıntı bırakmayan, sınavlarda kullanıma uygun silgi seti.

Castellini Beyaz Tahta Silgisi
35,90 TL.

  Sınıflarda beyaz tahtalarda kullanıma uygun, kendinden manyetik yapışkanlı silgi.

Gıpta Prizma Bloknot Kareli 100 Yaprak A4
19,90 TL.

  Gıpta Prizma Bloknot 
    * 60 Gr Kağıt 
    * Ofset Baskılı 
    * Spiralli Bloknot 
    * A4 - A5 boyutunda 100 yaprak kareli defter.

Burada da XML verilerinin kaç adet olduğunu len() fonksiyonu yardımıyla tespit ettiğimize dikkat etmişsinizdir.

Belirli bir eleman hakkında bilgi edinmek istediğimizde ElementTree modülü find() ve findall() metodları ile yardımcı olur.

Arama metodları ile tüm verilere ulaşalım ve sadece istediğimiz verileri ekrana yazdıralım;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Tüm verilerden istediklerimizi ekrana yazdırmak
for urunlerimiz in kok.findall("urun"):
  ad = urunlerimiz.find('urun_adi').text
  fiyat = urunlerimiz.find('fiyat').text
  print("Ürün Adı: ",ad,"-","Ürün Fiyatı: ",fiyat)

Çıktı:

Ürün Adı: Rotring Tikky Versatil Kalem 0,9 - Ürün Fiyatı: 27,99 TL.
Ürün Adı: Faber-Castell 3'lü Büyük Beyaz Silgi - Ürün Fiyatı: 12,50 TL.
Ürün Adı: Castellini Beyaz Tahta Silgisi - Ürün Fiyatı: 35,90 TL.
Ürün Adı: Gıpta Prizma Bloknot Kareli 100 Yaprak A4 - Ürün Fiyatı: 19,90 TL.

Örneğin XML verimizde bir ürünün adını biliyorken ait olduğu kategoriyi bulmak için;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Arama yaparak bir verinin içinde bulunduğu üst elemanın parametresini bulmak
for urun in kok.findall("./urun/[urun_adi='Gıpta Prizma Bloknot Kareli 100 Yaprak A4']"):
  print("Sonuç: ",urun.attrib)

Çıktı:

Sonuç: {'alt-kategori': 'Defterler'}

Bir başka örnek daha yapalım ve XML verimizde bir ürünün adını biliyorken fiyatını bulalım;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Adını bildiğimiz elemanın istediğimiz verisine ulaşmak
for urun in kok.findall("./urun/[urun_adi='Gıpta Prizma Bloknot Kareli 100 Yaprak A4']"):
  print("Ürün Fiyatı: ",urun[1].text)

Çıktı:

Ürün Fiyatı: 19,90 TL.

 

XML Dosyalarını Düzenlemek

XML dosyalarında bir veriyi güncellemek için tıpkı değişkenlere yeni değer atama işleminde yaptığımız şekilde yukarıdaki yöntemlerle veriye erişişr ve yeni değeri atamak yoluyla güncelleriz. Tabii bir dosya içindeki veriyi güncellemek istediğimiz için yeni veriyi atadıktan sonra dosyayı da kaydetmeyi unutmamalıyız.

Örnek bir uygulama için yukarıda kullandığımız XML dosyasında bir ürünün fiyatını değiştirelim. XML verileri metin bazlı dosya formatına sahip oldukları için verileri de metin olarak atamanız gerektiğini unutmayın.

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

for urunlerimiz in kok.findall("urun"):
  if urunlerimiz.find('urun_adi').text == "Castellini Beyaz Tahta Silgisi":
     urunlerimiz.find('fiyat').text="40,90 TL."
    # Yeni verilerimiz ile XML dosyasını güncelliyoruz.
     veriler.write("veriler.xml",encoding="UTF-8")

Çıktı:

<urun alt-kategori="Silgiler">
  <urun_adi>Castellini Beyaz Tahta Silgisi</urun_adi>
  <fiyat>40,90 TL.</fiyat>
  <aciklama>
    Sınıflarda beyaz tahtalarda kullanıma uygun, kendinden manyetik yapışkanlı silgi.
  </aciklama>
</urun>

Bu konuda gerçek hayata daha yakın bir uygulama da fiyatları matematiksel olarak işlemek olabilir. Çünkü gerçek hayatta uygulamalarınızda ürünlerin satış fiyatları üzerinden belirli bir yüzde oranında indirim ya da artış yapmanız istenebileceği gibi, alış fiyatlarında değişim olduğunda fiyatları X TL. artıralım gibi bir görev alabilirsiniz. Böyle zamanlarda metin bazlı XML dosyasındaki rakamları sayısal formata çevirip işlem yapmanız gerekecektir. Esasında tüm fiyat verisini çekip, sayısala çevirip, işlem gerçekleştirdikten sonra güncel fiyatları kaydetmeye dayalı bir yol izlenebilir. Biz bunun küçük ve basit bir örneğini yaparak biraz önce direkt metin olarak yaptığımız değişikliği şimdi de sayısal olarak yaparak ürün fiyatını 5 TL. artıralım;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

for urunlerimiz in kok.findall("urun"):
  if urunlerimiz.find('urun_adi').text == "Castellini Beyaz Tahta Silgisi":
  # Eski fiyatı ondalık sayıya çevirip matematiksel olarak fiyatı değiştirmek
    # Ürünün mevcut fiyatını eskifiyat isimli bir değişkene depoluyoruz
    eskifiyat=urunlerimiz.find('fiyat').text
    # Bu fiyat metin olduğundan rakam kısmını almak için TL. kısmını ayırıyoruz
    eskifiyat=eskifiyat.split(' ')
    # Rakam kısmından ondalık virgülünü ayırıyoruz 
    eskiondalik=eskifiyat[0].split(",")
    # Elimizdeki tam ve ondalık kısımlardan arasına nokta ekleyerek yeni bir ondalık sayı oluşturuyoruz.
    eskifiyat=float(eskiondalik[0]+"."+eskiondalik[1])
    # Artık matematiksel işlem yapabiliriz. Fiyatı 5 TL. artırıyoruz.
    yenifiyat=eskifiyat+5
    # yenifiyat değişkenini tekrar metin formatına çeviriyoruz ki nokta yerine virgül ve TL. ifadesini ekleyebilelim
    yenifiyat=str(yenifiyat)
    # yenifiyat metninden ondalık noktasını ayırıyoruz 
    yeniondalik=yenifiyat.split(".")
    # Metin formatında Türkçe ondalık sayı oluşturmak için virgül ve TL. ifadelerini ekliyoruz.
    yenifiyat=yeniondalik[0]+","+yeniondalik[1]+"0 TL."
    # Ürünün fiyatına yenifiyat değerini aktarıyoruz.
    urunlerimiz.find('fiyat').text=yenifiyat
    # Ürünün fiyatını güncellediğimiz tarihi parametre olarak ekleyebiliriz
    urunlerimiz.find('fiyat').set("guncelleme_tarihi","01.01.2021")
    # Yeni verilerimiz ile XML dosyasını güncelliyoruz.
    veriler.write("veriler.xml",encoding="UTF-8")

Çıktı:

<urun alt-kategori="Silgiler">
  <urun_adi>Castellini Beyaz Tahta Silgisi</urun_adi>
  <fiyat guncelleme_tarihi="01.01.2021">40,90 TL.</fiyat>
  <aciklama>
    Sınıflarda beyaz tahtalarda kullanıma uygun, kendinden manyetik yapışkanlı silgi.
  </aciklama>
</urun>

Burada ek bir veri olarak set() metodu yardımıyla fiyatı güncellediğimiz tarihi XML dosyasının <fiyat> etiketi içine yerleştirdiğimize de dikkat ediniz. Bu mantıksal olarak bu tür görevlerde fiyatın son güncellenme tarihini vererek fayda sağlayabileceği gibi, bize de aynı zamanda bir XML dosyası içindeki elemana ait etiket içine set() metodu ile parametre eklemeyi öğretiyor.

Peki, bir etiket içine parametre değil de, yeni bir XML etiketi eklemek istersek nasıl yapacağız? Bu işlem için de SubElement() metodunu kullanacağız;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

# Eleman eklemek
for stokverisi in kok.findall("urun"):
  stok = xml.SubElement(stokverisi, "stok")
  stok.text="12"

veriler.write("veriler.xml",encoding="UTF-8")

Her bir ürünümüze yeni bir stok etiketi ekleyip, başlangıç stok adedini bir düzine olacak şekilde belirledik. İşlemin doğru gerçekleşip gerçekleşmediğini görmek için XML dosyasına göz atabilir ya da daha önce öğrendiğimiz yöntemlerle Python kodu yazıp stok verisini çekerek ekrana yazdırabilirsiniz. Örneğin yukarıdaki koda şu kodu eklersek;

for urunlerimiz in kok.findall("urun"):
  ad = urunlerimiz.find('urun_adi').text
  fiyat = urunlerimiz.find('fiyat').text
  stok = urunlerimiz.find("stok").text
  print("Ürün Adı: ",ad,"-","Stok Adedi:", stok,"-","Ürün Fiyatı: ",fiyat)
Çıktı:

Ürün Adı: Rotring Tikky Versatil Kalem 0,9 - Stok Adedi: 12 - Ürün Fiyatı: 27,99 TL.
Ürün Adı: Faber-Castell 3'lü Büyük Beyaz Silgi - Stok Adedi: 12 - Ürün Fiyatı: 12,50 TL.
Ürün Adı: Castellini Beyaz Tahta Silgisi - Stok Adedi: 12 - Ürün Fiyatı: 40,90 TL.
Ürün Adı: Gıpta Prizma Bloknot Kareli 100 Yaprak A4 - Stok Adedi: 12 - Ürün Fiyatı: 19,90 TL.

 

XML dosyalarında okuma, veri ekleme gibi işlemleri öğrendiğimize göre sıra son işlemimizi öğrenmeye geliyor; veri silme…

Öncelikle örnek olması için yukarıda set() metoduyla eklediğimiz parametreyi kaldırmayı, dolayısıyla XML dosyasından parametre silme işlemini görelim. Parametrelere attrib() metoduyla erişebildiğimizi biliyoruz. Parametreyi kaldırma işlemini de tıpkı listelerse olduğu gibi pop() metoduyla gerçekleştireceğiz;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

guncellemetarihinibul = kok.find("./urun/fiyat[@guncelleme_tarihi='01.01.2021']")
guncellemetarihinibul.attrib.pop("guncelleme_tarihi", None)
veriler.write("veriler.xml",encoding="UTF-8")

Sonuç olarak XML dokümanınıza göz attığınızda daha önce oluşturduğumuz parametre silinmiş olur;

<urun alt-kategori="Silgiler">
  <urun_adi>Castellini Beyaz Tahta Silgisi</urun_adi>
  <fiyat>40,90 TL.</fiyat>
  <aciklama>
    Sınıflarda beyaz tahtalarda kullanıma uygun, kendinden manyetik yapışkanlı silgi.
  </aciklama>
</urun>

Peki parametreyi değil de XML etiketinin tamamını silmek istersek bunu nasıl yaparız? Daha önce stok isimli bir parametre oluşturmuştuk. Önceki örneklerimizden de findall() metodu ile XML etiketlerine nasıl erişebileceğimizi biliyoruz. Tek yapmamız gereken bu bilgiye remove() metodunu ve parametre olarak da tıpkı listelerde olduğu gibi silmek istediğimiz etiketin sıra numarasını vermek yeterli;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

for urun in kok.findall("./urun/[urun_adi='Gıpta Prizma Bloknot Kareli 100 Yaprak A4']"):
  urun.remove(urun[3])
veriler.write("veriler.xml",encoding="UTF-8")

Çıktı:

<urun alt-kategori="Defterler">
  <urun_adi>Gıpta Prizma Bloknot Kareli 100 Yaprak A4</urun_adi>
  <fiyat>19,90 TL.</fiyat>
  <aciklama>
    Gıpta Prizma Bloknot 
      * 60 Gr Kağıt 
      * Ofset Baskılı 
      * Spiralli Bloknot 
      * A4 - A5 boyutunda 100 yaprak kareli defter.
  </aciklama>
</urun>

Gördüğünüz gibi bulduğumuz kaydın 3.(listelerde sıralamanın 0’dan başladığını hatırlayınız) sırasında yer alan <stok> etiketi silinmiş oldu.

Eğer bir etiketin tüm alt etiketlerini silmek istersek da clear() metodunu kullanırız;

import xml.etree.ElementTree as xml

# Dosyaya erişelim ve biçimlendirmesini parse() metoduyla ele alalım
veriler = xml.parse("veriler.xml")

# En üst seviye XML etiketinin ne olduğunu bulalım
kok = veriler.getroot()

for urun in kok.findall("./urun/[urun_adi='Rotring Tikky Versatil Kalem 0,9']"):
  urun.clear()
veriler.write("veriler.xml",encoding="UTF-8")

 

XML Dosyası Oluşturmak

Harici bir XML dosyasını olkumayı ve üzerinde değişiklikler yaparak çalışmayı öğrendik. Ancak bazı durumlarda biz de projelerimizde veri alışverişi yapmak için XML dosyası oluşturmayı düşünebiliriz. Bu  durumda çalıştığımız verileri XML formatında nasıl kaydedebileceğimizi görelim.

Daha öncede olduğu gibi ElementTree modülünden faydalanabiliriz. Daha önce XML etiketimizin içinde bir alt etiket oluşturmak için SubElement() metodunu kullanmıştık. Benzer şekilde Element() metodu da yeni XML etiketleri oluşturmamıza yardımcı olur. Dilerseniz üst seviye etiketleri Element() metodu onun içine yerleştireceğiniz alt seviye etiketleri ise SubElement() metoduyla oluşturabilirsiniz. Ya da sadece Element() metoduyla iç içe yuvalanacağı seviyeyi belirterek bunu gerçekleştirebilirsiniz.

Verilerimizi dosyamıza belirli bir hiyerarşik formatta ve yapı içerisinde kaydedeceğimize göre, aldığımız verileri bu formatta konumlandıracak bir fonksiyona ihtiyacımız var demektir.

Örnek olarak daha önce çalıştığımıza benzer şekilde bir ürün verisi için XML yapısı oluşturmaya çalışalım.

import xml.etree.ElementTree as xml

# XML dosyasını oluşturacak olan fonksiyonu tanımlayalım
def xmlolustur(dosyaadi,ad,fyt,ack):
  # Önce kök etiketimizi oluşturmalıyız
  kok = xml.Element("urunler")

  # Kök etiketin içine alt seviye etiketimizi yerleştirelim
  altseviye = xml.Element("urun")
  kok.append(altseviye)

  # Alt seviyenin içine yeni etiketler oluşturalım
  urunadi = xml.Element("urun_adi")
  altseviye.append(urunadi)
  fiyat = xml.Element("fiyat")
  altseviye.append(fiyat)
  aciklama = xml.Element("aciklama")
  altseviye.append(aciklama)

  # Parametrelerden gelen verilerin nereye yerleştirileceğini belirleyelim
  urunadi.text=ad
  fiyat.text=fyt
  aciklama.text=ack

  xmlyapisi = xml.ElementTree(kok)

  with open(dosyaadi,"wb") as dosyam:
    xmlyapisi.write(dosyam, encoding="UTF-8", xml_declaration=True)

Fonksiyonumuza xmlolustur() adını verdik ve dosyaya yazma işlemini de gördüğünüz gibi with..as bağlam yöneticisi ile ve open() metoduyla fonksiyon içinde hallettiğimiz için ilk parametre olarak bu dosyanın alacağı ismi kullandık. Diğer parametreler ise fonksiyon içinde uygun konumlara yerleştirmek için fonksiyonu kullanırken göndereceğimiz ürün verileri olarak tanımlandı. Bildiğiniz gibi ürün verilerimiz, ürün adı, fiyatı ve ürün bilgilerinden oluşacak.

En üst seviyedeki kök etiketimizi Element() metoduyla oluşturduktan sonra, onun içine yerleşecek olan etiketi bu kök etiketini atadığımız değişkeni referans alarak oluşturuyoruz. Bu durumda SubElement() yerine yine Element() metodunu kullanmamızın bir sakıncası yok.

Örneğimize göre bir sonraki seviye verilerin yer aldığı etiketlerin seviyesidir. Bu etiketleri de alt seviye etiketi referans alarak aynı şekilde oluşturuyoruz.

Parametrelerden gelen verileri de bu etiketlerin içinde yer alacak şekilde yerleştiriyoruz.

Artık XML yapısını oluşturmaya hazırız. ElementTree() metoduna parametre olarak en üst seviye etiketi veriyoruz.

Son olarak yapmamız gereken oluşturduğumuz bu yapıyı bir dosyaya kaydetmek. Bunun için daha önce dosyalarla çalışma konusunda öğrendiğimzi şekilde with..as bağlam yöneticisi yardımıyla open() fonksiyonunu kullanarak bir dosya oluşturuyoruz. Bu dosyayı “wb” binary modunda yazma yetkisiyle oluşturuyoruz ve dosyamız içinde Türkçe karakterler kullandığımız için mutlaka encoding=”UTF-8″ formatında oluşturulması gerektiğini ekliyoruz. xml_declaration=True parametresi ise XML dosyalarının en üstünde yer alan ve dosyanın türünü belirleyen <?xml version=’1.0′ encoding=’UTF-8′?> satırının eklenmesini sağlıyor.

Artık tek yapmamız gereken uygulamamız içinde veri oluşturmak ve bu fonksiyona parametre olarak atayarak fonksiyonu çağırıp çalıştırmaktır. Böylece XML dosyası kodumuz ile aynı klasör içinde oluşturulacaktır.

import xml.etree.ElementTree as xml

# XML dosyasını oluşturacak olan fonksiyonu tanımlayalım
def xmlolustur(dosyaadi,ad,fyt,ack):
  # Önce kök etiketimizi oluşturmalıyız
  kok = xml.Element("urunler")

  # Kök etiketin içine alt seviye etiketimizi yerleştirelim
  altseviye = xml.Element("urun")
  kok.append(altseviye)

  # Alt seviyenin içine yeni etiketler oluşturalım
  urunadi = xml.Element("urun_adi")
  fiyat = xml.Element("fiyat")
  aciklama = xml.Element("aciklama")

  altseviye.append(urunadi)
  altseviye.append(fiyat)
  altseviye.append(aciklama)

  urunadi.text=ad
  fiyat.text=fyt
  aciklama.text=ack

  xmlyapisi = xml.ElementTree(kok)

  with open(dosyaadi,"wb") as dosyam:
    xmlyapisi.write(dosyam, encoding="UTF-8", xml_declaration=True)

urun1_ad = "Rotring Tikky Versatil Kalem 0,9"
urun1_fyt = "27,99 TL."
urun1_ack = "Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor."

xmlolustur("yenixml.xml",urun1_ad,urun1_fyt,urun1_ack)

Çıktı:

<?xml version='1.0' encoding='UTF-8'?>
<urunler><urun><urun_adi>Rotring Tikky Versatil Kalem 0,9</urun_adi><fiyat>27,99 TL.</fiyat><aciklama>Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor.</aciklama></urun></urunler>

Gördüğünüz gibi dosyamız istediğimiz formatta oluşturuldu. Dilerseniz bu şekilde de kullanabilirsiniz. Örneği anlaşılabilir olması bakımından basit tutmak adına tek bir ürün verisiyle oluşturduk, ama siz isterseniz kullanıcının veri girişiyle oluşturulan verileri listeler ya da sözlükler halinde tutarak fonksiyona gönderip daha çok veri içeren bir XML dosyası oluşturabilirsiniz. Ancak bu daha önceki bilgileriniz ile çözebileceğiniz bir işlem olduğu için burada yer vermeye gerek görmedik. Mevcut bilginize yenisini ekleyebileceğiniz bir örnekle yetindik. Dilerseniz yukarıdaki konu başlıklarında öğrendiğiniz şekilde etiketlerin içine parametreler de ekleyebilirsiniz.

Eğer oluşturduğunuz XML dosyasının hiyerarşik olarak girintili bir şekilde daha okunabilir bir görünüm ile oluşturulmasını isterseniz, bunu toprettyxml() metoduyla gerçekleştirebilirsiniz;

import xml.etree.ElementTree as xml
from xml.dom import minidom

# XML dosyasını oluşturacak olan fonksiyonu tanımlayalım
def xmlolustur(dosyaadi,ad,fyt,ack):
  # Önce kök etiketimizi oluşturmalıyız
  kok = xml.Element("urunler")

  # Kök etiketin içine alt seviye etiketimizi yerleştirelim
  altseviye = xml.Element("urun")
  kok.append(altseviye)

  # Alt seviyenin içine yeni etiketler oluşturalım
  urunadi = xml.Element("urun_adi")
  fiyat = xml.Element("fiyat")
  aciklama = xml.Element("aciklama")

  altseviye.append(urunadi)
  altseviye.append(fiyat)
  altseviye.append(aciklama)

  urunadi.text=ad
  fiyat.text=fyt
  aciklama.text=ack

  # XML'in okunabilir formatta kaydedilmesi için
  metnecevir = xml.tostring(kok)
  agacgorunumu = minidom.parseString(metnecevir)
  okunurxml = agacgorunumu.toprettyxml(encoding="UTF-8")

  with open("okunurxml.xml","wb") as dosyam:
    dosyam.write(okunurxml)

urun1_ad = "Rotring Tikky Versatil Kalem 0,9"
urun1_fyt = "27,99 TL."
urun1_ack = "Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor."

xmlolustur("yenixml.xml",urun1_ad,urun1_fyt,urun1_ack)

Çıktı:

<?xml version="1.0" encoding="UTF-8"?>
<urunler>
    <urun>
        <urun_adi>Rotring Tikky Versatil Kalem 0,9</urun_adi>
        <fiyat>27,99 TL.</fiyat>
        <aciklama>Yazım ve çizim yapmak için son derece uygun bir model olan Rotring Tikky 1904507 Mekanik Kurşun Kalem 0.9 mm, başta öğrenciler olmak üzere sık kalem kullanımı yapan kişilere hitap ediyor.</aciklama>
    </urun>
</urunler>

Bu insan tarafından daha rahat şekilde okunabilir görünümü elde etmek için ihtiyaç duyduğumuz metodları kullanabilmek için dom modülünden minidom eklemek amacıyla from xml.dom import minidom satırını eklediğimize dikkat ediniz lütfen.

 

XML dosyalarıyla çalışırken Python ile okuma,düzenleme ve yazma işlemleriyle her türlü işlemi gerçekleştirebilirsiniz. Ayrıca XML ve XPath ile ilgili bilgilerinizi geliştirerek yapabileceğiniz işlemleri daha kolay kavrayabilirsiniz.

ElementTree modülü XML yapısını çok boyutlu listeler gibi kullanmanızı sağlar. Zaten örneklerimizin bazı yerlerinde kullandığımız urun[3] şeklinde verilere erişmemizden bunu fark etmiş olmalısınız. Ayrıca yine örneklerimizde gördüğünüz gibi etiketleri de birer sözlük gibi sunar. Böylece XML etiketlerinin parametreleriyle işlem yapmamızı kolaylaştırır. Eğer ElementTree modülünü detaylı inceleyecek olursanız burada bahsettiklerimizin üzerine yeni bir bakış açısı kazanabilirsiniz. Bu modül Python’da XML dosyaları ile çalışmamızı oldukça kolaylaştırır.

Ancak burada yer alan örneklerimizde XML dosyasını okumak için kullandığımız parse() metodunu küçük boyutlu XML dosyalarıyla çalışırken kullanmanızı tavsiye ederim. Çünkü bu metod tüm dosyayı tek seferde okur ve hafızaya alır. Bu nedenle büyük XML dosyalarıyla çalışırken parse() metodunu kullanırsanız RAM tüketiminiz yüksek, uygulama performansınız düşük olur. Büyük dosyalarda iterparse() metodu ile çalışmalısınız.

Ya da harici bir modül olan lxml‘den faydalanabilirsiniz. Bu modül ElementTree’den daha fazla esneklik ve kullanım şekli sağlamakla birlikte HTML dokümanları ile çalışmanızı dolayısıyla web sayfalarından veri elde etmenizi de sağlar.

 

Burada yer alan örneklere şu adreste göz atabilirsiniz;

https://repl.it/@ObenSEVEN/xml

 

Detaylı bilgi için; ElementTree | MiniDom