14. Belge işleme XML
![]() |
Aşağıdaki XML belgesini ele alalım:
<tribu>
<enseignant>
<personne sexe="M">
<nom>dupont</nom>
<prenom>jean</prenom>
<age>28</age>
ceci est un commentaire
</personne>
<section>27</section>
</enseignant>
<etudiant>
<personne sexe="F">
<nom>martin</nom>
<prenom>charline</prenom>
<age>22</age>
</personne>
<formation>dess IAIE</formation>
</etudiant>
</tribu>
Bu belgeyi analiz ederek aşağıdaki konsol çıktısını elde ediyoruz:
tribu
enseignant
(personne,(sexe,M) )
nom
[dupont]
/nom
prenom
[jean]
/prenom
age
[28]
/age
/personne
section
[27]
/section
/enseignant
etudiant
(personne,(sexe,F) )
nom
[martin]
/nom
prenom
[charline]
/prenom
age
[22]
/age
/personne
formation
[dess IAIE]
/formation
/etudiant
/tribu
Şunları nasıl tanıyacağımızı bilmeliyiz:
- <eğitim> gibi bir başlangıç etiketini;
- </enseignant> gibi bir bitiş etiketini;
- <personne sexe="F"> gibi öznitelikli bir başlangıç etiketini;
- martin gibi bir etiket gövdesi (<nom>martin</nom>. içinde)
XML kodunu analiz eden programa XML ayrıştırıcısı denir. XML kodunu ayrıştırmak için gerekli işlevleri bize iki modül sağlar: xml.sax ve xml.sax.handler.
[xml.sax] modülü, şu komut aracılığıyla bize bir XML ayrıştırıcısı sağlar:
Bu ayrıştırıcı, XML metnini sırayla analiz eder. Aşağıdaki olaylarda kullanıcı yöntemlerini çağırır:
- etiket başlangıcında startElement yöntemi;
- etiket sonu durumunda endElement yöntemi;
- characters yöntemi, bir etiket gövdesi üzerinde.
Ayrıştırıcıya, bu yöntemleri uygulayan sınıfı belirtmemiz gerekir:
Ayrıştırıcının setContentHandler yöntemine, startElement, endElement ve characters yöntemlerini uygulayan bir sınıf örneği aktarıyoruz. Kullanılan sınıf, xml.sax.handler.ContentHandler sınıfından türetilmiş bir sınıftır. Yukarıdaki yöntemler aşağıdaki parametrelerle çağrılır:
- name, başlangıç etiketinin adıdır. attributs ise etiketin öznitelik sözlüğüdür. Dolayısıyla, <personne sexe="M"> etiketi için name="personne" ve attributs={'sexe':'M'} değerleri elde edilir.
- name, bitiş etiketinin adıdır. Dolayısıyla, </etudiant> etiketi için name='etudiant' olacaktır.
- data, etiket gövdesidir. Dolayısıyla, etiket
data='\r\n dupont\r\n ' elde ederiz. Genellikle, verinin başındaki ve sonundaki boşluklar kaldırılır.
Bunu açıkladıktan sonra, XML formatındaki bir belgeyi analiz eden komut dosyasına geçebiliriz:
# -*- coding=utf-8 -*-
import xml.sax, xml.sax.handler,re
# yönetim sınıfı XML
class XmlHandler(xml.sax.handler.ContentHandler):
# başlangıç etiketiyle karşılaşıldığında çağrılan işlev
def startElement(self,name,attributs):
global depth
# bir dizi boşluk (girinti)
print " " * depth,
# öznitelikler
precisions=""
for (attrib,valeur) in attributs.items():
precisions+="(%s,%s) " % (attrib,valeur)
# etiket adı ve varsa öznitelikler görüntülenir
if precisions :
print "(%s,%s)" % (name,precisions)
else :
print name
# bir üst düzey daha
depth+=1
# bu bir veri etiketi mi?
global balisesDonnees,baliseDeDonnees
if balisesDonnees.has_key(name.lower()):
baliseDeDonnees=1
# son etiketine rastlandığında çağrılan işlev
def endElement(self,name):
# etiket sonu
# girinti düzeyi
global depth
depth-=1
# bir dizi boşluk (girinti)
print " " * depth,
# etiket adı
print "/%s" % (name)
# veri görüntüleme işlevi
def characters(self,data):
# veriler
global baliseDeDonnees
# geçerli etiket bir veri etiketi mi?
if not baliseDeDonnees :
return
# girinti düzeyi
global depth
# bir dizi boşluk (girinti)
print " " * depth,
# veriler görüntüleniyor
match=re.match(r"^\s*(.*)\s*$",data)
if match:
print "[%s]" % (match.groups()[0])
# veri etiketinin sonu
baliseDeDonnees=False
# ------------------------------------------- ana
# program
# veriler
file="data.xml" # xml dosyası
depth=0 # girinti seviyesi=ağaç yapısındaki derinlik
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # "true" ise, bir veri etiketiyle karşı karşıya olduğumuzu gösterir
# bir XML metin analiz nesnesi oluşturulur
xml_parser=xml.sax.make_parser()
# etiket yöneticisi
xml_parser.setContentHandler(XmlHandler())
# XML dosyasının işlenmesi
xml_parser.parse(file)
Notlar:
- komut dosyası, xml.sax ve xml.sax.handler modüllerinin işlev kütüphanesini kullanır (3. satır);
-
- satır: analiz edilen XML dosyası;
-
- satır: XML ayrıştırıcısı;
- satır 70: ayrıştırıcı tarafından gönderilen olayların yöneticisi, XmlHandler sınıfının bir örneği olacaktır;
- satır 72: XML belgesinin analizi başlatılır;
-
- satır: startElement, endElement ve characters yöntemlerini uygulayan sınıf. Bu sınıf, ayrıştırıcı tarafından kullanılan yöntemleri uygulayan xml.sax.handler.ContentHandler sınıfından türetilmiştir;
-
- satır: startElement yöntemi;
-
- satır: endElement yöntemi;
-
- satır: characters. yöntemi
Sonuçlar, bu paragrafın başında sunulanlarla aynıdır.
