xml.dom.minidom
— 最小 DOM 實現¶
xml.dom.minidom
是文件物件模型介面的最小實現,其 API 與其他語言中的 API 類似。它的目標是比完整的 DOM 更簡單,而且也小得多。不熟悉 DOM 的使用者應考慮使用 xml.etree.ElementTree
模組進行 XML 處理。
警告
xml.dom.minidom
模組對於惡意構造的資料是不安全的。如果需要解析不受信任或未經驗證的資料,請參閱 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 解析器物件。此函式將更改解析器的文件處理程式並激活名稱空間支援;其他解析器配置(如設定實體解析器)必須提前完成。
如果字串中有 XML,則可以使用 parseString()
函式
- xml.dom.minidom.parseString(string, parser=None)¶
返回一個表示 string 的
Document
。此方法為字串建立一個io.StringIO
物件,並將其傳遞給parse()
。
這兩個函式都返回一個表示文件內容的 Document
物件。
parse()
和 parseString()
函式所做的是將 XML 解析器與“DOM 構建器”連線起來,該構建器可以接受來自任何 SAX 解析器的解析事件,並將它們轉換為 DOM 樹。這些函式的名稱可能具有誤導性,但在學習介面時很容易掌握。文件的解析將在這些函式返回之前完成;只是這些函式本身不提供解析器實現。
您還可以透過呼叫“DOM 實現”物件上的方法來建立 Document
。您可以透過呼叫 xml.dom
包或 xml.dom.minidom
模組中的 getDOMImplementation()
函式來獲取此物件。擁有 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 的特定擴充套件,它會使節點及其後代基本上無用。否則,Python 的垃圾回收器最終將處理樹中的物件。
另請參閱
- 文件物件模型 (DOM) 1 級規範
W3C 針對
xml.dom.minidom
支援的 DOM 的建議。
DOM 物件¶
Python 的 DOM API 定義作為 xml.dom
模組文件的一部分給出。本節列出了 API 和 xml.dom.minidom
之間的差異。
- Node.unlink()¶
斷開 DOM 中的內部引用,以便在沒有迴圈 GC 的 Python 版本上進行垃圾回收。即使在可以使用迴圈 GC 時,使用此方法也可以更快地釋放大量記憶體,因此在不再需要 DOM 物件時立即呼叫此方法是一種好習慣。這隻需要在
Document
物件上呼叫,但可以在子節點上呼叫以丟棄該節點的子節點。您可以使用
with
語句來避免顯式呼叫此方法。以下程式碼將在退出with
程式碼塊時自動取消連結 domwith xml.dom.minidom.parse(datasource) as dom: ... # Work with dom.
- Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)¶
將 XML 寫入 writer 物件。writer 接收文字而不是位元組作為輸入,它應該有一個
write()
方法,該方法與檔案物件介面的匹配。indent 引數是當前節點的縮排。addindent 引數是用於當前節點的子節點的增量縮排。newl 引數指定用於終止換行符的字串。對於
Document
節點,可以使用額外的關鍵字引數 encoding 來指定 XML 頭的編碼欄位。類似地,顯式宣告 standalone 引數會導致獨立文件宣告被新增到 XML 文件的序言中。如果該值設定為
True
,則新增standalone="yes"
,否則設定為"no"
。不宣告該引數將從文件中省略該宣告。在 3.8 版本中更改:
writexml()
方法現在保留使用者指定的屬性順序。在 3.9 版本中更改: 添加了 standalone 引數。
- Node.toxml(encoding=None, standalone=None)¶
返回一個字串或位元組串,其中包含 DOM 節點表示的 XML。
使用顯式的 encoding [1] 引數,結果是指定編碼的位元組串。如果沒有 encoding 引數,結果是 Unicode 字串,並且結果字串中的 XML 宣告不指定編碼。使用 UTF-8 以外的編碼對該字串進行編碼可能是錯誤的,因為 UTF-8 是 XML 的預設編碼。
standalone 引數的行為與
writexml()
中完全相同。在 3.8 版本中更改:
toxml()
方法現在保留使用者指定的屬性順序。在 3.9 版本中更改: 添加了 standalone 引數。
- Node.toprettyxml(indent='\t', newl='\n', encoding=None, standalone=None)¶
返回文件的美化列印版本。indent 指定縮排字串,預設為製表符;newl 指定在每行末尾發出的字串,預設為
\n
。encoding 引數的行為類似於
toxml()
的相應引數。standalone 引數的行為與
writexml()
中完全相同。在 3.8 版本中更改:
toprettyxml()
方法現在保留使用者指定的屬性順序。在 3.9 版本中更改: 添加了 standalone 引數。
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 1.0 的 DOM,具有一些 DOM 2 特性(主要是名稱空間特性)。
在 Python 中使用 DOM 介面非常簡單。以下對映規則適用
介面透過例項物件訪問。應用程式不應例項化類本身;它們應該使用
Document
物件上提供的建立器函式。派生介面支援來自基礎介面的所有操作(和屬性)以及任何新操作。操作用作方法。由於 DOM 僅使用
in
引數,因此引數以正常順序(從左到右)傳遞。沒有可選引數。void
操作返回None
。IDL 屬性對映到例項屬性。為了與 OMG IDL 語言對映到 Python 相容,也可以透過訪問器方法
_get_foo()
和_set_foo()
訪問屬性foo
。readonly
屬性不得更改;這在執行時不會強制執行。型別
short int
、unsigned int
、unsigned long long
和boolean
都對映到 Python 整數物件。型別
DOMString
對映到 Python 字串。xml.dom.minidom
支援位元組或字串,但通常會生成字串。型別為DOMString
的值也可能是None
,在 W3C 的 DOM 規範允許的情況下,可以具有 IDLnull
值。const
宣告對映到其各自範圍內的變數(例如xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE
);它們不得更改。DOMException
目前在xml.dom.minidom
中不受支援。相反,xml.dom.minidom
使用標準的 Python 異常,例如TypeError
和AttributeError
。NodeList
物件是使用 Python 的內建列表型別實現的。這些物件提供 DOM 規範中定義的介面,但使用早期版本的 Python 時,它們不支援官方 API。然而,它們比 W3C 建議中定義的介面更“Pythonic”。
以下介面在 xml.dom.minidom
中沒有實現
DOMTimeStamp
EntityReference
其中大多數反映 XML 文件中的資訊,這些資訊對大多數 DOM 使用者來說不是通用的。
腳註