xml.dom.minidom
— 最小 DOM 實現¶
xml.dom.minidom
是文件物件模型介面的最小實現,其 API 與其他語言中的類似。它旨在比完整 DOM 更簡單,也顯著更小。不熟悉 DOM 的使用者應考慮使用 xml.etree.ElementTree
模組進行 XML 處理。
備註
如果您需要解析不受信任或未經身份驗證的資料,請參閱 XML 安全。
DOM 應用程式通常從將一些 XML 解析為 DOM 開始。使用 xml.dom.minidom
,這透過解析函式完成
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
包中的 getDOMImplementation()
函式或 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 的擴充套件,它使節點及其後代基本無用。否則,Python 的垃圾回收器最終會處理樹中的物件。
參見
- 文件物件模型 (DOM) 級別 1 規範
xml.dom.minidom
支援的 W3C DOM 推薦標準。
DOM 物件¶
Python 的 DOM API 定義作為 xml.dom
模組文件的一部分提供。本節列出了 API 與 xml.dom.minidom
之間的差異。
- Node.unlink()¶
斷開 DOM 內部引用,以便在沒有迴圈 GC 的 Python 版本上進行垃圾回收。即使迴圈 GC 可用,使用此方法也可以更早地釋放大量記憶體,因此在不再需要 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 寫入 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 語言對映相容,屬性
foo
也可以透過訪問器方法_get_foo()
和_set_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 使用者沒有普遍實用價值的資訊。
腳註