xml.etree.ElementTree — ElementTree XML API

原始碼: Lib/xml/etree/ElementTree.py


xml.etree.ElementTree 模組實現了一個簡單高效的 API,用於解析和建立 XML 資料。

在 3.3 版本中變更: 此模組將在可用時使用快速實現。

自 3.3 版本起棄用: xml.etree.cElementTree 模組已被棄用。

警告

xml.etree.ElementTree 模組對於惡意構造的資料不安全。 如果需要解析不受信任或未經身份驗證的資料,請參閱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。 請檢視文件以確保。

作為 Elementroot 有一個標籤和一個屬性字典

>>> 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.text),新增和修改屬性(Element.set() 方法),以及新增新的子元素(例如使用 Element.append())來操作 Element 物件。

假設我們想將每個國家的排名加一,並在排名元素中新增一個 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 示例的一種方法是將 URI 手動新增到 find()findall() 的 xpath 中的每個標籤或屬性。

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 語法

語法

含義

tag

選擇所有具有給定標籤的子元素。 例如, spam 選擇所有名為 spam 的子元素,而 spam/egg 選擇所有在所有名為 spam 的子元素中名為 egg 的孫子元素。 {namespace}* 選擇給定名稱空間中的所有標籤,{*}spam 選擇任何(或沒有)名稱空間中名為 spam 的標籤,而 {}* 僅選擇不在名稱空間中的標籤。

在 3.8 版本中更改:添加了對星號萬用字元的支援。

*

選擇所有子元素,包括註釋和處理指令。例如,*/egg 選擇所有名為 egg 的孫子元素。

.

選擇當前節點。 這在路徑的開頭最有用,用於指示它是相對路徑。

//

選擇當前元素下所有級別上的所有子元素。 例如,.//egg 選擇整個樹中的所有 egg 元素。

..

選擇父元素。 如果路徑試圖到達起始元素(呼叫 find 的元素)的祖先,則返回 None

[@attrib]

選擇所有具有給定屬性的元素。

[@attrib='value']

選擇給定屬性具有給定值的所有元素。 該值不能包含引號。

[@attrib!='value']

選擇給定屬性不具有給定值的所有元素。 該值不能包含引號。

在 3.10 版本中新增。

[tag]

選擇所有具有名為 tag 的子元素的元素。 僅支援直接子元素。

[.='text']

選擇所有完整文字內容(包括後代)等於給定 text 的元素。

在 3.7 版本中新增。

[.!='text']

選擇所有完整文字內容(包括後代)不等於給定 text 的元素。

在 3.10 版本中新增。

[tag='text']

選擇所有具有名為 tag 的子元素,且該子元素的完整文字內容(包括後代)等於給定 text 的元素。

[tag!='text']

選擇所有具有名為 tag 的子元素,且該子元素的完整文字內容(包括後代)不等於給定 text 的元素。

在 3.10 版本中新增。

[position]

選擇所有位於給定位置的元素。 位置可以是整數(1 是第一個位置),表示式 last() (表示最後一個位置),或者是相對於最後一個位置的位置(例如,last()-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 跳過輸入中的註釋,而不是為它們建立註釋物件。只有當使用 Element 方法之一將註釋節點插入到樹中時,ElementTree 才會包含註釋節點。

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) 對的 迭代器;它有一個 root 屬性,該屬性引用一旦完全讀取 source 後生成的 XML 樹的根元素。如果 source 是檔名,則迭代器具有關閉內部檔案物件的 close() 方法。

請注意,雖然 iterparse() 會增量地構建樹,但它會在 source(或它命名的檔案)上發出阻塞讀取。因此,它不適用於無法進行阻塞讀取的應用程式。有關完全非阻塞的解析,請參閱 XMLPullParser

註解

iterparse() 發出 “start” 事件時,它僅保證它已看到開始標記的 “>” 字元,因此屬性已定義,但此時文字和 tail 屬性的內容未定義。這同樣適用於元素子元素;它們可能存在也可能不存在。

如果您需要完全填充的元素,請查詢 “end” 事件。

自 3.4 版本起已棄用: parser 引數。

在 3.8 版本中更改: 添加了 commentpi 事件。

在 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 物件。只有當使用 Element 方法之一將處理指令節點插入到樹中時,ElementTree 才會包含處理指令節點。

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_declarationdefault_namespaceshort_empty_elements 的含義與 ElementTree.write() 中相同。返回一個(可選)編碼的包含 XML 資料的字串。

在 3.4 版本中更改: 添加了 short_empty_elements 引數。

在 3.8 版本中更改: 添加了 xml_declarationdefault_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_declarationdefault_namespaceshort_empty_elements 的含義與 ElementTree.write() 中相同。返回一個(可選)編碼的包含 XML 資料的字串列表。它不保證任何特定的順序,但保證 b"".join(tostringlist(element)) == tostring(element)

在 3.2 版本中新增。

在 3.4 版本中更改: 添加了 short_empty_elements 引數。

在 3.8 版本中更改: 添加了 xml_declarationdefault_namespace 引數。

