xml.dom.minidom --- پیادهسازی کمینهی DOM¶
کد منبع: Lib/xml/dom/minidom.py
xml.dom.minidom یک پیادهسازی حداقلی از رابط مدل شیء سند (DOM) با API مشابه زبانهای دیگر است. این پیادهسازی بهگونهای در نظر گرفته شده است که سادهتر از DOM کامل و همچنین بهطور قابلتوجهی کوچکتر باشد. کاربرانی که از قبل با DOM مهارت ندارند، بهتر است بهجای آن برای پردازش XML خود از ماژول xml.etree.ElementTree استفاده کنند.
توجه
اگر نیاز دارید دادههای غیرقابلاعتماد یا احراز هویتنشده را تجزیه کنید، به امنیت XML مراجعه کنید.
برنامههای DOM معمولاً با تجزیهی مقداری XML به یک DOM آغاز میشوند. با xml.dom.minidom، این کار از طریق توابع parse انجام میشود:
from xml.dom.minidom import parse, parseString
dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name
datasource = open('c:\\temp\\mydata.xml')
dom2 = parse(datasource) # parse an open file
dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')
تابع parse() میتواند یک نام پرونده یا یک شیء پرونده باز را دریافت کند.
- xml.dom.minidom.parse(filename_or_file, parser=None, bufsize=None)¶
یک
Documentاز ورودی دادهشده برمیگرداند. filename_or_file میتواند یک نام پرونده یا یک شیء شبهپرونده باشد. parser، در صورت داده شدن، باید یک شیء پارسر SAX2 باشد. این تابع هندلر سند (document handler) پارسر را تغییر میدهد و پشتیبانی از فضای نام را فعال میکند؛ سایر پیکربندیهای پارسر (مانند تنظیم حلکننده موجودیت (entity resolver)) باید از قبل انجام شده باشند.
اگر XML را در یک رشته دارید، میتوانید بهجای آن از تابع parseString() استفاده کنید:
- xml.dom.minidom.parseString(string, parser=None)¶
یک
Documentبرمیگرداند که رشته را نشان میدهد. این متد یک شیءio.StringIOبرای رشته ایجاد میکند و آن را بهparse()میفرستد.
هر دو تابع یک شیء Document برمیگردانند که نشاندهنده محتوای سند است.
کاری که توابع parse() و parseString() انجام میدهند، اتصال یک پارسر XML به یک «سازنده DOM» (DOM builder) است که میتواند رویدادهای تجزیه را از هر پارسر SAX بپذیرد و آنها را به یک درخت DOM تبدیل کند. نام این توابع شاید گمراهکننده باشد، اما هنگام یادگیری رابطها بهآسانی قابلدرک هستند. تجزیه سند پیش از بازگشت این توابع کامل میشود؛ صرفاً این توابع خود پیادهسازی پارسری ارائه نمیدهند.
همچنین میتوانید با فراخوانی یک متد روی یک شیء «پیادهسازی DOM»، یک Document ایجاد کنید. میتوانید این شیء را با فراخوانی تابع getDOMImplementation() در بسته xml.dom یا ماژول xml.dom.minidom دریافت کنید. هنگامی که یک Document داشتید، میتوانید گرههای فرزند را برای پر کردن DOM به آن اضافه کنید:
from xml.dom.minidom import getDOMImplementation
impl = getDOMImplementation()
newdoc = impl.createDocument(None, "some_tag", None)
top_element = newdoc.documentElement
text = newdoc.createTextNode('Some textual content.')
top_element.appendChild(text)
هنگامی که یک شیء سند DOM داشته باشید، میتوانید از طریق ویژگیها و متدهای آن به بخشهای سند XML خود دسترسی پیدا کنید. این ویژگیها در مشخصات DOM تعریف شدهاند. ویژگی اصلی شیء سند، ویژگی documentElement است. این ویژگی، المان اصلی سند XML را در اختیار شما قرار میدهد: المانی که همهی سایر المانها را در بر دارد. در اینجا یک برنامه نمونه آمده است:
dom3 = parseString("<myxml>Some data</myxml>")
assert dom3.documentElement.tagName == "myxml"
هنگامی که کارتان با یک درخت DOM به پایان رسید، میتوانید بهاختیار متد unlink() را برای تشویق پاکسازی زودهنگام اشیایی که دیگر مورد نیاز نیستند فراخوانی کنید. unlink() یک افزونهی خاص xml.dom.minidom برای DOM API است که گره و نوادگان آن را عملاً بیاستفاده میکند. در غیر این صورت، زبالهروبی پایتون در نهایت اشیاء موجود در درخت را آزاد خواهد کرد.
همچنین ملاحظه نمائید
- مشخصات سطح ۱ مدل شیء سند (DOM)
توصیهنامهی W3C برای DOM که توسط
xml.dom.minidomپشتیبانی میشود.
اشیای DOM¶
تعریف API DOM برای پایتون بهعنوان بخشی از مستندات ماژول xml.dom ارائه شده است. این بخش تفاوتهای بین API و xml.dom.minidom را فهرست میکند.
- Node.unlink()¶
ارجاعهای داخلی درون DOM را قطع کنید تا در نسخههای پایتون بدون زبالهروبی چرخهای، زبالهروبی شود. حتی زمانی که زبالهروبی چرخهای در دسترس است، استفاده از این میتواند مقادیر زیادی حافظه را زودتر در دسترس قرار دهد، بنابراین فراخوانی این روی اشیای DOM به محض اینکه دیگر نیازی به آنها نیست، روش خوبی است. فقط لازم است این روی شیء
Documentفراخوانی شود، اما میتوان آن را روی گرههای فرزند نیز فراخوانی کرد تا فرزندان آن گره حذف شوند.میتوانید با استفاده از دستور
withاز فراخوانی صریح این متد اجتناب کنید. کد زیر هنگام خروج از بلوکwith، بهطور خودکار پیوند dom را قطع میکند:with xml.dom.minidom.parse(datasource) as dom: ... # Work with dom.
- Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)¶
XML را در شیء نویسنده بنویسید. نویسنده ورودی را بهصورت متن دریافت میکند، نه بایت؛ باید متد
write()داشته باشد که با متد موجود در رابط شیء پرونده مطابقت دارد. پارامتر indent تورفتگی گره جاری است. پارامتر addindent تورفتگی افزایشی است که برای زیرگرههای گره جاری استفاده میشود. پارامتر newl رشتهای را مشخص میکند که برای پایان دادن به سطرهای جدید استفاده میشود.برای گره
Document، میتوان از یک آرگومان کلیدواژهای اضافی به نام encoding برای مشخص کردن فیلد کدگذاری سرآیند XML استفاده کرد.بهطور مشابه، ذکر صریح آرگومان standalone باعث میشود اعلامیههای مستقل سند به پیشدرآمد سند XML افزوده شوند. اگر مقدار به
Trueتنظیم شود،standalone="yes"افزوده میشود، در غیر این صورت مقدار به"no"تنظیم میشود. ذکر نکردن آرگومان، اعلامیه را از سند حذف میکند.تغییر یافته در نسخهی 3.8: متد
writexml()اکنون ترتیب صفتهایی را که کاربر تعیین کرده است حفظ میکند.تغییر یافته در نسخهی 3.9: پارامتر standalone افزوده شد.
تغییر یافته در نسخهی 3.16.0a0 (unreleased): Namespace declarations missing for the serialized element and its attributes are now written. It now works for
DocumentFragmentnodes.
- Node.toxml(encoding=None, standalone=None)¶
یک رشته یا رشته بایتی حاوی XML بازنماییشده توسط گره DOM را برمیگرداند.
با یک آرگومان encoding [1] صریح، نتیجه یک رشته بایت با کدگذاری مشخص است. بدون آرگومان encoding، نتیجه یک رشته یونیکد است و اعلامیه XML در رشته حاصل، کدگذاری را مشخص نمیکند. کدگذاری این رشته با کدگذاری غیر از UTF-8 احتمالاً نادرست است، زیرا UTF-8 کدگذاری پیشفرض XML است.
آرگومان standalone دقیقاً مانند
writexml()رفتار میکند.تغییر یافته در نسخهی 3.8: متد
toxml()اکنون ترتیب ویژگیها را همانطور که کاربر تعیین کرده است حفظ میکند.تغییر یافته در نسخهی 3.9: پارامتر standalone افزوده شد.
تغییر یافته در نسخهی 3.16.0a0 (unreleased): It now works for
DocumentFragmentnodes.
- Node.toprettyxml(indent='\t', newl='\n', encoding=None, standalone=None)¶
یک نسخهی زیبانویسیشده از سند برمیگرداند. indent رشتهی تورفتگی را مشخص میکند و پیشفرض آن یک نویسهی تب است؛ newl رشتهای را که در پایان هر خط درج میشود مشخص میکند و پیشفرض آن
\nاست.آرگومان encoding مانند آرگومان متناظر در
toxml()رفتار میکند.آرگومان standalone دقیقاً مانند
writexml()رفتار میکند.No indentation is added inside an element which is marked with
xml:space="preserve", which is declared in the DTD as not having element content, or, in absence of such declaration, which contains text, because this would change its content.تغییر یافته در نسخهی 3.8: متد
toprettyxml()اکنون ترتیب ویژگیهای تعیینشده توسط کاربر را حفظ میکند.تغییر یافته در نسخهی 3.9: پارامتر standalone افزوده شد.
تغییر یافته در نسخهی 3.16.0a0 (unreleased): Whitespace is no longer added inside an element with mixed content or marked with
xml:space="preserve". It now works forDocumentFragmentnodes.
مثال DOM¶
این برنامه نمونه، مثال نسبتاً واقعگرایانهای از یک برنامه ساده است. در این مورد خاص، از انعطافپذیری DOM استفاده چندانی نمیکنیم.
import xml.dom.minidom
document = """\
<slideshow>
<title>Demo slideshow</title>
<slide><title>Slide title</title>
<point>This is a demo</point>
<point>Of a program for processing slides</point>
</slide>
<slide><title>Another demo slide</title>
<point>It is important</point>
<point>To have more than</point>
<point>one slide</point>
</slide>
</slideshow>
"""
dom = xml.dom.minidom.parseString(document)
def getText(nodelist):
rc = []
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc.append(node.data)
return ''.join(rc)
def handleSlideshow(slideshow):
print("<html>")
handleSlideshowTitle(slideshow.getElementsByTagName("title")[0])
slides = slideshow.getElementsByTagName("slide")
handleToc(slides)
handleSlides(slides)
print("</html>")
def handleSlides(slides):
for slide in slides:
handleSlide(slide)
def handleSlide(slide):
handleSlideTitle(slide.getElementsByTagName("title")[0])
handlePoints(slide.getElementsByTagName("point"))
def handleSlideshowTitle(title):
print(f"<title>{getText(title.childNodes)}</title>")
def handleSlideTitle(title):
print(f"<h2>{getText(title.childNodes)}</h2>")
def handlePoints(points):
print("<ul>")
for point in points:
handlePoint(point)
print("</ul>")
def handlePoint(point):
print(f"<li>{getText(point.childNodes)}</li>")
def handleToc(slides):
for slide in slides:
title = slide.getElementsByTagName("title")[0]
print(f"<p>{getText(title.childNodes)}</p>")
handleSlideshow(dom)
minidom و استاندارد DOM¶
ماژول xml.dom.minidom اساساً یک DOM سازگار با DOM 1.0 است که برخی ویژگیهای DOM 2 (عمدتاً ویژگیهای فضای نام) را دارد.
استفاده از رابط DOM در پایتون ساده است. قواعد نگاشت زیر اعمال میشوند:
رابطها از طریق اشیای نمونه قابل دسترسی هستند. برنامهها نباید خودشان کلاسها را نمونهسازی کنند؛ باید از توابع سازنده موجود در شیء
Documentاستفاده کنند. رابطهای مشتقشده از تمام عملیات (و ویژگیها)ی رابطهای پایه، بههمراه هر عملیات جدیدی پشتیبانی میکنند.از عملیاتها بهعنوان متد استفاده میشود. از آنجا که DOM فقط از پارامترهای
inاستفاده میکند، آرگومانها با ترتیب معمول (از چپ به راست) ارسال میشوند. هیچ آرگومان اختیاری وجود ندارد. عملیاتهایvoid،Noneرا برمیگردانند.ویژگیهای IDL به ویژگیهای نمونه نگاشت میشوند. برای سازگاری با نگاشت زبان OMG IDL برای پایتون، میتوان به ویژگی
fooاز طریق متدهای دسترسیدهنده_get_foo()و_set_foo()نیز دسترسی داشت. ویژگیهایreadonlyنباید تغییر داده شوند؛ این موضوع در رانتایم اعمال نمیشود.انواع
short int،unsigned int،unsigned long longوbooleanهمگی به اشیاء عدد صحیح پایتون نگاشت میشوند.نوع
DOMStringبه رشتههای پایتون نگاشت میشود.xml.dom.minidomاز بایتها یا رشتهها پشتیبانی میکند، اما بهطور معمول رشتهها را تولید میکند. مقادیر از نوعDOMStringممکن است در مواردی که مشخصه DOM از W3C اجازه داشتن مقدارnullدر IDL را بدهد،Noneنیز باشند.اعلانهای
constبه متغیرهایی در محدودهی مربوط به خود نگاشت میشوند (برای مثالxml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE)؛ این متغیرها نباید تغییر کنند.DOMExceptionدر حال حاضر درxml.dom.minidomپشتیبانی نمیشود. در عوض،xml.dom.minidomاز استثناهای استاندارد پایتون مانندTypeErrorوAttributeErrorاستفاده میکند.هر یک از رابطهای
NodeListوNamedNodeMapدو پیادهسازی دارند، که متدها و عملیاتهای اضافی فراهم میکنند.childNodesیک زیرکلاس ازlistاست، یا برای گرههایی که نمیتوانند فرزند داشته باشند، یک زیرکلاس ازtupleاست. این ویژگی پیمایش، الحاق، نمایهسازی و برش را پشتیبانی میکند.attributesازlen()، عملگرin، زیرنویسی با یک نام یا با یک تاپل(namespaceURI, localName)، انتساب و حذف، و متدهایget()،keys()،keysNS()،values()،items()وitemsNS()پشتیبانی میکند.entitiesوnotationsفقطخواندنی هستند و تنها ازlen()و زیرنویسی با یک نام پشتیبانی میکنند.strictErrorCheckingis alwaysFalse.تغییر یافته در نسخهی 3.16.0a0 (unreleased): Previously,
specifiedwas alwaysFalse.The constraints of the DOM are now enforced, and the corresponding exceptions are raised.
تغییر یافته در نسخهی 3.16.0a0 (unreleased): Previously, many invalid operations silently succeeded and produced an invalid document, but removing an absent attribute raised
NotFoundErr.تغییر یافته در نسخهی 3.16.0a0 (unreleased): Namespaces are now validated in the factory methods and when setting
prefixof an attribute.
رابطهای زیر در xml.dom.minidom پیادهسازی ندارند:
DOMTimeStamp
This reflects information in the XML document that is not of general utility to most DOM users.
تغییر یافته در نسخهی 3.16.0a0 (unreleased): EntityReference is now implemented.
Note that the parser expands entity references,
so they only occur in a document if created explicitly.
پانویسها