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
Bağlantıda Kalalım