在 3.8 版本中更改: tostringlist() 函式現在保留使用者指定的屬性順序。

xml.etree.ElementTree.XML(text, parser=None)

從字串常量解析 XML 部分。此函式可用於在 Python 程式碼中嵌入 “XML 字面量”。text 是包含 XML 資料的字串。parser 是一個可選的解析器例項。如果未給出,則使用標準的 XMLParser 解析器。返回一個 Element 例項。

xml.etree.ElementTree.XMLID(text, parser=None)

從字串常量解析 XML 部分,並返回一個字典,該字典將元素 ID 對映到元素。text 是包含 XML 資料的字串。parser 是一個可選的解析器例項。如果未給出,則使用標準的 XMLParser 解析器。返回一個元組,其中包含一個 Element 例項和一個字典。

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 是根 ElementElementTree 例項,用於查詢此類元素。loader 是一個可選的資源載入器。如果省略,則預設為 default_loader()。如果給定,它應該是一個可呼叫物件,實現與 default_loader() 相同的介面。base_url 是原始檔案的基本 URL,用於解析相對包含的檔案引用。max_depth 是遞迴包含的最大數量。限制用於減少惡意內容爆炸的風險。傳遞 None 來停用此限制。

在 3.9 版本中變更: 添加了 base_urlmax_depth 引數。

Element 物件

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)

Element 類。此類定義了 Element 介面,並提供了此介面的參考實現。

元素名稱、屬性名稱和屬性值可以是位元組串或 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 元素的 texttail 屬性均為 Noneb 元素的 text"1"tail"4"c 元素的 text"2"tailNoned 元素的 textNonetail"3"

要收集元素的內部文字,請參閱 itertext(),例如 "".join(element.itertext())

應用程式可以在這些屬性中儲存任意物件。

attrib

一個包含元素屬性的字典。請注意,雖然 attrib 值始終是一個真正的可變 Python 字典,但 ElementTree 實現可以選擇使用另一種內部表示形式,並且僅在有人請求時才建立字典。為了利用這種實現,請儘可能使用下面的字典方法。

以下類似字典的方法可用於元素屬性。

clear()

重置元素。此函式刪除所有子元素,清除所有屬性,並將 text 和 tail 屬性設定為 None

get(key, default=None)

獲取名為 key 的元素屬性。

返回屬性值,如果未找到該屬性,則返回 default

items()

將元素屬性作為(名稱,值)對的序列返回。屬性以任意順序返回。

keys()

將元素的屬性名稱作為列表返回。名稱以任意順序返回。

set(key, value)

將元素上的屬性 key 設定為 value

以下方法用於元素子元素。

append(subelement)

將元素 subelement 新增到此元素內部子元素列表的末尾。如果 subelement 不是 Element,則引發 TypeError

extend(subelements)

從元素的可迭代物件追加 subelements。如果子元素不是 Element,則引發 TypeError

在 3.2 版本中新增。

find(match, namespaces=None)

查詢與 match 匹配的第一個子元素。match 可以是標記名稱或 路徑。返回一個元素例項或 Nonenamespaces 是一個從名稱空間字首到完整名稱的可選對映。傳遞 '' 作為字首,將表示式中所有未加字首的標記名稱移動到給定的名稱空間中。

findall(match, namespaces=None)

按標記名稱或 路徑查詢所有匹配的子元素。返回一個列表,其中包含文件順序中所有匹配的元素。namespaces 是一個從名稱空間字首到完整名稱的可選對映。傳遞 '' 作為字首,將表示式中所有未加字首的標記名稱移動到給定的名稱空間中。

findtext(match, default=None, namespaces=None)

查詢與 match 匹配的第一個子元素的文字。match 可以是標記名稱或 路徑。返回第一個匹配元素的文字內容,如果未找到任何元素,則返回 default。請注意,如果匹配元素沒有文字內容,則返回一個空字串。namespaces 是一個從名稱空間字首到完整名稱的可選對映。傳遞 '' 作為字首,將表示式中所有未加字首的標記名稱移動到給定的名稱空間中。

insert(index, subelement)

在此元素的給定位置插入subelement。如果subelement不是 Element,則會引發 TypeError

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 物件

class xml.etree.ElementTree.QName(text_or_uri, tag=None)

QName 包裝器。這可以用於包裝 QName 屬性值,以便在輸出時獲得正確的名稱空間處理。text_or_uri 是一個包含 QName 值的字串,格式為 {uri}local,或者,如果給定了 tag 引數,則是 QName 的 URI 部分。如果給定了 tag,則第一個引數被解釋為 URI,此引數被解釋為本地名稱。QName 例項是不透明的。

TreeBuilder 物件

class xml.etree.ElementTree.TreeBuilder(element_factory=None, *, comment_factory=None, pi_factory=None, insert_comments=False, insert_pis=False)

通用元素結構構建器。此構建器將一系列開始、資料、結束、註釋和 pi 方法呼叫轉換為格式良好的元素結構。您可以使用此類使用自定義 XML 解析器或某種其他類似 XML 格式的解析器來構建元素結構。

