از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
خواندن و نوشتن فایل های XML در پایتون
سرفصلهای مطلب
XML یا زبان نشانه گذاری توسعه پذیر یک زبان نشانه گذاری است که معمولاً برای ساختار، ذخیره و انتقال داده ها بین سیستم ها استفاده می شود. اگرچه مانند گذشته رایج نیست، اما همچنان در خدماتی مانند RSS و SOAP و همچنین برای ساختاربندی فایلهایی مانند اسناد مایکروسافت آفیس استفاده میشود.
از آنجایی که پایتون یک زبان محبوب برای تجزیه و تحلیل وب و داده است، احتمالاً در برخی مواقع نیاز به خواندن یا نوشتن دادههای XML خواهید داشت، در این صورت خوش شانس هستید.
در طول این مقاله ما در درجه اول نگاهی به این خواهیم داشت ElementTree ماژول برای خواندن، نوشتن، و اصلاح داده های XML. ما همچنین آن را با قدیمی تر مقایسه خواهیم کرد minidom ماژول در چند بخش اول تا بتوانید مقایسه خوبی از این دو داشته باشید.
ماژول های XML
را minidom
یا Minimal DOM Implementation، یک پیاده سازی ساده از Document Object Model (DOM) است. را DOM یک رابط برنامه نویسی کاربردی است که XML را به عنوان یک ساختار درختی در نظر می گیرد که در آن هر کدام node در درخت یک شی است. بنابراین، استفاده از این ماژول مستلزم آشنایی با عملکرد آن است.
را ElementTree
ماژول یک رابط “پایتونیک” بیشتر برای مدیریت XMl فراهم می کند و گزینه خوبی برای کسانی است که با DOM آشنایی ندارند. همچنین به دلیل رابط کاربری ساده اش که در سراسر این مقاله خواهید دید، احتمالاً کاندیدای بهتری برای استفاده توسط برنامه نویسان تازه کار بیشتر است.
در این مقاله، ElementTree
ماژول در همه مثال ها استفاده خواهد شد، در حالی که minidom
همچنین نشان داده خواهد شد، اما فقط برای شمارش و خواندن اسناد XML.
نمونه فایل XML
در مثالهای زیر، از فایل XML زیر استفاده میکنیم که آن را بهعنوان «items.xml» ذخیره میکنیم:
<data>
<items>
<item name="item1">item1abc</item>
<item name="item2">item2abc</item>
</items>
</data>
همانطور که می بینید، این یک مثال نسبتا ساده XML است که فقط شامل چند شیء تو در تو و یک ویژگی است. با این حال، نشان دادن تمام عملیات XML در این مقاله باید کافی باشد.
خواندن اسناد XML
استفاده از minidom
به منظور تجزیه یک سند XML با استفاده از minidom
، ابتدا باید import آن را از xml.dom
مدول. این ماژول از parse
تابع ایجاد یک شی DOM از فایل XML ما است. را parse
تابع دارای نحو زیر است:
xml.dom.minidom.parse(filename_or_file(, parser(, bufsize)))
در اینجا نام فایل می تواند یک رشته حاوی مسیر فایل یا یک شی از نوع فایل باشد. تابع یک سند را برمی گرداند که می تواند به عنوان یک نوع XML مدیریت شود. بنابراین، ما می توانیم از تابع استفاده کنیم getElementByTagName()
برای پیدا کردن یک برچسب خاص
از آنجایی که هر کدام node را می توان به عنوان یک شی در نظر گرفت، ما می توانیم با استفاده از ویژگی های شی به ویژگی ها و متن یک عنصر دسترسی پیدا کنیم. در مثال زیر به ویژگی ها و متن یک خاص دسترسی پیدا کرده ایم node، و از همه گره ها با هم.
from xml.dom import minidom
mydoc = minidom.parse('items.xml')
items = mydoc.getElementsByTagName('item')
print('Item #2 attribute:')
print(items(1).attributes('name').value)
print('\nAll attributes:')
for elem in items:
print(elem.attributes('name').value)
print('\nItem #2 data:')
print(items(1).firstChild.data)
print(items(1).childNodes(0).data)
print('\nAll item data:')
for elem in items:
print(elem.firstChild.data)
نتیجه به شرح زیر است:
$ python minidomparser.py
Item
item2
All attributes:
item1
item2
Item
item2abc
item2abc
All item data:
item1abc
item2abc
شکل 1
اگر میخواهیم از فایلی که قبلاً باز شده است استفاده کنیم، فقط میتوانیم شی فایل خود را به آن منتقل کنیم parse
مانند:
datasource = open('items.xml')
mydoc = parse(datasource)
همچنین، اگر دادههای XML قبلاً بهعنوان یک رشته بارگذاری شده بودند، میتوانستیم از آن استفاده کنیم parseString()
در عوض عملکرد
با استفاده از ElementTree
ElementTree
راه بسیار ساده ای را به ما ارائه می دهد process فایل های XML مثل همیشه، برای استفاده از آن ابتدا باید import ماژول در کد ما از import
فرمان با as
کلمه کلیدی که به ما امکان می دهد از یک نام ساده شده استفاده کنیم (ET
در این مورد) برای ماژول در کد.
دنبال کردن import، یک ساختار درختی با parse
تابع، و ما آن را بدست می آوریم root عنصر زمانی که ما به root node ما به راحتی می توانیم از اطراف درخت عبور کنیم، زیرا یک درخت یک نمودار متصل است.
استفاده کردن ElementTree
و مانند مثال کد قبلی، کد را بدست می آوریم node ویژگی ها و متن با استفاده از اشیاء مربوط به هر یک node.
کد به شرح زیر است:
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
print('Item #2 attribute:')
print(root(0)(1).attrib)
print('\nAll attributes:')
for elem in root:
for subelem in elem:
print(subelem.attrib)
print('\nItem #2 data:')
print(root(0)(1).text)
print('\nAll item data:')
for elem in root:
for subelem in elem:
print(subelem.text)
نتیجه به شرح زیر خواهد بود:
$ python treeparser.py
Item
item2
All attributes:
item1
item2
Item
item2abc
All item data:
item1abc
item2abc
شکل 2
همانطور که می بینید، این بسیار شبیه به minidom
مثال. یکی از تفاوت های اصلی این است که attrib
شی به سادگی یک شی دیکشنری است که باعث می شود تا کمی با سایر کدهای پایتون سازگاری داشته باشد. ما همچنین نیازی به استفاده نداریم value
برای دسترسی به مقدار ویژگی آیتم مانند قبل.
ممکن است متوجه شده باشید که چگونه به اشیا و ویژگی ها دسترسی پیدا می کنید ElementTree
همانطور که قبلا ذکر کردیم کمی پایتونیک تر است. این به این دلیل است که دادههای XML برخلاف با بهصورت فهرستها و فرهنگهای ساده تجزیه میشوند minidom
جایی که موارد به صورت سفارشی تجزیه می شوند xml.dom.minidom.Attr
و “گره های متن DOM”.
شمارش عناصر یک سند XML
استفاده از minidom
همانطور که در مورد قبلی، minidom
باید از کشور وارد شود dom
مدول. این ماژول عملکرد را ارائه می دهد getElementsByTagName
، که از آن برای یافتن مورد برچسب استفاده می کنیم. پس از به دست آوردن، ما از آن استفاده می کنیم len()
روش داخلی برای به دست آوردن تعداد موارد فرعی متصل به a node. نتیجه به دست آمده از کد زیر نشان داده شده است شکل 3.
from xml.dom import minidom
mydoc = minidom.parse('items.xml')
items = mydoc.getElementsByTagName('item')
print(len(items))
$ python counterxmldom.py
2
شکل 3
به خاطر داشته باشید که این خواهد شد فقط تعداد آیتم های فرزند را در زیر یادداشتی که اجرا می کنید بشمارید len()
روی، که در این مورد است root node. اگر می خواهید همه عناصر فرعی را در یک درخت بسیار بزرگتر بیابید، باید از همه عناصر عبور کنید و هر یک از فرزندان آنها را بشمارید.
با استفاده از ElementTree
به طور مشابه، ElementTree
ماژول به ما اجازه می دهد تا مقدار گره های متصل به a را محاسبه کنیم node.
کد مثال:
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
print(len(root(0)))
نتیجه به شرح زیر است:
$ python counterxml.py
2
شکل 4
نوشتن اسناد XML
با استفاده از ElementTree
ElementTree
همچنین برای نوشتن داده ها بر روی فایل های XML عالی است. کد زیر روش ایجاد یک فایل XML با ساختار مشابه فایلی که در مثال های قبلی استفاده کردیم را نشان می دهد.
مراحل عبارتند از:
- یک عنصر ایجاد کنید که مانند ما عمل کند root عنصر در مورد ما تگ این عنصر “داده” است.
- زمانی که ما خودمان را داریم root عنصر، ما می توانیم عناصر فرعی را با استفاده از
SubElement
تابع. این تابع دارای نحو است:
SubElement(parent, tag, attrib={}, **extra)
اینجا parent
پدر و مادر است node برای اتصال به attrib
یک فرهنگ لغت حاوی ویژگی های عنصر و extra
آرگومان های کلمه کلیدی اضافی هستند. این تابع یک عنصر را به ما برمیگرداند که میتوان از آن برای پیوست کردن سایر عناصر فرعی استفاده کرد، همانطور که در خطوط زیر با ارسال موارد به SubElement
سازنده
3. اگرچه می توانیم ویژگی های خود را با the اضافه کنیم SubElement
تابع، ما همچنین می توانیم از set()
عملکرد، همانطور که در کد زیر انجام می دهیم. متن عنصر با ایجاد می شود text
دارایی از Element
هدف – شی.
4. در 3 خط آخر کد زیر یک رشته از درخت XML ایجاد می کنیم و آن داده ها را در فایلی که باز می کنیم می نویسیم.
کد مثال:
import xml.etree.ElementTree as ET
data = ET.Element('data')
items = ET.SubElement(data, 'items')
item1 = ET.SubElement(items, 'item')
item2 = ET.SubElement(items, 'item')
item1.set('name','item1')
item2.set('name','item2')
item1.text = 'item1abc'
item2.text = 'item2abc'
mydata = ET.tostring(data)
myfile = open("items2.xml", "w")
myfile.write(mydata)
اجرای این کد منجر به یک فایل جدید به نام “items2.xml” می شود که حداقل از نظر ساختار داده XML باید معادل فایل اصلی “items.xml” باشد. احتمالاً متوجه خواهید شد که رشته حاصل فقط یک خط است و هیچ تورفتگی ندارد.
یافتن عناصر XML
با استفاده از ElementTree
را ElementTree
ماژول ارائه می دهد findall()
تابع، که به ما در یافتن موارد خاص در درخت کمک می کند. همه موارد را با شرایط مشخص شده برمی گرداند. علاوه بر این، ماژول دارای عملکرد است find()
، که فقط برمی گرداند اولین عنصر فرعی که با معیارهای مشخص شده مطابقت دارد. سینتکس هر دوی این توابع به شرح زیر است:
findall(match, namespaces=None)
find(match, namespaces=None)
برای هر دوی این توابع match
پارامتر می تواند یک نام تگ XML یا یک مسیر باشد. کارکرد findall()
لیستی از عناصر و را برمی گرداند find
یک شی از نوع واحد را برمی گرداند Element
.
علاوه بر این، یک تابع کمکی دیگر وجود دارد که متن اولین را برمی گرداند node که با معیار داده شده مطابقت دارد:
findtext(match, default=None, namespaces=None)
در اینجا چند نمونه کد برای نشان دادن روش عملکرد این توابع وجود دارد:
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
for elem in root:
print(elem.find('item').get('name'))
for elem in root:
for subelem in elem.findall('item'):
print(subelem.attrib)
print(subelem.get('name'))
و این هم نتیجه اجرای مجدد این کد:
$ python findtree.py
item1
{'name': 'item1'}
item1
{'name': 'item2'}
item2
شکل 5
اصلاح عناصر XML
با استفاده از ElementTree
را ElementTree
ماژول چندین ابزار برای اصلاح اسناد XML موجود ارائه می دهد. مثال زیر روش تغییر نام a را نشان می دهد node، نام یک ویژگی را تغییر دهید و مقدار آن را تغییر دهید و چگونه یک ویژگی اضافی به یک عنصر اضافه کنید.
آ node متن را می توان با تعیین مقدار جدید در قسمت متن تغییر داد node هدف – شی. نام مشخصه را می توان با استفاده از عبارت دوباره تعریف کرد set(name, value)
تابع. را set
تابع نباید فقط کار کند روی یک ویژگی موجود، همچنین می تواند برای تعریف یک ویژگی جدید استفاده شود.
کد زیر روش انجام این عملیات را نشان می دهد:
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
for elem in root.iter('item'):
elem.text = 'new text'
for elem in root.iter('item'):
elem.set('name', 'newitem')
for elem in root.iter('item'):
elem.set('name2', 'newitem2')
tree.write('newitems.xml')
پس از اجرای کد، فایل XML ایجاد شده “newitems.xml” دارای یک درخت XML با داده های زیر خواهد بود:
<data>
<items>
<item name="newitem" name2="newitem2">new text</item>
<item name="newitem" name2="newitem2">new text</item>
</items>
</data>
همانطور که می بینیم هنگام مقایسه با فایل XML اصلی، نام عناصر آیتم به “newitem”، متن به “new text” و ویژگی “name2” به هر دو گره اضافه شده است.
همچنین ممکن است متوجه شوید که نوشتن داده های XML به این روش (تماس tree.write
با نام فایل) قالب بندی بیشتری به درخت XML اضافه می کند تا حاوی خطوط جدید و تورفتگی باشد.
ایجاد عناصر فرعی XML
با استفاده از ElementTree
را ElementTree
ماژول بیش از یک راه برای افزودن یک عنصر جدید دارد. اولین راهی که به آن نگاه خواهیم کرد استفاده از makeelement()
تابع، که دارای node نام و فرهنگ لغت با ویژگی های آن به عنوان پارامتر.
راه دوم از طریق SubElement()
کلاس، که عنصر والد و فرهنگ لغت ویژگی ها را به عنوان ورودی می گیرد.
در مثال زیر هر دو روش را نشان می دهیم. در مورد اول node هیچ ویژگی ندارد، بنابراین ما یک فرهنگ لغت خالی ایجاد کردیم (attrib = {}
). در حالت دوم، از دیکشنری پر شده برای ایجاد ویژگی ها استفاده می کنیم.
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
attrib = {}
element = root.makeelement('seconditems', attrib)
root.append(element)
attrib = {'name2': 'secondname2'}
subelement = root(0)(1).makeelement('seconditem', attrib)
ET.SubElement(root(1), 'seconditem', attrib)
root(1)(0).text = 'seconditemabc'
tree.write('newitems2.xml')
پس از اجرای این کد، فایل XML حاصل به شکل زیر خواهد بود:
<data>
<items>
<item name="item1">item1abc</item>
<item name="item2">item2abc</item>
</items>
<seconditems>
<seconditem name2="secondname2">seconditemabc</seconditem>
</seconditems>
</data>
همانطور که می بینیم هنگام مقایسه با فایل اصلی، عنصر “seconditems” و عنصر فرعی آن “seconditem” اضافه شده است. علاوه بر این، “مورد دوم” node دارای “name2” به عنوان یک ویژگی، و متن آن “seconditemabc” است، همانطور که انتظار می رود.
حذف عناصر XML
با استفاده از ElementTree
همانطور که احتمالاً انتظار دارید، ElementTree
ماژول قابلیت های لازم برای حذف را دارد nodeویژگی ها و عناصر فرعی.
حذف یک ویژگی
کد زیر روش حذف a را نشان می دهد node’s ویژگی با استفاده از pop()
تابع. تابع در مورد اعمال می شود attrib
پارامتر شی نام ویژگی را مشخص می کند و آن را روی آن تنظیم می کند None
.
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
root(0)(0).attrib.pop('name', None)
tree.write('newitems3.xml')
نتیجه فایل XML زیر خواهد بود:
<data>
<items>
<item>item1abc</item>
<item name="item2">item2abc</item>
</items>
</data>
همانطور که در کد XML بالا می بینیم، اولین مورد هیچ ویژگی “name” ندارد.
حذف یک عنصر فرعی
یک عنصر فرعی خاص را می توان با استفاده از آن حذف کرد remove
تابع. این تابع باید مشخص کند node که می خواهیم حذف کنیم.
مثال زیر روش استفاده از آن را به ما نشان می دهد:
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
root(0).remove(root(0)(0))
tree.write('newitems4.xml')
نتیجه فایل XML زیر خواهد بود:
<data>
<items>
<item name="item2">item2abc</item>
</items>
</data>
همانطور که از کد XML بالا می بینیم، اکنون فقط یک “آیتم” وجود دارد. node. مورد دوم از درخت اصلی حذف شده است.
حذف تمام عناصر فرعی
را ElementTree
ماژول به ما ارائه می دهد clear()
تابع، که می تواند برای حذف استفاده شود همه عناصر فرعی یک عنصر معین
مثال زیر روش استفاده را به ما نشان می دهد clear()
:
import xml.etree.ElementTree as ET
tree = ET.parse('items.xml')
root = tree.getroot()
root(0).clear()
tree.write('newitems5.xml')
نتیجه فایل XML زیر خواهد بود:
<data>
<items />
</data>
همانطور که در کد XML بالا می بینیم، تمام عناصر فرعی عنصر “اقلام” از درخت حذف شده اند.
بسته بندی
پایتون چندین گزینه برای مدیریت فایل های XML ارائه می دهد. در این مقاله به بررسی آن پرداخته ایم ElementTree
ماژول، و از آن برای تجزیه، ایجاد، اصلاح و حذف فایل های XML استفاده کرد. ما نیز استفاده کرده ایم minidom
مدل برای تجزیه فایل های XML. من شخصاً استفاده از آن را توصیه می کنم ElementTree
ماژول چون کار با آن بسیار ساده تر است و ماژول مدرن تری از این دو است.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-28 23:22:05