Uzun zaman önce söz verdiğim bu yazıyı şimdi yazayım dedim. Neyse, lafı uzatmadan başlayalım. Daha önce ElementTree‘nin ne kadar güzel bir XML kitaplığı olduğundan bahsetmiştim. XML yapıları oluşturma konusunda da, ayrıştırma konusunda olduğu kadar pratik ve başarılı. Giriş düzeyinde bahsedeyim.
Şöyle bir veri yığınını XML formatına dönüştürmek istiyorsunuz diyelim ki:
source = "bash" pkgname = "bash" version = "4.2" summary = "The standard GNU Bourne again shell" homepage = "http://tiswww.case.edu/php/chet/bash/bashtop.html" dependency = "ncurses"
Oluşturmak istediğimiz XML formatı da tam olarak şöyle:
<package source="bash">
<name version="4.1_p7">bash</name>
<summary>The standard GNU Bourne again shell</summary>
<homepage>http://tiswww.case.edu/php/chet/bash/bashtop.html</homepage>
<dependencies>
<dependency>ncurses</dependency>
</dependencies>
</package>
Bu işi yapacak Python kodu ise:
import xml.etree.cElementTree as iks
source = "bash"
pkgname = "bash"
version = "4.2"
summary = "The standard GNU Bourne again shell"
homepage = "http://tiswww.case.edu/php/chet/bash/bashtop.html"
dependency = "ncurses"
root = iks.Element("package")
root.set("source", version)
name_tag = iks.SubElement(root, "name")
name_tag.set("version", version)
name_tag.text = pkgname
summary_tag = iks.SubElement(root, "summary")
summary_tag.text = summary
homepage_tag = iks.SubElement(root, "homepage")
homepage_tag.text = homepage
dependencies_tag = iks.SubElement(root, "dependencies")
dependency_tag = iks.SubElement(dependencies_tag, "dependency")
dependency_tag.text = dependency
print(iks.tostring(root))
ElementTree’den bahsederken cElementTree kullanmama dikkat edin. cElementTree, tahmin edebileceğiniz gibi ElementTree’nin C ile gerçeklenmiş hali. Hız açısından her zaman C ile yazılmış modülleri tercih edin. Python 2 serisindeki pickle/cPickle ikilisi de buna bir örnek teşkil ediyor.
Kodu açıklamak istiyorum ama; açıklanacak fazla birşey de göremiyorum. Gayet sade ve anlaşılır. Biraz açıklama yapayım yine de: XML yapısındaki ilk girdiyi(örnekte root yani, “package”) oluşturmak için Element metodunu kullanıyoruz. Daha sonra alt girdiler oluşturmak içinse SubElement metodu devreye giriyor. attribute atamak için set metodu kullanılırken girdilere değer vermek için(doğru bir ifade mi?) text metodunu kullanmak yeterli oluyor. Bu kadar basit bir kodu nasıl açıklayacağımı pek bilemedim gördüğünüz gibi…
Aslında önemli bir nokta var. ElementTree, tüm olumlu özelliklerine rağmen XML dosyaları oluşturmak konusunda biraz sıkıntılı. Yukarıdaki kod bloğunun nasıl çıktı verdiğine bakalım:
<package source="4.2"><name version="4.2">bash</name><summary>The standard GNU Bourne again shell</summary><homepage>http://tiswww.case.edu/php/chet/bash/bashtop.html</homepage><dependencies><dependency>ncurses</dependency></dependencies></package>
Oluşturacağınız XML dosyasını insanlar okuyacaksa çok talihsiz bir çıktı bu. İşin kötüsü; kitaplık, girintileme sorununu çözmek için bir fonksiyon da sağlamıyor. Sorunun çözümü ElementTree’nin internet sitesinde bir yerlerde yatıyor. Aşağıdaki fonksiyonu koda eklediğimizde çıktı başta verdiğim XML yapısı gibi düzgün görünecek.
def indent(elem, level = 0):
i = "\n" + level*" "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
#if not elem.tail or not elem.tail.strip():
# elem.tail = i
for e in elem:
indent(e, level+1)
if not e.tail or not e.tail.strip():
e.tail = i + " "
if not e.tail or not e.tail.strip():
e.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
Çıktıyı ekrana yazdırmadan önce root değişkeni bu fonksiyondan geçmeli. Yani:
..... .. indent(root) print(iks.tostring(root))
Girintilemenin doğru yapıldığını göreceksiniz.
ElementTree’nin benim burada anlattığımdan kat kat fazla yeteneği var. Orjinal dökümantasyonu inceleyerek bolca bilgi edinebilirsiniz. Benimkisi biraz “böyle bir şey de var himm” denilecek türden bir yazı oldu. Ufak bir bilgi notu gibi…