14. معالجة المستندات XML
![]() |
لنأخذ المستند XML التالي:
<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>
نقوم بتحليل هذا المستند لإنتاج الناتج التالي على وحدة التحكم:
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
يجب أن نعرف كيفية التعرف على:
- علامة البداية مثل <تدريب>؛
- علامة نهاية مثل </enseignant>؛
- علامة بداية مع سمات مثل <personne sexe="F">؛
- نص العلامة مثل martin في <nom>martin</nom>.
يُطلق على برنامج تحليل الكود XML اسم محلل XML. هناك وحدتان توفران لنا الوظائف اللازمة لتحليل رمز XML: xml.sax و xml.sax.handler.
توفر لنا الوحدة النمطية [xml.sax] محللًا XML من خلال الأمر:
يقوم محلل النص هذا بتحليل النص XML بالتسلسل. ويستدعي أساليب المستخدم عند وقوع الأحداث التالية:
- الطريقة startElement عند بداية العلامة؛
- الطريقة endElement عند نهاية العلامة؛
- الطريقة characters عند جسم العلامة.
علينا أن نحدد للمحلل الفئة التي تنفذ هذه الطرق:
نمرر إلى الطريقة setContentHandler في المحلل، مثيلًا للفئة التي تنفذ الطرق startElement و endElement و characters. الفئة المستخدمة هي فئة مشتقة من الفئة xml.sax.handler.ContentHandler. يتم استدعاء الطرق السابقة مع المعلمات التالية:
- name هو اسم علامة البداية. attributs هو قاموس سمات العلامة. وبالتالي، بالنسبة لعلامة <personne sexe="M">، سيكون لدينا name="personne" و attributs={'sexe':'M'}
- name هو اسم علامة النهاية. وبالتالي، بالنسبة لعلامة </etudiant>، سيكون الناتج name='etudiant'.
- data هو نص العلامة. لذا، إذا كانت العلامة هي
فسيكون data='\r\n dupont\r\n '. بشكل عام، يتم التخلص من المسافات التي تسبق البيانات وتليها.
وبعد توضيح ذلك، يمكننا الانتقال إلى البرنامج النصي لتحليل مستند XML:
# -*- coding=utf-8 -*-
import xml.sax, xml.sax.handler,re
# فئة الإدارة XML
class XmlHandler(xml.sax.handler.ContentHandler):
# وظيفة يتم استدعاؤها عند العثور على علامة بداية
def startElement(self,name,attributs):
global depth
# سلسلة من المسافات (تباعد)
print " " * depth,
# السمات
precisions=""
for (attrib,valeur) in attributs.items():
precisions+="(%s,%s) " % (attrib,valeur)
# يتم عرض اسم العلامة والسمات إن وجدت
if precisions :
print "(%s,%s)" % (name,precisions)
else :
print name
# مستوى إضافي في الشجرة
depth+=1
# هل هذه علامة بيانات؟
global balisesDonnees,baliseDeDonnees
if balisesDonnees.has_key(name.lower()):
baliseDeDonnees=1
# الوظيفة التي يتم استدعاؤها عند العثور على علامة نهاية
def endElement(self,name):
# نهاية العلامة
# مستوى المسافة البادئة
global depth
depth-=1
# سلسلة من المسافات (التبعية)
print " " * depth,
# اسم العلامة
print "/%s" % (name)
# وظيفة عرض البيانات
def characters(self,data):
# البيانات
global baliseDeDonnees
# هل العلامة الحالية هي علامة بيانات؟
if not baliseDeDonnees :
return
# مستوى المسافة البادئة
global depth
# سلسلة من المسافات (التبعية)
print " " * depth,
# يتم عرض البيانات
match=re.match(r"^\s*(.*)\s*$",data)
if match:
print "[%s]" % (match.groups()[0])
# نهاية علامة البيانات
baliseDeDonnees=False
# ------------------------------------------- main
# البرنامج
# البيانات
file="data.xml" # ملف xml
depth=0 # مستوى التبعية = العمق في الشجرة
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # إذا كانت القيمة «صحيح»، فهذا يشير إلى أننا نتعامل مع علامة بيانات
# يتم إنشاء كائن لتحليل نص XML
xml_parser=xml.sax.make_parser()
# مدير العلامات
xml_parser.setContentHandler(XmlHandler())
# معالجة ملف XML
xml_parser.parse(file)
ملاحظات:
- يستخدم البرنامج النصي مكتبة وظائف الوحدات النمطية xml.sax و xml.sax.handler (السطر 3)؛
- السطر 62: الملف XML الذي تم تحليله؛
- السطر 68: محلل XML؛
- السطر 70: سيكون مدير الأحداث الصادرة عن المحلل مثيلًا لفئة XmlHandler؛
- السطر 72: بدء تحليل المستند XML؛
- السطر 6: الفئة التي تنفذ الطرق startElement، endElement، characters. وهي مشتقة من الفئة xml.sax.handler.ContentHandler التي تنفذ الطرق المستخدمة من قبل المحلل؛
- السطر 9: الطريقة startElement؛
- السطر 30: الطريقة endElement؛
- السطر 41: الطريقة characters.
النتائج هي تلك المعروضة في بداية هذه الفقرة.
