xml.etree.ElementTree — ElementTree XML API¶
原始碼: Lib/xml/etree/ElementTree.py
xml.etree.ElementTree 模組實現了用於解析和建立 XML 資料的簡單高效的 API。
3.3 版本中的更改: 此模組將在可用時使用快速實現。
自 3.3 版本棄用: xml.etree.cElementTree 模組已棄用。
備註
如果您需要解析不受信任或未經身份驗證的資料,請參閱 XML 安全。
教程¶
這是使用 xml.etree.ElementTree(簡稱 ET)的簡短教程。目的是演示模組的一些構建塊和基本概念。
XML 樹和元素¶
XML 是一種固有的層次化資料格式,最自然的表示方式是樹。ET 為此提供了兩個類——ElementTree 表示整個 XML 文件的樹,而 Element 表示樹中的單個節點。與整個文件的互動(從檔案讀取和寫入)通常在 ElementTree 級別進行。與單個 XML 元素及其子元素的互動在 Element 級別進行。
解析 XML¶
我們將使用虛構的 country_data.xml XML 文件作為本節的示例資料
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
我們可以透過從檔案讀取來匯入此資料
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
或者直接從字串中讀取
root = ET.fromstring(country_data_as_string)
fromstring() 直接將字串中的 XML 解析為 Element,它是解析樹的根元素。其他解析函式可能會建立 ElementTree。請查閱文件以確保。
作為 Element,root 有一個標籤和屬性字典
>>> root.tag
'data'
>>> root.attrib
{}
它也有子節點,我們可以迭代它們
>>> for child in root:
... print(child.tag, child.attrib)
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}
子節點是巢狀的,我們可以透過索引訪問特定的子節點
>>> root[0][1].text
'2008'
備註
並非所有 XML 輸入的元素都會成為解析樹的元素。目前,此模組跳過輸入中的任何 XML 註釋、處理指令和文件型別宣告。然而,使用此模組的 API 而不是從 XML 文字解析構建的樹可以包含註釋和處理指令;它們將在生成 XML 輸出時包含在內。可以透過將自定義 TreeBuilder 例項傳遞給 XMLParser 建構函式來訪問文件型別宣告。
用於非阻塞解析的 Pull API¶
此模組提供的大多數解析函式都需要一次性讀取整個文件才能返回任何結果。可以使用 XMLParser 並逐步向其饋送資料,但它是一個推式 API,在回撥目標上呼叫方法,這對於大多數需求來說太底層且不方便。有時使用者真正想要的是能夠增量解析 XML,而無需阻塞操作,同時享受完全構建的 Element 物件的便利。
實現此目的最強大的工具是 XMLPullParser。它不需要阻塞讀取來獲取 XML 資料,而是透過 XMLPullParser.feed() 呼叫逐步饋送資料。要獲取解析的 XML 元素,請呼叫 XMLPullParser.read_events()。這是一個示例
>>> parser = ET.XMLPullParser(['start', 'end'])
>>> parser.feed('<mytag>sometext')
>>> list(parser.read_events())
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
>>> parser.feed(' more text</mytag>')
>>> for event, elem in parser.read_events():
... print(event)
... print(elem.tag, 'text=', elem.text)
...
end
mytag text= sometext more text
顯而易見的用例是應用程式以非阻塞方式執行,其中 XML 資料正在從套接字接收或從某些儲存裝置增量讀取。在這種情況下,阻塞讀取是不可接受的。
由於其高度靈活性,XMLPullParser 對於簡單用例可能不方便使用。如果您不介意應用程式在讀取 XML 資料時阻塞,但仍然希望具有增量解析功能,請檢視 iterparse()。當您正在讀取大型 XML 文件並且不想將其完全儲存在記憶體中時,它會很有用。
如果需要透過事件獲得 即時 反饋,呼叫方法 XMLPullParser.flush() 可以幫助減少延遲;請務必研究相關的安全說明。
查詢感興趣的元素¶
Element 有一些有用的方法,可以幫助遞迴迭代其下的所有子樹(其子元素、孫元素等)。例如,Element.iter()
>>> for neighbor in root.iter('neighbor'):
... print(neighbor.attrib)
...
{'name': 'Austria', 'direction': 'E'}
{'name': 'Switzerland', 'direction': 'W'}
{'name': 'Malaysia', 'direction': 'N'}
{'name': 'Costa Rica', 'direction': 'W'}
{'name': 'Colombia', 'direction': 'E'}
Element.findall() 僅查詢標籤是當前元素的直接子元素的元素。Element.find() 查詢具有特定標籤的 第一個 子元素,Element.text 訪問元素的文字內容。Element.get() 訪問元素的屬性
>>> for country in root.findall('country'):
... rank = country.find('rank').text
... name = country.get('name')
... print(name, rank)
...
Liechtenstein 1
Singapore 4
Panama 68
透過使用 XPath 可以進行更復雜的元素查詢規範。
修改 XML 檔案¶
ElementTree 提供了一種構建 XML 文件並將其寫入檔案的簡單方法。ElementTree.write() 方法用於此目的。
一旦建立,Element 物件可以透過直接更改其欄位(例如 Element.text)、新增和修改屬性(Element.set() 方法)以及新增新子元素(例如使用 Element.append())來操作。
假設我們希望將每個國家的排名加一,並向排名元素新增一個 updated 屬性
>>> for rank in root.iter('rank'):
... new_rank = int(rank.text) + 1
... rank.text = str(new_rank)
... rank.set('updated', 'yes')
...
>>> tree.write('output.xml')
我們的 XML 現在看起來像這樣
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
我們可以使用 Element.remove() 刪除元素。假設我們想要刪除所有排名高於 50 的國家
>>> for country in root.findall('country'):
... # using root.findall() to avoid removal during traversal
... rank = int(country.find('rank').text)
... if rank > 50:
... root.remove(country)
...
>>> tree.write('output.xml')
請注意,迭代時併發修改可能會導致問題,就像迭代和修改 Python 列表或字典時一樣。因此,示例首先使用 root.findall() 收集所有匹配的元素,然後才迭代匹配列表。
我們的 XML 現在看起來像這樣
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
</data>
構建 XML 文件¶
SubElement() 函式還提供了一種方便的方式為給定元素建立新的子元素
>>> a = ET.Element('a')
>>> b = ET.SubElement(a, 'b')
>>> c = ET.SubElement(a, 'c')
>>> d = ET.SubElement(c, 'd')
>>> ET.dump(a)
<a><b /><c><d /></c></a>
使用名稱空間解析 XML¶
如果 XML 輸入具有名稱空間,則形式為 prefix:sometag 的帶有字首的標籤和屬性將擴充套件為 {uri}sometag,其中 prefix 被完整的 URI 替換。此外,如果存在預設名稱空間,則該完整 URI 將新增到所有未加字首的標籤中。
這是一個包含兩個名稱空間的 XML 示例,一個帶字首“fictional”,另一個用作預設名稱空間
<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"
xmlns="http://people.example.com">
<actor>
<name>John Cleese</name>
<fictional:character>Lancelot</fictional:character>
<fictional:character>Archie Leach</fictional:character>
</actor>
<actor>
<name>Eric Idle</name>
<fictional:character>Sir Robin</fictional:character>
<fictional:character>Gunther</fictional:character>
<fictional:character>Commander Clement</fictional:character>
</actor>
</actors>
搜尋和瀏覽此 XML 示例的一種方法是在 find() 或 findall() 的 xpath 中手動將 URI 新增到每個標籤或屬性
root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):
name = actor.find('{http://people.example.com}name')
print(name.text)
for char in actor.findall('{http://characters.example.com}character'):
print(' |-->', char.text)
搜尋帶名稱空間的 XML 示例的更好方法是使用您自己的字首建立一個字典並在搜尋函式中使用這些字首
ns = {'real_person': 'http://people.example.com',
'role': 'http://characters.example.com'}
for actor in root.findall('real_person:actor', ns):
name = actor.find('real_person:name', ns)
print(name.text)
for char in actor.findall('role:character', ns):
print(' |-->', char.text)
這兩種方法都輸出
John Cleese
|--> Lancelot
|--> Archie Leach
Eric Idle
|--> Sir Robin
|--> Gunther
|--> Commander Clement
XPath 支援¶
此模組對 XPath 表示式 提供了有限的支援,用於在樹中定位元素。目標是支援縮寫語法的一小部分;完整的 XPath 引擎超出模組的範圍。
示例¶
這是一個演示模組某些 XPath 功能的示例。我們將使用 解析 XML 部分中的 countrydata XML 文件
import xml.etree.ElementTree as ET
root = ET.fromstring(countrydata)
# Top-level elements
root.findall(".")
# All 'neighbor' grand-children of 'country' children of the top-level
# elements
root.findall("./country/neighbor")
# Nodes with name='Singapore' that have a 'year' child
root.findall(".//year/..[@name='Singapore']")
# 'year' nodes that are children of nodes with name='Singapore'
root.findall(".//*[@name='Singapore']/year")
# All 'neighbor' nodes that are the second child of their parent
root.findall(".//neighbor[2]")
對於帶名稱空間的 XML,請使用通常的合格 {namespace}tag 符號
# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")
支援的 XPath 語法¶
語法 |
含義 |
|---|---|
|
選擇所有具有給定標籤的子元素。例如, 3.8 版本中的更改: 增加了對星號萬用字元的支援。 |
|
選擇所有子元素,包括註釋和處理指令。例如, |
|
選擇當前節點。這在路徑開頭最有用,表示這是一個相對路徑。 |
|
選擇所有子元素,在當前元素下的所有級別上。例如, |
|
選擇父元素。如果路徑嘗試訪問起始元素(呼叫 |
|
選擇所有具有給定屬性的元素。 |
|
選擇給定屬性具有給定值的所有元素。該值不能包含引號。 |
|
選擇給定屬性不具有給定值的所有元素。該值不能包含引號。 在 3.10 版本加入。 |
|
選擇所有具有名為 |
|
選擇其完整文字內容(包括後代)等於給定 在 3.7 版本加入。 |
|
選擇其完整文字內容(包括後代)不等於給定 在 3.10 版本加入。 |
|
選擇所有具有名為 |
|
選擇所有具有名為 在 3.10 版本加入。 |
|
選擇所有位於給定位置的元素。位置可以是整數(1 是第一個位置),表示式 |
謂詞(方括號內的表示式)必須後跟標籤名、星號或另一個謂詞。position 謂詞必須後跟標籤名。
參考¶
函式¶
- xml.etree.ElementTree.canonicalize(xml_data=None, *, out=None, from_file=None, **options)¶
C14N 2.0 轉換函式。
規範化是一種標準化 XML 輸出的方式,允許逐位元組比較和數字簽名。它減少了 XML 序列化器所擁有的自由,而是生成更受限制的 XML 表示。主要限制涉及名稱空間宣告的位置、屬性的順序和可忽略的空白。
此函式以 XML 資料字串(xml_data)或檔案路徑或類檔案物件(from_file)作為輸入,將其轉換為規範形式,並使用 out 類檔案物件(如果提供)將其寫入,否則將其作為文字字串返回。輸出檔案接收文字,而不是位元組。因此,它應該以文字模式並使用
utf-8編碼開啟。典型用途
xml_data = "<root>...</root>" print(canonicalize(xml_data)) with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file: canonicalize(xml_data, out=out_file) with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file: canonicalize(from_file="inputfile.xml", out=out_file)
配置 options 如下
with_comments:設定為 true 以包含註釋(預設值:false)
- strip_text:設定為 true 以在文字內容前後去除空白
(預設值:false)
- rewrite_prefixes:設定為 true 以將名稱空間字首替換為“n{number}”
(預設值:false)
- qname_aware_tags:一組 qname 感知標籤名,其中字首
應在文字內容中替換(預設值:空)
- qname_aware_attrs:一組 qname 感知屬性名,其中字首
應在文字內容中替換(預設值:空)
exclude_attrs:一組不應序列化的屬性名
exclude_tags:一組不應序列化的標籤名
在上述選項列表中,“一組”指任何字串集合或可迭代物件,不期望任何順序。
在 3.8 版本加入。
- xml.etree.ElementTree.Comment(text=None)¶
註釋元素工廠。此工廠函式建立一個特殊元素,該元素將由標準序列化器序列化為 XML 註釋。註釋字串可以是位元組字串或 Unicode 字串。text 是包含註釋字串的字串。返回表示註釋的元素例項。
請注意,
XMLParser會跳過輸入中的註釋,而不是為它們建立註釋物件。ElementTree僅當使用Element方法之一將註釋節點插入樹中時,才會包含註釋節點。
- xml.etree.ElementTree.dump(elem)¶
將元素樹或元素結構寫入 sys.stdout。此函式僅應用於除錯。
確切的輸出格式取決於實現。在此版本中,它作為普通 XML 檔案寫入。
elem 是一個元素樹或單個元素。
3.8 版本中的更改:
dump()函式現在保留使用者指定的屬性順序。
- xml.etree.ElementTree.fromstring(text, parser=None)¶
從字串常量解析 XML 片段。與
XML()相同。text 是包含 XML 資料的字串。parser 是可選的解析器例項。如果未給出,則使用標準XMLParser解析器。返回Element例項。
- xml.etree.ElementTree.fromstringlist(sequence, parser=None)¶
從字串片段序列解析 XML 文件。sequence 是包含 XML 資料片段的列表或其他序列。parser 是可選的解析器例項。如果未給出,則使用標準
XMLParser解析器。返回Element例項。在 3.2 版本加入。
- xml.etree.ElementTree.indent(tree, space=' ', level=0)¶
向子樹新增空白以在視覺上縮排樹。這可用於生成漂亮的 XML 輸出。tree 可以是 Element 或 ElementTree。space 是每個縮排級別將插入的空白字串,預設為兩個空格字元。對於在已縮排樹中縮排部分子樹,將初始縮排級別作為 level 傳遞。
在 3.9 版本中新增。
- xml.etree.ElementTree.iselement(element)¶
檢查物件是否似乎是有效的元素物件。element 是一個元素例項。如果是元素物件,則返回
True。
- xml.etree.ElementTree.iterparse(source, events=None, parser=None)¶
將 XML 片段逐步解析為元素樹,並向用戶報告正在發生的事情。source 是包含 XML 資料的檔名或 檔案物件。events 是要報告的事件序列。支援的事件是字串
"start"、"end"、"comment"、"pi"、"start-ns"和"end-ns"(“ns”事件用於獲取詳細的名稱空間資訊)。如果省略 events,則只報告"end"事件。parser 是可選的解析器例項。如果未給出,則使用標準XMLParser解析器。parser 必須是XMLParser的子類,並且只能使用預設的TreeBuilder作為目標。返回一個提供(event, elem)對的 迭代器;一旦 source 完全讀取,它就有一個引用結果 XML 樹的根元素的root屬性。如果 source 是檔名,迭代器具有close()方法,用於關閉內部檔案物件。請注意,儘管
iterparse()增量構建樹,但它對 source(或其命名的檔案)發出阻塞讀取。因此,它不適用於無法進行阻塞讀取的應用程式。對於完全非阻塞解析,請參閱XMLPullParser。備註
iterparse()只保證在發出“start”事件時看到了起始標籤的“>”字元,因此屬性已定義,但文字和尾部屬性的內容在該點未定義。元素子元素也是如此;它們可能存在也可能不存在。如果需要完全填充的元素,請改為查詢“end”事件。
自 3.4 版本棄用: parser 引數。
3.8 版本中的更改: 添加了
comment和pi事件。3.13 版本中的更改: 添加了
close()方法。
- xml.etree.ElementTree.parse(source, parser=None)¶
將 XML 片段解析為元素樹。source 是包含 XML 資料的檔名或檔案物件。parser 是可選的解析器例項。如果未給出,則使用標準
XMLParser解析器。返回ElementTree例項。
- xml.etree.ElementTree.ProcessingInstruction(target, text=None)¶
PI 元素工廠。此工廠函式建立一個特殊元素,該元素將序列化為 XML 處理指令。target 是包含 PI 目標的字串。如果給出 text,則為包含 PI 內容的字串。返回表示處理指令的元素例項。
請注意,
XMLParser會跳過輸入中的處理指令,而不是為它們建立 PI 物件。ElementTree僅當使用Element方法之一將處理指令節點插入樹中時,才會包含處理指令節點。
- xml.etree.ElementTree.register_namespace(prefix, uri)¶
註冊名稱空間字首。登錄檔是全域性的,任何給定字首或名稱空間 URI 的現有對映都將被刪除。prefix 是名稱空間字首。uri 是名稱空間 URI。此名稱空間中的標籤和屬性將盡可能使用給定字首進行序列化。
在 3.2 版本加入。
- xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)¶
子元素工廠。此函式建立元素例項,並將其附加到現有元素。
元素名稱、屬性名稱和屬性值可以是位元組字串或 Unicode 字串。parent 是父元素。tag 是子元素名稱。attrib 是可選字典,包含元素屬性。extra 包含作為關鍵字引數給出的附加屬性。返回元素例項。
- xml.etree.ElementTree.tostring(element, encoding='us-ascii', method='xml', *, xml_declaration=None, default_namespace=None, short_empty_elements=True)¶
生成 XML 元素的字串表示,包括所有子元素。element 是一個
Element例項。encoding [1] 是輸出編碼(預設為 US-ASCII)。使用encoding="unicode"生成 Unicode 字串(否則,生成位元組字串)。method 是"xml"、"html"或"text"之一(預設為"xml")。xml_declaration、default_namespace 和 short_empty_elements 的含義與ElementTree.write()中相同。返回包含 XML 資料的(可選)編碼字串。3.4 版本中的更改: 添加了 short_empty_elements 引數。
3.8 版本中的更改: 添加了 xml_declaration 和 default_namespace 引數。
3.8 版本中的更改:
tostring()函式現在保留使用者指定的屬性順序。
- xml.etree.ElementTree.tostringlist(element, encoding='us-ascii', method='xml', *, xml_declaration=None, default_namespace=None, short_empty_elements=True)¶
生成 XML 元素的字串表示,包括所有子元素。element 是一個
Element例項。encoding [1] 是輸出編碼(預設為 US-ASCII)。使用encoding="unicode"生成 Unicode 字串(否則,生成位元組字串)。method 是"xml"、"html"或"text"之一(預設為"xml")。xml_declaration、default_namespace 和 short_empty_elements 的含義與ElementTree.write()中相同。返回包含 XML 資料的(可選)編碼字串列表。它不保證任何特定的序列,除了b"".join(tostringlist(element)) == tostring(element)。在 3.2 版本加入。
3.4 版本中的更改: 添加了 short_empty_elements 引數。
3.8 版本中的更改: 添加了 xml_declaration 和 default_namespace 引數。
3.8 版本中的更改:
tostringlist()函式現在保留使用者指定的屬性順序。
XInclude 支援¶
此模組透過 xml.etree.ElementInclude 輔助模組為 XInclude 指令 提供有限支援。此模組可用於根據樹中的資訊將子樹和文字字串插入元素樹中。
示例¶
這是一個演示 XInclude 模組用法的示例。要在當前文件中包含 XML 文件,請使用 {http://www.w3.org/2001/XInclude}include 元素並將 parse 屬性設定為 "xml",並使用 href 屬性指定要包含的文件。
<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="source.xml" parse="xml" />
</document>
預設情況下,href 屬性被視為檔名。您可以使用自定義載入器覆蓋此行為。另請注意,標準助手不支援 XPointer 語法。
要處理此檔案,請像往常一樣載入它,並將根元素傳遞給 xml.etree.ElementTree 模組
from xml.etree import ElementTree, ElementInclude
tree = ElementTree.parse("document.xml")
root = tree.getroot()
ElementInclude.include(root)
ElementInclude 模組將 {http://www.w3.org/2001/XInclude}include 元素替換為 source.xml 文件中的根元素。結果可能看起來像這樣
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<para>This is a paragraph.</para>
</document>
如果省略 parse 屬性,則預設為“xml”。href 屬性是必需的。
要包含文字文件,請使用 {http://www.w3.org/2001/XInclude}include 元素,並將 parse 屬性設定為“text”
<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
Copyright (c) <xi:include href="year.txt" parse="text" />.
</document>
結果可能看起來像
<document xmlns:xi="http://www.w3.org/2001/XInclude">
Copyright (c) 2003.
</document>
參考¶
函式¶
- xml.etree.ElementInclude.default_loader(href, parse, encoding=None)¶
預設載入器。此預設載入器從磁碟讀取包含的資源。href 是一個 URL。parse 用於解析模式,“xml”或“text”。encoding 是可選的文字編碼。如果未給出,則編碼為
utf-8。返回展開的資源。如果解析模式是"xml",則這是一個Element例項。如果解析模式是"text",則這是一個字串。如果載入器失敗,它可以返回None或引發異常。
- xml.etree.ElementInclude.include(elem, loader=None, base_url=None, max_depth=6)¶
此函式在 elem 指向的樹中原地展開 XInclude 指令。elem 是根
Element或ElementTree例項,用於查詢此類元素。loader 是可選的資源載入器。如果省略,則預設為default_loader()。如果給出,它應該是一個可呼叫物件,實現與default_loader()相同的介面。base_url 是原始檔案的基本 URL,用於解析相對包含檔案引用。max_depth 是遞迴包含的最大數量。限制以減少惡意內容爆炸的風險。傳遞None以停用此限制。3.9 版本中的更改: 添加了 base_url 和 max_depth 引數。
元素物件¶
- class xml.etree.ElementTree.Element(tag, attrib={}, **extra)¶
元素類。此類定義了元素介面,並提供了此介面的參考實現。
元素名稱、屬性名稱和屬性值可以是位元組字串或 Unicode 字串。tag 是元素名稱。attrib 是可選的字典,包含元素屬性。extra 包含作為關鍵字引數給出的附加屬性。
- tag¶
一個字串,用於標識此元素代表的資料型別(換句話說,元素型別)。
- text¶
- tail¶
這些屬性可用於儲存與元素關聯的附加資料。它們的值通常是字串,但可以是任何特定於應用程式的物件。如果元素是從 XML 檔案建立的,則 text 屬性儲存元素起始標籤與其第一個子元素或結束標籤之間的文字,或者
None;tail 屬性儲存元素結束標籤與下一個標籤之間的文字,或者None。對於 XML 資料<a><b>1<c>2<d/>3</c></b>4</a>
a 元素的 text 和 tail 屬性均為
None;b 元素的 text 為"1",tail 為"4";c 元素的 text 為"2",tail 為None;d 元素的 text 為None,tail 為"3"。要收集元素的內部文字,請參閱
itertext(),例如"".join(element.itertext())。應用程式可以在這些屬性中儲存任意物件。
- attrib¶
包含元素屬性的字典。請注意,雖然 attrib 值始終是真正的可變 Python 字典,但 ElementTree 實現可以選擇使用另一種內部表示,並且僅當有人請求時才建立字典。為了利用此類實現,請儘可能使用下面的字典方法。
以下類字典方法適用於元素屬性。
- clear()¶
重置一個元素。此函式刪除所有子元素,清除所有屬性,並將文字和尾部屬性設定為
None。
- get(key, default=None)¶
獲取名為 key 的元素屬性。
返回屬性值,如果未找到屬性,則返回 default。
- items()¶
將元素屬性作為 (名稱, 值) 對的序列返回。屬性以任意順序返回。
- keys()¶
將元素屬性名稱作為列表返回。名稱以任意順序返回。
- set(key, value)¶
將元素上屬性 key 的值設定為 value。
以下方法適用於元素的子元素。
- find(match, namespaces=None)¶
查詢與 match 匹配的第一個子元素。match 可以是標籤名稱或 路徑。返回元素例項或
None。namespaces 是從名稱空間字首到完整名稱的可選對映。傳遞''作為字首,將表示式中所有未加字首的標籤名稱移動到給定名稱空間中。
- findall(match, namespaces=None)¶
透過標籤名稱或 路徑 查詢所有匹配的子元素。返回一個列表,其中包含按文件順序排列的所有匹配元素。namespaces 是從名稱空間字首到完整名稱的可選對映。傳遞
''作為字首,將表示式中所有未加字首的標籤名稱移動到給定名稱空間中。
- findtext(match, default=None, namespaces=None)¶
查詢與 match 匹配的第一個子元素的文字。match 可以是標籤名稱或 路徑。返回第一個匹配元素的文字內容,如果沒有找到元素,則返回 default。請注意,如果匹配元素沒有文字內容,則返回空字串。namespaces 是從名稱空間字首到完整名稱的可選對映。傳遞
''作為字首,將表示式中所有未加字首的標籤名稱移動到給定名稱空間中。
- iter(tag=None)¶
建立一個以當前元素為根的樹 迭代器。迭代器按照文件(深度優先)順序迭代此元素及其下面的所有元素。如果 tag 不是
None或'*',則迭代器僅返回標籤等於 tag 的元素。如果在迭代期間修改了樹結構,則結果未定義。在 3.2 版本加入。
- iterfind(match, namespaces=None)¶
透過標籤名稱或 路徑 查詢所有匹配的子元素。返回一個可迭代物件,按文件順序生成所有匹配元素。namespaces 是從名稱空間字首到完整名稱的可選對映。
在 3.2 版本加入。
- itertext()¶
建立文字迭代器。迭代器遍歷此元素和所有子元素,按文件順序返回所有內部文字。
在 3.2 版本加入。
- makeelement(tag, attrib)¶
建立與此元素相同型別的新元素物件。不要呼叫此方法,請改用
SubElement()工廠函式。
- remove(subelement)¶
從元素中刪除 subelement。與 find* 方法不同,此方法基於例項標識(而非標籤值或內容)比較元素。
Element物件還支援以下序列型別方法用於處理子元素:__delitem__()、__getitem__()、__setitem__()、__len__()。注意:沒有子元素的元素將測試為
False。在 Python 的未來版本中,所有元素都將測試為True,無論是否存在子元素。因此,請優先使用顯式len(elem)或elem is not None測試。element = root.find('foo') if not element: # careful! print("element not found, or element has no subelements") if element is None: print("element not found")
3.12 版本中的更改: 測試 Element 的真值會發出
DeprecationWarning。在 Python 3.8 之前,透過按名稱對屬性進行排序,人為地使元素的 XML 屬性的序列化順序可預測。基於現在保證的字典順序,此任意重新排序在 Python 3.8 中被刪除,以保留屬性最初由使用者程式碼解析或建立的順序。
通常,使用者程式碼不應依賴於特定的屬性順序,因為 XML 資訊集 明確排除屬性順序傳達資訊。程式碼應準備好處理輸入中的任何順序。在需要確定性 XML 輸出的情況下,例如用於加密簽名或測試資料集,可以使用
canonicalize()函式進行規範化序列化。在不適用規範輸出但仍希望輸出特定屬性順序的情況下,程式碼應旨在直接以所需順序建立屬性,以避免程式碼讀者感知上的不匹配。如果這難以實現,則可以在序列化之前應用以下方法來強制執行獨立於元素建立的順序
def reorder_attributes(root): for el in root.iter(): attrib = el.attrib if len(attrib) > 1: # adjust attribute order, e.g. by sorting attribs = sorted(attrib.items()) attrib.clear() attrib.update(attribs)
ElementTree 物件¶
- class xml.etree.ElementTree.ElementTree(element=None, file=None)¶
ElementTree 包裝類。此類表示整個元素層次結構,並增加了對與標準 XML 之間進行序列化的額外支援。
element 是根元素。如果給定 XML file,則樹將使用其內容進行初始化。
- _setroot(element)¶
替換此樹的根元素。這將丟棄樹的當前內容,並將其替換為給定元素。請謹慎使用。element 是一個元素例項。
- find(match, namespaces=None)¶
與
Element.find()相同,從樹的根開始。
- findall(match, namespaces=None)¶
與
Element.findall()相同,從樹的根開始。
- findtext(match, default=None, namespaces=None)¶
與
Element.findtext()相同,從樹的根開始。
- getroot()¶
返回此樹的根元素。
- iter(tag=None)¶
為根元素建立並返回一個樹迭代器。迭代器按章節順序遍歷此樹中的所有元素。tag 是要查詢的標籤(預設為返回所有元素)。
- iterfind(match, namespaces=None)¶
與
Element.iterfind()相同,從樹的根部開始查詢。在 3.2 版本加入。
- parse(source, parser=None)¶
將外部 XML 部分載入到此元素樹中。source 是一個檔名或 檔案物件。parser 是可選的解析器例項。如果未給定,則使用標準
XMLParser解析器。返回該部分的根元素。
- write(file, encoding='us-ascii', xml_declaration=None, default_namespace=None, method='xml', *, short_empty_elements=True)¶
將元素樹作為 XML 寫入檔案。file 是一個檔名,或一個為寫入而開啟的 檔案物件。encoding [1] 是輸出編碼(預設為 US-ASCII)。xml_declaration 控制是否應將 XML 宣告新增到檔案中。使用
False表示從不新增,True表示始終新增,None表示僅在非 US-ASCII、UTF-8 或 Unicode 時新增(預設為None)。default_namespace 設定預設的 XML 名稱空間(對於“xmlns”)。method 可以是"xml"、"html"或"text"(預設為"xml")。僅限關鍵字引數 short_empty_elements 控制不包含內容的元素的格式。如果為True(預設值),它們將作為單個自閉合標籤發出,否則它們將作為一對開始/結束標籤發出。輸出可以是字串(
str)或二進位制(bytes)。這由 encoding 引數控制。如果 encoding 是"unicode",則輸出是字串;否則,它是二進位制。請注意,如果 file 是一個開啟的 檔案物件,這可能會與 file 的型別衝突;請確保不要嘗試將字串寫入二進位制流,反之亦然。3.4 版本中的更改: 添加了 short_empty_elements 引數。
3.8 版本發生變更:
write()方法現在保留使用者指定的屬性順序。
這是將要操作的 XML 檔案
<html>
<head>
<title>Example page</title>
</head>
<body>
<p>Moved to <a href="http://example.org/">example.org</a>
or <a href="http://example.com/">example.com</a>.</p>
</body>
</html>
更改第一個段落中每個連結的“target”屬性的示例
>>> from xml.etree.ElementTree import ElementTree
>>> tree = ElementTree()
>>> tree.parse("index.xhtml")
<Element 'html' at 0xb77e6fac>
>>> p = tree.find("body/p") # Finds first occurrence of tag p in body
>>> p
<Element 'p' at 0xb77ec26c>
>>> links = list(p.iter("a")) # Returns list of all links
>>> links
[<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
>>> for i in links: # Iterates through all found links
... i.attrib["target"] = "blank"
...
>>> tree.write("output.xhtml")
QName 物件¶
TreeBuilder 物件¶
- class xml.etree.ElementTree.TreeBuilder(element_factory=None, *, comment_factory=None, pi_factory=None, insert_comments=False, insert_pis=False)¶
通用元素結構構建器。此構建器將一系列 start、data、end、comment 和 pi 方法呼叫轉換為格式良好的元素結構。您可以使用此類別使用自定義 XML 解析器或用於其他類似 XML 格式的解析器構建元素結構。
如果給定 element_factory,它必須是一個可呼叫物件,接受兩個位置引數:標籤和屬性字典。它應返回一個新的元素例項。
如果給定 comment_factory 和 pi_factory 函式,它們應像
Comment()和ProcessingInstruction()函式一樣,用於建立註釋和處理指令。如果未給定,則使用預設工廠。當 insert_comments 和/或 insert_pis 為真時,如果註釋/pi 出現在根元素內(但不在根元素之外),它們將被插入到樹中。- data(data)¶
向當前元素新增文字。data 是一個字串。這應該是一個位元組字串或 Unicode 字串。
- end(tag)¶
關閉當前元素。tag 是元素名稱。返回關閉的元素。
- start(tag, attrs)¶
開啟一個新元素。tag 是元素名稱。attrs 是一個包含元素屬性的字典。返回開啟的元素。
- comment(text)¶
使用給定的 text 建立註釋。如果
insert_comments為真,這也會將其新增到樹中。在 3.8 版本加入。
- pi(target, text)¶
使用給定的 target 名稱和 text 建立處理指令。如果
insert_pis為真,這也會將其新增到樹中。在 3.8 版本加入。
此外,自定義
TreeBuilder物件可以提供以下方法- doctype(name, pubid, system)¶
處理 doctype 宣告。name 是 doctype 名稱。pubid 是公共識別符號。system 是系統識別符號。此方法在預設的
TreeBuilder類中不存在。在 3.2 版本加入。
- start_ns(prefix, uri)¶
當解析器遇到新的名稱空間宣告時呼叫,在定義該宣告的起始元素的
start()回撥之前。prefix 對於預設名稱空間是'',否則是宣告的名稱空間字首名稱。uri 是名稱空間 URI。在 3.8 版本加入。
- end_ns(prefix)¶
在一個聲明瞭名稱空間字首對映的元素的
end()回撥之後呼叫,並帶有超出範圍的 prefix 名稱。在 3.8 版本加入。
- class xml.etree.ElementTree.C14NWriterTarget(write, *, with_comments=False, strip_text=False, rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None, exclude_attrs=None, exclude_tags=None)¶
一個 C14N 2.0 寫入器。引數與
canonicalize()函式的引數相同。此類不構建樹,而是使用 write 函式將回調事件直接轉換為序列化形式。在 3.8 版本加入。
XMLParser 物件¶
- class xml.etree.ElementTree.XMLParser(*, target=None, encoding=None)¶
此類是模組的低階構建塊。它使用
xml.parsers.expat進行高效、基於事件的 XML 解析。可以使用feed()方法增量地向其提供 XML 資料,解析事件透過呼叫 target 物件上的回撥函式轉換為推式 API。如果省略 target,則使用標準TreeBuilder。如果給定 encoding [1],則該值將覆蓋 XML 檔案中指定的編碼。3.8 版本發生變更: 引數現在是 僅限關鍵字。不再支援 html 引數。
- close()¶
完成向解析器提供資料。返回呼叫構造期間傳入的 target 的
close()方法的結果;預設情況下,這是頂層文件元素。
- feed(data)¶
向解析器提供資料。data 是編碼資料。
- flush()¶
觸發對所有先前提供的未解析資料的解析,這可用於確保更即時的反饋,特別是對於 Expat >=2.6.0。
flush()的實現暫時停用 Expat 的重新解析延遲(如果當前已啟用)並觸發重新解析。停用重新解析延遲具有安全隱患;有關詳細資訊,請參閱xml.parsers.expat.xmlparser.SetReparseDeferralEnabled()。請注意,
flush()已作為安全修復程式向後移植到 CPython 的某些早期版本。如果在各種 Python 版本上執行的程式碼中使用flush(),請使用hasattr()檢查其可用性。在 3.13 版本加入。
XMLParser.feed()為每個開始標籤呼叫 target 的start(tag, attrs_dict)方法,為每個結束標籤呼叫其end(tag)方法,資料由方法data(data)處理。有關進一步支援的回撥方法,請參閱TreeBuilder類。XMLParser.close()呼叫 target 的方法close()。XMLParser不僅可以用於構建樹結構。這是一個計算 XML 檔案最大深度的示例>>> from xml.etree.ElementTree import XMLParser >>> class MaxDepth: # The target object of the parser ... maxDepth = 0 ... depth = 0 ... def start(self, tag, attrib): # Called for each opening tag. ... self.depth += 1 ... if self.depth > self.maxDepth: ... self.maxDepth = self.depth ... def end(self, tag): # Called for each closing tag. ... self.depth -= 1 ... def data(self, data): ... pass # We do not need to do anything with data. ... def close(self): # Called when all data has been parsed. ... return self.maxDepth ... >>> target = MaxDepth() >>> parser = XMLParser(target=target) >>> exampleXml = """ ... <a> ... <b> ... </b> ... <b> ... <c> ... <d> ... </d> ... </c> ... </b> ... </a>""" >>> parser.feed(exampleXml) >>> parser.close() 4
XMLPullParser 物件¶
- class xml.etree.ElementTree.XMLPullParser(events=None)¶
一個適用於非阻塞應用程式的拉取解析器。其輸入端 API 與
XMLParser類似,但XMLPullParser不會向回撥目標推送呼叫,而是收集一個內部解析事件列表,並允許使用者從中讀取。events 是要報告的事件序列。支援的事件是字串"start"、"end"、"comment"、"pi"、"start-ns"和"end-ns"(“ns”事件用於獲取詳細的名稱空間資訊)。如果省略 events,則只報告"end"事件。- feed(data)¶
向解析器提供給定的位元組資料。
- flush()¶
觸發對所有先前提供的未解析資料的解析,這可用於確保更即時的反饋,特別是對於 Expat >=2.6.0。
flush()的實現暫時停用 Expat 的重新解析延遲(如果當前已啟用)並觸發重新解析。停用重新解析延遲具有安全隱患;有關詳細資訊,請參閱xml.parsers.expat.xmlparser.SetReparseDeferralEnabled()。請注意,
flush()已作為安全修復程式向後移植到 CPython 的某些早期版本。如果在各種 Python 版本上執行的程式碼中使用flush(),請使用hasattr()檢查其可用性。在 3.13 版本加入。
- close()¶
通知解析器資料流已終止。與
XMLParser.close()不同,此方法總是返回None。解析器關閉時尚未檢索到的任何事件仍然可以透過read_events()讀取。
- read_events()¶
返回一個迭代器,用於遍歷已在提供給解析器的資料中遇到的事件。迭代器產生
(event, elem)對,其中 event 是表示事件型別(例如"end")的字串,elem 是遇到的Element物件,或其他上下文值,如下所示。start,end: 當前元素。comment,pi: 當前註釋/處理指令start-ns: 一個元組(prefix, uri),命名宣告的名稱空間對映。end-ns:None(這在未來的版本中可能會改變)
在之前呼叫
read_events()中提供的事件將不會再次產生。事件只有在從迭代器中檢索時才從內部佇列中消耗,因此多個讀取器並行迭代從read_events()獲得的迭代器將產生不可預測的結果。
備註
XMLPullParser僅保證在發出“start”事件時已看到起始標籤的“>”字元,因此屬性已定義,但文字和尾部屬性的內容在該點未定義。元素子元素也適用同樣的情況;它們可能存在,也可能不存在。如果需要完全填充的元素,請改為查詢“end”事件。
在 3.4 版本加入。
3.8 版本中的更改: 添加了
comment和pi事件。
異常¶
- class xml.etree.ElementTree.ParseError¶
XML 解析錯誤,當解析失敗時由本模組中的各種解析方法引發。此異常例項的字串表示將包含使用者友好的錯誤訊息。此外,它將具有以下可用屬性
- code¶
來自 expat 解析器的數字錯誤程式碼。有關錯誤程式碼及其含義的列表,請參閱
xml.parsers.expat的文件。
- position¶
一個 line、column 數字元組,指定錯誤發生的位置。
腳註