element_factory(如果給定)必須是可呼叫的,它接受兩個位置引數:一個標籤和一個屬性字典。它應該返回一個新的元素例項。

comment_factorypi_factory 函式(如果給定)的行為應類似於 Comment()ProcessingInstruction() 函式來建立註釋和處理指令。如果未給出,將使用預設工廠。當 insert_comments 和/或 insert_pis 為 true 時,如果註釋/pi 出現在根元素內(但不位於根元素之外),則會將它們插入到樹中。

close()

重新整理構建器緩衝區,並返回頂層文件元素。返回一個 Element 例項。

data(data)

將文字新增到當前元素。data 是一個字串。這應該是一個位元組串或一個 Unicode 字串。

end(tag)

關閉當前元素。tag 是元素名稱。返回已關閉的元素。

start(tag, attrs)

開啟一個新元素。tag 是元素名稱。attrs 是一個包含元素屬性的字典。返回開啟的元素。

comment(text)

使用給定的 text 建立註釋。如果 insert_comments 為 true,則也會將其新增到樹中。

在 3.8 版本中新增。

pi(target, text)

使用給定的 target 名稱和 text 建立處理指令。如果 insert_pis 為 true,則也會將其新增到樹中。

在 3.8 版本中新增。

此外,自定義的 TreeBuilder 物件可以提供以下方法

doctype(name, pubid, system)

處理文件型別宣告。name 是文件型別名稱。pubid 是公共識別符號。system 是系統識別符號。此方法不存在於預設的 TreeBuilder 類中。

在 3.2 版本中新增。

start_ns(prefix, uri)

每當解析器遇到新的名稱空間宣告時,在定義它的開始元素的 start() 回撥之前呼叫。prefix 對於預設名稱空間為 '',否則為宣告的名稱空間字首名稱。uri 是名稱空間 URI。

在 3.8 版本中新增。

end_ns(prefix)

在聲明瞭名稱空間字首對映的元素的 end() 回撥之後呼叫,名稱是超出作用域的字首

在 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()

完成向解析器饋送資料。返回在構造期間傳遞的 targetclose() 方法的呼叫結果;預設情況下,這是頂級文件元素。

feed(data)

向解析器饋送資料。data 是編碼資料。

flush()

觸發對先前饋送的未解析資料進行解析,這可用於確保更即時的反饋,尤其是在 Expat >=2.6.0 的情況下。flush() 的實現暫時停用 Expat 的重新解析延遲(如果當前啟用)並觸發重新解析。停用重新解析延遲具有安全後果;有關詳細資訊,請參閱 xml.parsers.expat.xmlparser.SetReparseDeferralEnabled()

請注意,flush() 已作為安全修復程式向 CPython 的某些早期版本進行了反向移植。如果在各種 Python 版本中執行的程式碼中使用,請使用 hasattr() 檢查 flush() 的可用性。

3.13 版本新增。

XMLParser.feed() 為每個開始標籤呼叫 targetstart(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 版本中執行的程式碼中使用,請使用 hasattr() 檢查 flush() 的可用性。

3.13 版本新增。

close()

向解析器發出資料流已終止的訊號。與 XMLParser.close() 不同,此方法始終返回 None。當解析器關閉時,任何尚未檢索到的事件仍然可以使用 read_events() 讀取。

read_events()

返回一個迭代器,該迭代器遍歷在饋送到解析器的資料中遇到的事件。迭代器生成 (event, elem) 對,其中 event 是表示事件型別的字串(例如 "end"),而 elem 是遇到的 Element 物件或其他上下文值,如下所示。

  • start, end:當前的 Element。

  • comment, pi:當前註釋/處理指令

  • start-ns:一個元組 (prefix, uri),命名宣告的名稱空間對映。

  • end-nsNone(這可能會在未來版本中更改)

先前呼叫 read_events() 中提供的事件將不會再次產生。只有當從迭代器中檢索事件時,才會從內部佇列中消耗事件,因此並行迭代從 read_events() 獲取的迭代器的多個讀取器將產生不可預測的結果。

註解

XMLPullParser 僅保證當它發出“start”事件時,它已經看到了起始標記的“>”字元,因此屬性已定義,但此時文字和 tail 屬性的內容未定義。同樣適用於元素子節點;它們可能存在也可能不存在。

如果您需要完全填充的元素,請查詢 “end” 事件。

3.4版本新增。

在 3.8 版本中更改: 添加了 commentpi 事件。

異常

class xml.etree.ElementTree.ParseError

XML 解析錯誤,當解析失敗時,此模組中的各種解析方法會引發此錯誤。此異常例項的字串表示將包含使用者友好的錯誤訊息。此外,它還將具有以下可用屬性

code

來自 expat 解析器的數字錯誤程式碼。有關錯誤程式碼及其含義的列表,請參見 xml.parsers.expat 的文件。

position

一個 line(行)和 column(列)數字的元組,指定錯誤發生的位置。

腳註