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
ما باید بدانیم چگونه تشخیص دهیم:
- یک تگ آغازین مانند <training>;
- یک تگ پایانی مانند </teacher>؛
- یک تگ بازشونده با ویژگیها، مانند <person sex="F">;
- بدنه یک تگ مانند martin در داخل <nom>martin</nom>.
برنامهای که کد XML را تحلیل میکند، پارسر XML نامیده میشود. دو ماژول قابلیت تجزیهٔ کدی مانند XML را فراهم میکنند: xml.sax و xml.sax.handler.
ماژول [xml.sax] از طریق دستور زیر یک پارسر XML را در اختیار ما قرار میدهد:
این تجزیهگر متن XML را بهصورت متوالی تحلیل میکند. این تجزیهگر در رویدادها متدهای تعریفشده توسط کاربر را فراخوانی میکند:
- متد startElement در شروع یک تگ؛
- روش endElement هنگام بستهشدن یک تگ؛
- متد characters در بدنه یک تگ.
ما باید به تجزیهگر بگوییم کدام کلاس این متدها را پیادهسازی میکند:
ما یک نمونه از کلاسی را که متدهای startElement، endElement و characters را پیادهسازی میکند، به متد setContentHandler پارسر پاس میکنیم. کلاس مورد استفاده زیرکلاس کلاس xml.sax.handler.ContentHandler است. متدهای قبلی با پارامترهای زیر فراخوانی میشوند:
- name نام تگ آغازین است. attributs فرهنگ لغت ویژگیهای تگ است. بنابراین، برای تگ <person sex="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
# ------------------------------------------- اصلی
# برنامه
# دادهها
file="data.xml" # فایل XML
depth=0 # سطح تورفتگی = عمق در ساختار درختی
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # اگر true باشد، نشان میدهد که این یک تگ داده است
#یک شیء تحلیل متن XML ایجاد میشود
xml_parser=xml.sax.make_parser()
# پردازشگر تگ
xml_parser.setContentHandler(XmlHandler())
# پردازش فایل XML
xml_parser.parse(file)
یادداشتها:
- اسکریپت از کتابخانه توابع ماژولهای xml.sax و xml.sax.handler (خط ۳) استفاده میکند؛
- خط ۶۲: فایل تحلیلشده XML;
- خط ۶۸: پارسر XML؛
- خط ۷۰: رسیدگیکننده برای رویدادهای صادرشده توسط تجزیهکننده، یک نمونه از کلاس XmlHandler خواهد بود؛
- خط ۷۲: پردازش سند XML آغاز میشود؛
- خط ۶: کلاسی که متدهای startElement، endElement و characters را پیادهسازی میکند. این از کلاس xml.sax.handler.ContentHandler مشتق شده است، که متدهای مورد استفاده توسط تجزیهگر را پیادهسازی میکند؛
- خط ۹: متد startElement;
- خط ۳۰: متد endElement;
- خط ۴۱: متد characters.
نتایج همانهایی هستند که در ابتدای این پاراگراف ارائه شدهاند.
