xml.etree.ElementTree
--- ElementTree XML API?
源代碼: Lib/xml/etree/ElementTree.py
xml.etree.ElementTree
模塊實現(xiàn)了一個簡單高效的API,用于解析和創(chuàng)建XML數(shù)據(jù)。
在 3.3 版更改: 此模塊將在可能的情況下使用快速實現(xiàn)。
3.3 版后已移除: xml.etree.cElementTree
模塊已被棄用。
警告
xml.etree.ElementTree
模塊對于惡意構(gòu)建的數(shù)據(jù)是不安全的。如果需要解析不可信或未經(jīng)身份驗證的數(shù)據(jù),請參見 XML 漏洞 。
教程?
這是一個使用 xml.etree.ElementTree
(簡稱 ET
)的簡短教程。目標(biāo)是演示模塊的一些構(gòu)建塊和基本概念。
XML 樹和元素?
XML 是一種繼承性的分層數(shù)據(jù)格式,最自然的表示方法是使用樹。 為此, ET
有兩個類 -- ElementTree
將整個XML文檔表示為一個樹, Element
表示該樹中的單個節(jié)點(diǎn)。 與整個文檔的交互(讀寫文件)通常在 ElementTree
級別完成。 與單個 XML 元素及其子元素的交互是在 Element
級別完成的。
解析 XML?
我們將使用以下 XML 文檔作為本節(jié)的示例數(shù)據(jù):
<?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>
可以通過從文件中讀取來導(dǎo)入此數(shù)據(jù):
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
,該元素是已解析樹的根元素。 其他解析函數(shù)可能會創(chuàng)建一個 ElementTree
。 確切信息請查閱文檔。
作為 Element
, root
具有標(biāo)簽和屬性字典:
>>> root.tag
'data'
>>> root.attrib
{}
還有可以迭代的子節(jié)點(diǎn):
>>> for child in root:
... print(child.tag, child.attrib)
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}
子級是可以嵌套的,我們可以通過索引訪問特定的子級節(jié)點(diǎn):
>>> root[0][1].text
'2008'
備注
并非 XML 輸入的所有元素都將作為解析樹的元素結(jié)束。 目前,此模塊跳過輸入中的任何 XML 注釋、處理指令和文檔類型聲明。 然而,使用這個模塊的 API 而不是從 XML 文本解析構(gòu)建的樹可以包含注釋和處理指令,生成 XML 輸出時同樣包含這些注釋和處理指令。 可以通過將自定義 TreeBuilder
實例傳遞給 XMLParser
構(gòu)造器來訪問文檔類型聲明。
用于非阻塞解析的拉取 API?
此模塊所提供了大多數(shù)解析函數(shù)都要求在返回任何結(jié)果之前一次性讀取整個文檔。 可以使用 XMLParser
并以增量方式添加數(shù)據(jù),但這是在回調(diào)目標(biāo)上調(diào)用方法的推送式 API。 有時用戶真正想要的是能夠以增量方式解析 XML 而無需阻塞操作,同時享受完整的已構(gòu)造 Element
對象。
針對此需求的最強(qiáng)大工具是 XMLPullParser
。 它不要求通過阻塞式讀取來獲得 XML 數(shù)據(jù),而是通過執(zhí)行 XMLPullParser.feed()
調(diào)用來增量式地添加數(shù)據(jù)。 要獲得已解析的 XML 元素,應(yīng)調(diào)用 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
常見的用例是針對以非阻塞方式進(jìn)行的應(yīng)用程序,其中 XML 是從套接字接收或從某些存儲設(shè)備增量式讀取的。 在這些用例中,阻塞式讀取是不可接受的。
因為其非常靈活,XMLPullParser
在更簡單的用例中使用起來可能并不方便。 如果你不介意你的應(yīng)用程序在讀取 XML 數(shù)據(jù)時造成阻塞但仍希望具有增量解析能力,可以考慮 iterparse()
。 它在你讀取大型 XML 文檔并且不希望將它完全放去內(nèi)存時會很適用。
查找感興趣的元素?
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()
僅查找當(dāng)前元素的直接子元素中帶有指定標(biāo)簽的元素。 Element.find()
找?guī)в刑囟?biāo)簽的 第一個 子級,然后可以用 Element.text
訪問元素的文本內(nèi)容。 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
提供了一種構(gòu)建XML文檔并將其寫入文件的簡單方法。調(diào)用 ElementTree.write()
方法就可以實現(xiàn)。
創(chuàng)建后可以直接操作 Element
對象。例如:使用 Element.text
修改文本字段,使用 Element.set()
方法添加和修改屬性,以及使用 Element.append()
添加新的子元素。
假設(shè)我們要為每個國家/地區(qū)的中添加一個排名,并在排名元素中添加一個 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現(xiàn)在看起來像這樣:
<?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()
刪除元素。假設(shè)我們要刪除排名高于50的所有國家/地區(qū):
>>> 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')
請注意在迭代時進(jìn)行并發(fā)修改可能會導(dǎo)致問題,就像在迭代并修改 Python 列表或字典時那樣。 因此,這個示例先通過 root.findall()
收集了所有匹配的元素,在此之后再對匹配項列表進(jìn)行迭代。
生成的XML現(xiàn)在看起來像這樣:
<?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>
構(gòu)建 XML 文檔?
SubElement()
函數(shù)還提供了一種便捷方法來為給定元素創(chuàng)建新的子元素:
>>> 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
形式的標(biāo)記和屬性將被擴(kuò)展為 {uri}sometag
,其中 prefix 會被完整 URI 所替換。 并且,如果存在 默認(rèn)命名空間,則完整 URI 會被添加到所有未加前綴的標(biāo)記之前。
下面的 XML 示例包含兩個命名空間,一個具有前綴 "fictional" 而另一個則作為默認(rèn)命名空間:
<?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 中的每個標(biāo)記或?qū)傩蕴砑?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 示例創(chuàng)建一個字典來存放你自己的前綴并在搜索函數(shù)中使用它們:
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 表達(dá)式 的有限支持用于在樹中定位元素。 其目標(biāo)是支持一個簡化語法的較小子集;完整的 XPath 引擎超出了此模塊的適用范圍。
示例?
下面是一個演示此模塊的部分 XPath 功能的例子。 我們將使用來自 解析 XML 小節(jié)的 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,應(yīng)使用通常的限定 {namespace}tag
標(biāo)記法:
# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")
支持的XPath語法?
語法 |
含意 |
---|---|
|
選擇具有給定標(biāo)記的所有子元素。 例如, 在 3.8 版更改: 增加了對星號通配符的支持。 |
|
選擇所有子元素,包括注釋和處理說明。例如 |
|
選擇當(dāng)前節(jié)點(diǎn)。這在路徑的開頭非常有用,用于指示它是相對路徑。 |
|
選擇所有子元素 在當(dāng)前元素的所有下級中選擇所有下級元素。 例如, |
|
選擇父元素。 如果路徑試圖前往起始元素的上級(元素的 |
|
選擇具有給定屬性的所有元素。 |
|
選擇給定屬性具有給定值的所有元素。該值不能包含引號。 |
|
選擇給定屬性不具有給定值的所有元素。 該值不能包含引號。 3.10 新版功能. |
|
選擇所有包含 |
|
選擇完整文本內(nèi)容等于 3.7 新版功能. |
|
選擇完整文本內(nèi)容包括其下級內(nèi)容不等于給定的 3.10 新版功能. |
|
選擇所有包含名為 |
|
選擇具有名為 3.10 新版功能. |
|
選擇位于給定位置的所有元素。 位置可以是一個整數(shù) (1 表示首位),表達(dá)式 |
謂詞(方括號內(nèi)的表達(dá)式)之前必須帶有標(biāo)簽名稱,星號或其他謂詞。position
謂詞前必須有標(biāo)簽名稱。
參考?
函數(shù)?
- xml.etree.ElementTree.canonicalize(xml_data=None, *, out=None, from_file=None, **options)?
C14N 2.0 轉(zhuǎn)換功能。.
規(guī)整化是標(biāo)準(zhǔn)化 XML 輸出的一種方式,該方式允許按字節(jié)比較和數(shù)字簽名。 它降低了 XML 序列化器所具有的自由度并改為生成更受約束的 XML 表示形式。 主要限制涉及命名空間聲明的位置、屬性的順序和可忽略的空白符等。
此函數(shù)接受一個 XML 數(shù)字字符串 (xml_data) 或文件路徑或者文件類對象 (from_file) 作為輸入,將其轉(zhuǎn)換為規(guī)整形式,并在提供了 out 文件(類)對象的情況下將其寫到該對象的話,或者如果未提供則將其作為文本字符串返回。 輸出文件接受文本而非字節(jié)數(shù)據(jù)。 因此它應(yīng)當(dāng)以使用
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: 設(shè)為真值以包括注釋 (默認(rèn)為假值)
- strip_text: 設(shè)為真值以去除文本內(nèi)容前后的空白符
(默認(rèn)值:否)
- rewrite_prefixes: 設(shè)為真值以替換帶有 "n{number}" 前綴的命名空間
(默認(rèn)值:否)
- qname_aware_tags: 一組可感知限定名稱的標(biāo)記名稱,其中的前綴
應(yīng)當(dāng)在文本內(nèi)容中被替換 (默認(rèn)為空值)
- qname_aware_attrs: 一組可感知限定名稱的屬性名稱,其中的前綴
應(yīng)當(dāng)在文本內(nèi)容中被替換 (默認(rèn)為空值)
exclude_attrs: 一組不應(yīng)當(dāng)被序列化的屬性名稱
exclude_tags: 一組不應(yīng)當(dāng)被序列化的標(biāo)記名稱
在上面的選項列表中,"一組" 是指任意多項集或包含字符串的可迭代對象,排序是不必要的。
3.8 新版功能.
- xml.etree.ElementTree.Comment(text=None)?
注釋元素工廠函數(shù)。 這個工廠函數(shù)可創(chuàng)建一個特殊元素,它將被標(biāo)準(zhǔn)序列化器當(dāng)作 XML 注釋來進(jìn)行序列化。 注釋字串可以是字節(jié)串或是 Unicode 字符串。 text 是包含注釋字串的字符串。 返回一個表示注釋的元素實例。
請注意
XMLParser
會跳過輸入中的注釋而不會為其創(chuàng)建注釋對象。ElementTree
將只在當(dāng)使用某個Element
方法向樹插入了注釋節(jié)點(diǎn)時才會包含注釋節(jié)點(diǎn)。
- xml.etree.ElementTree.dump(elem)?
將一個元素樹或元素結(jié)構(gòu)體寫入到 sys.stdout。 此函數(shù)應(yīng)當(dāng)只被用于調(diào)試。
實際輸出格式是依賴于具體實現(xiàn)的。 在這個版本中,它將以普通 XML 文件的格式寫入。
elem 是一個元素樹或單獨(dú)元素。
在 3.8 版更改:
dump()
函數(shù)現(xiàn)在會保留用戶指定的屬性順序。
- xml.etree.ElementTree.fromstring(text, parser=None)?
根據(jù)一個字符串常量解析 XML 的節(jié)。 與
XML()
類似。 text 是包含 XML 數(shù)據(jù)的字符串。 parser 是可選的解析器實例。 如果未給出,則會使用標(biāo)準(zhǔn)XMLParser
解析器。 返回一個Element
實例。
- xml.etree.ElementTree.fromstringlist(sequence, parser=None)?
根據(jù)一個字符串片段序列解析 XML 文檔。 sequence 是包含 XML 數(shù)據(jù)片段的列表或其他序列對象。 parser 是可選的解析器實例。 如果未給出,則會使用標(biāo)準(zhǔn)的
XMLParser
解析器。 返回一個Element
實例。3.2 新版功能.
- xml.etree.ElementTree.indent(tree, space=' ', level=0)?
添加空格到子樹來實現(xiàn)樹的縮進(jìn)效果。 這可以被用來生成美化打印的 XML 輸出。 tree 可以為 Element 或 ElementTree。 space 是對應(yīng)將被插入的每個縮進(jìn)層級的空格字符串,默認(rèn)為兩個空格符。 要對已縮進(jìn)的樹的部分子樹進(jìn)行縮進(jìn),請傳入初始縮進(jìn)層級作為 level。
3.9 新版功能.
- xml.etree.ElementTree.iselement(element)?
檢測一個對象是否為有效的元素對象。 element 是一個元素實例。 如果對象是一個元素對象則返回
True
。
- xml.etree.ElementTree.iterparse(source, events=None, parser=None)?
以增量方式將一個 XML 節(jié)解析為元素樹,并向用戶報告執(zhí)行情況。 source 是包含 XML 數(shù)據(jù)的文件名或 file object。 events 是要報告的事件序列。 所支持的事件字符串有
"start"
,"end"
,"comment"
,"pi"
,"start-ns"
和"end-ns"
("ns" 事件用于獲取詳細(xì)的命名空間信息)。 如果 events 被省略,則只有"end"
事件會被報告。 parser 是可選的解析器實例。 如果未給出,則會使用標(biāo)準(zhǔn)的XMLParser
解析器。 parser 必須為XMLParser
的子類并且只能使用默認(rèn)的TreeBuilder
作為目標(biāo)。 返回一個提供(event, elem)
對的 iterator。請注意雖然
iterparse()
是以增量方式構(gòu)建樹,但它會對 source (或其所指定的文件) 發(fā)出阻塞式讀取。 因此,它不適用于不可執(zhí)行阻塞式讀取的應(yīng)用。 對于完全非阻塞式的解析,請參看XMLPullParser
。備注
iterparse()
只會確保當(dāng)發(fā)出 "start" 事件時看到了開始標(biāo)記的 ">" 字符,因而在這個點(diǎn)上屬性已被定義,但文本容和末尾屬性還未被定義。 這同樣適用于元素的下級;它們可能存在也可能不存在。如果你需要已完全填充的元素,請改為查找 "end" 事件。
3.4 版后已移除: parser 參數(shù)。
在 3.8 版更改: 增加了
comment
和pi
事件。
- xml.etree.ElementTree.parse(source, parser=None)?
將一個 XML 的節(jié)解析為元素樹。 source 是包含 XML 數(shù)據(jù)的文件名或文件對象。 parser 是可選的解析器實例。 如果未給出,則會使用標(biāo)準(zhǔn)的
XMLParser
解析器。 返回一個ElementTree
實例。
- xml.etree.ElementTree.ProcessingInstruction(target, text=None)?
PI 元素工廠函數(shù)。 這個工廠函數(shù)可創(chuàng)建一個特殊元素,它將被當(dāng)作 XML 處理指令來進(jìn)行序列化。 target 是包含 PI 目標(biāo)的字符串。 text 如果給出則是包含 PI 內(nèi)容的字符串。 返回一個表示處理指令的元素實例。
請注意
XMLParser
會跳過輸入中的處理指令而不會為其創(chuàng)建注釋對象。ElementTree
將只在當(dāng)使用某個Element
方法向樹插入了處理指令節(jié)點(diǎn)時才會包含處理指令節(jié)點(diǎn)。
- xml.etree.ElementTree.register_namespace(prefix, uri)?
注冊一個命名空間前綴。 這個注冊表是全局的,并且任何對應(yīng)給定前綴或命名空間 URI 的現(xiàn)有映射都會被移除。 prefix 是命名空間前綴。 uri 是命名空間 URI。 如果可能的話,這個命名空間中的標(biāo)記和屬性將附帶給定的前綴來進(jìn)行序列化。
3.2 新版功能.
- xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)?
子元素工廠函數(shù)。 這個函數(shù)會創(chuàng)建一個元素實例,并將其添加到現(xiàn)有的元素。
元素名、屬性名和屬性值可以是字節(jié)串或 Unicode 字符串。 parent 是父元素。 tag 是子元素名。 attrib 是一個可選的字典,其中包含元素屬性。 extra 包含額外的屬性,以關(guān)鍵字參數(shù)形式給出。 返回一個元素實例。
- 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 是輸出編碼格式(默認(rèn)為 US-ASCII)。 請使用encoding="unicode"
來生成 Unicode 字符串(否則生成字節(jié)串)。 method 是"xml"
,"html"
或"text"
(默認(rèn)為"xml"
)。 xml_declaration, default_namespace 和 short_empty_elements 具有與ElementTree.write()
中一致的含義。 返回一個包含 XML 數(shù)據(jù)(可選)已編碼的字符串。3.4 新版功能: short_empty_elements 形參。
3.8 新版功能: xml_declaration 和 default_namespace 形參。
在 3.8 版更改:
tostring()
函數(shù)現(xiàn)在會保留用戶指定的屬性順序。
- 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 是輸出編碼格式(默認(rèn)為 US-ASCII)。 請使用encoding="unicode"
來生成 Unicode 字符串(否則生成字節(jié)串)。 method 是"xml"
,"html"
或"text"
(默認(rèn)為"xml"
)。 xml_declaration, default_namespace 和 short_empty_elements 具有與ElementTree.write()
中一致的含義。 返回一個包含 XML 數(shù)據(jù)(可選)已編碼字符串的列表。 它并不保證任何特定的序列,除了b"".join(tostringlist(element)) == tostring(element)
。3.2 新版功能.
3.4 新版功能: short_empty_elements 形參。
3.8 新版功能: xml_declaration 和 default_namespace 形參。
在 3.8 版更改:
tostringlist()
函數(shù)現(xiàn)在會保留用戶指定的屬性順序。
XInclude 支持?
此模塊通過 xml.etree.ElementInclude
輔助模塊提供了對 XInclude 指令 的有限支持,這個模塊可被用來根據(jù)元素樹的信息在其中插入子樹和文本字符串。
示例?
以下是一個演示 XInclude 模塊用法的例子。 要在當(dāng)前文本中包括一個 XML 文檔,請使用 {http://www.w3.org/2001/XInclude}include
元素并將 parse 屬性設(shè)為 "xml"
,并使用 href 屬性來指定要包括的文檔。
<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="source.xml" parse="xml" />
</document>
默認(rèn)情況下,href 屬性會被當(dāng)作文件名來處理。 你可以使用自定義加載器來重載此行為。 還要注意標(biāo)準(zhǔn)輔助器不支持 XPointer 語法。
要處理這個文件,請正常加載它,并將根元素傳給 xml.etree.ElementTree
模塊:
from xml.etree import ElementTree, ElementInclude
tree = ElementTree.parse("document.xml")
root = tree.getroot()
ElementInclude.include(root)
ElementInclude 模塊使用來自 source.xml 文檔的根元素替代 {http://www.w3.org/2001/XInclude}include
元素。 結(jié)果看起來大概是這樣:
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<para>This is a paragraph.</para>
</document>
如果省略了 parse 屬性,它會取默認(rèn)的 "xml"。 要求有 href 屬性。
要包括文本文檔,請使用 {http://www.w3.org/2001/XInclude}include
元素,并將 parse 屬性設(shè)為 "text":
<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
Copyright (c) <xi:include href="year.txt" parse="text" />.
</document>
結(jié)果可能如下所示:
<document xmlns:xi="http://www.w3.org/2001/XInclude">
Copyright (c) 2003.
</document>
參考?
函數(shù)?
- xml.etree.ElementInclude.default_loader(href, parse, encoding=None)?
默認(rèn)的加載器。 這個默認(rèn)的加載器會從磁盤讀取所包括的資源。 href 是一個 URL。 parse 是 "xml" 或 "text" 表示解析模式。 encoding 是可選的文本編碼格式。 如果未給出,則編碼格式為
utf-8
。 返回已擴(kuò)展的資源。 如果解析模式為"xml"
,則它是一個 ElementTree 實例。 如果解析模式為 "text",則它是一個 Unicode 字符串。 如果加載器失敗,它可以返回 None 或者引發(fā)異常。
- xml.etree.ElementInclude.include(elem, loader=None, base_url=None, max_depth=6)?
這個函數(shù)會擴(kuò)展 XInclude 指令。 elem 是根元素。 loader 是可選的資源加載器。 如果省略,則它默認(rèn)為
default_loader()
。 如果給出,則它應(yīng)當(dāng)是一個實現(xiàn)了與default_loader()
相同的接口的可調(diào)用對象。 base_url 是原文件的基準(zhǔn) URL,用于求解相對的包括文件引用。 max_depth 是遞歸包括的最大數(shù)量。 此限制是為了降低惡意內(nèi)容爆破的風(fēng)險。 傳入一個負(fù)值可禁用此限制。返回已擴(kuò)展的資源。 如果解析模式為
"xml"
,則它是一個 ElementTree 實例。 如果解析模式為 "text",則它是一個 Unicode 字符串。 如果加載器失敗,它可以返回 None 或者引發(fā)異常。3.9 新版功能: base_url 和 max_depth 形參。
元素對象?
- class xml.etree.ElementTree.Element(tag, attrib={}, **extra)?
元素類。 這個類定義了 Element 接口,并提供了這個接口的引用實現(xiàn)。
元素名、屬性名和屬性值可以是字節(jié)串或 Unicode 字符串。 tag 是元素名。 attrib 是一個可選的字典,其中包含元素屬性。 extra 包含額外的屬性,以關(guān)鍵字參數(shù)形式給出。
- tag?
一個標(biāo)識此元素意味著何種數(shù)據(jù)的字符串(換句話說,元素類型)。
- text?
- tail?
這些屬性可被用于存放與元素相關(guān)聯(lián)的額外數(shù)據(jù)。 它們的值通常為字符串但也可以是任何應(yīng)用專屬的對象。 如果元素是基于 XML 文件創(chuàng)建的,text 屬性會存放元素的開始標(biāo)記及其第一個子元素或結(jié)束標(biāo)記之間的文本,或者為
None
,而 tail 屬性會存放元素的結(jié)束標(biāo)記及下一個標(biāo)記之間的文本,或者為None
。 對于 XML 數(shù)據(jù)<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"
。要獲取一個元素的內(nèi)部文本,請參閱
itertext()
,例如"".join(element.itertext())
。應(yīng)用程序可以將任意對象存入這些屬性。
- attrib?
一個包含元素屬性的字典。 請注意雖然 attrib 值總是一個真正可變的 Python 字典,但 ElementTree 實現(xiàn)可以選擇其他內(nèi)部表示形式,并只在有需要時才創(chuàng)建字典。 為了發(fā)揮這種實現(xiàn)的優(yōu)勢,請在任何可能情況下使用下列字典方法。
以下字典類方法作用于元素屬性。
- clear()?
重設(shè)一個元素。 此方法會移除所有子元素,清空所有屬性,并將 text 和 tail 屬性設(shè)為
None
。
- get(key, default=None)?
獲取名為 key 的元素屬性。
返回屬性的值,或者如果屬性未找到則返回 default。
- items()?
將元素屬性以 (name, value) 對序列的形式返回。 所返回屬性的順序任意。
- keys()?
將元素屬性名稱以列表的形式返回。 所返回名稱的順序任意。
- set(key, value)?
將元素的 key 屬性設(shè)為 value。
以下方法作用于元素的下級(子元素)。
- append(subelement)?
將元素 subelement 添加到此元素的子元素內(nèi)部列表。 如果 subelement 不是一個
Element
則會引發(fā)TypeError
。
- extend(subelements)?
使用具有零個或多個元素的序列對象添加 subelements。 如果某個子元素不是
Element
則會引發(fā)TypeError
。3.2 新版功能.
- find(match, namespaces=None)?
查找第一個匹配 match 的子元素。 match 可以是一個標(biāo)記名稱或者 路徑。 返回一個元素實例或
None
。 namespaces 是可選的從命名空間前綴到完整名稱的映射。 傳入''
作為前綴可將表達(dá)式中所有無前綴的標(biāo)記名稱移動到給定的命名空間。
- findall(match, namespaces=None)?
根據(jù)標(biāo)記名稱或者 路徑 查找所有匹配的子元素。 返回一個包含所有匹配元素按文檔順序排序的列表。 namespaces 是可選的從命名空間前綴到完整名稱的映射。 傳入
''
作為前綴可將表達(dá)式中所有無前綴的標(biāo)記名稱移動到給定的命名空間。
- findtext(match, default=None, namespaces=None)?
查找第一個匹配 match 的子元素的文本。 match 可以是一個標(biāo)記名稱或者 路徑。 反回第一個匹配的元素的文本內(nèi)容,或者如果元素未找到則返回 default。 請注意如果匹配的元素沒有文本內(nèi)容則會返回一個空字符串。 namespaces 是可選的從命名空間前綴到完整名稱的映射。 傳入
''
作為前綴可將表達(dá)式中所有無前綴的標(biāo)記名稱移動到給定的命名空間。
- insert(index, subelement)?
將 subelement 插入到此元素的給定位置中。 如果 subelement 不是一個
Element
則會引發(fā)TypeError
。
- iter(tag=None)?
創(chuàng)建一個以當(dāng)前元素為根元素的樹的 iterator。 該迭代器將以文檔(深度優(yōu)先)順序迭代此元素及其所有下級元素。 如果 tag 不為
None
或'*'
,則迭代器只返回標(biāo)記為 tag 的元素。 如果樹結(jié)構(gòu)在迭代期間被修改,則結(jié)果是未定義的。3.2 新版功能.
- iterfind(match, namespaces=None)?
根據(jù)標(biāo)記名稱或者 路徑 查找所有匹配的子元素。 返回一個按文檔順序產(chǎn)生所有匹配元素的可迭代對象。 namespaces 是可選的從命名空間前綴到完整名稱的映射。
3.2 新版功能.
- itertext()?
創(chuàng)建一個文本迭代器。 該迭代器將按文檔順序遍歷此元素及其所有子元素,并返回所有內(nèi)部文本。
3.2 新版功能.
- makeelement(tag, attrib)?
創(chuàng)建一個與此元素類型相同的新元素對象。 請不要調(diào)用此方法,而應(yīng)改用
SubElement()
工廠函數(shù)。
- remove(subelement)?
從元素中移除 subelement。 與 find* 方法不同的是此方法會基于實例的標(biāo)識來比較元素,而不是基于標(biāo)記的值或內(nèi)容。
Element
對象還支持下列序列類型方法以配合子元素使用:__delitem__()
,__getitem__()
,__setitem__()
,__len__()
。注意:不帶子元素的元素將被檢測為
False
。 此行為將在未來的版本中發(fā)生變化。 請改用len(elem)
或elem is None
進(jìn)行檢測。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")
在 Python 3.8 之前,元素的 XML 屬性的序列化順序會通過按其名稱排序來強(qiáng)制使其可被預(yù)期。 由于現(xiàn)在字典已保證是有序的,這個強(qiáng)制重排序在 Python 3.8 中已被移除以保留原本由用戶代碼解析或創(chuàng)建的屬性順序。
通常,用戶代碼應(yīng)當(dāng)盡量不依賴于特定的屬性順序,因為 XML 信息設(shè)定 明確地排除了用屬性順序轉(zhuǎn)遞信息的做法。 代碼應(yīng)當(dāng)準(zhǔn)備好處理任何輸入順序。 對于要求確定性的 XML 輸出的情況,例如加密簽名或檢測數(shù)據(jù)集等,可以通過規(guī)范化
canonicalize()
函數(shù)來進(jìn)行傳統(tǒng)的序列化。對于規(guī)范化輸出不可用但仍然要求輸出特定屬性順序的情況,代碼應(yīng)當(dāng)設(shè)法直接按要求的順序來創(chuàng)建屬性,以避免代碼閱讀者產(chǎn)生不匹配的感覺。 如果這一點(diǎn)是難以做到的,可以在序列化之前應(yīng)用以下寫法來強(qiáng)制實現(xiàn)順序不依賴于元素的創(chuàng)建:
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 包裝器類。 這個類表示一個完整的元素層級結(jié)構(gòu),并添加了一些對于標(biāo)準(zhǔn) XML 序列化的額外支持。
element 是根元素。 如果給出 XML file 則將使用其內(nèi)容來初始化樹結(jié)構(gòu)。
- _setroot(element)?
替換該樹結(jié)構(gòu)的根元素。 這將丟棄該樹結(jié)構(gòu)的當(dāng)前內(nèi)容,并將其替換為給定的元素。 請小心使用。 element 是一個元素實例。
- find(match, namespaces=None)?
與
Element.find()
類似,從樹的根節(jié)點(diǎn)開始。
- findall(match, namespaces=None)?
與
Element.findall()
類似,從樹的根節(jié)點(diǎn)開始。
- findtext(match, default=None, namespaces=None)?
與
Element.findtext()
類似,從樹的根節(jié)點(diǎn)開始。
- getroot()?
返回這個樹的根元素。
- iter(tag=None)?
創(chuàng)建并返回根元素的樹結(jié)構(gòu)迭代器。 該迭代器會以節(jié)順序遍歷這個樹的所有元素。 tag 是要查找的標(biāo)記(默認(rèn)返回所有元素)。
- iterfind(match, namespaces=None)?
與
Element.iterfind()
類似,從樹的根節(jié)點(diǎn)開始。3.2 新版功能.
- parse(source, parser=None)?
將一個外部 XML 節(jié)載入到此元素樹。 source 是一個文件名或 file object。 parser 是可選的解析器實例。 如果未給出,則會使用標(biāo)準(zhǔn)的
XMLParser
解析器。 返回該節(jié)的根元素。
- write(file, encoding='us-ascii', xml_declaration=None, default_namespace=None, method='xml', *, short_empty_elements=True)?
將元素樹以 XML 格式寫入到文件。 file 為文件名,或是以寫入模式打開的 file object。 encoding 1 為輸出編碼格式 (默認(rèn)為 US-ASCII)。 xml_declaration 控制是否要將 XML 聲明添加到文件中。 使用
False
表示從不添加,True
表示總是添加,None
表示僅在非 US-ASCII 或 UTF-8 或 Unicode 時添加 (默認(rèn)為None
)。 default_namespace 設(shè)置默認(rèn) XML 命名空間 (用于 "xmlns")。 method 為"xml"
,"html"
或"text"
(默認(rèn)為"xml"
)。 僅限關(guān)鍵字形參 short_empty_elements 控制不包含內(nèi)容的元素的格式。 如為True
(默認(rèn)值),它們會被輸出為單個自結(jié)束標(biāo)記,否則它們會被輸出為一對開始/結(jié)束標(biāo)記。輸出是一個字符串 (
str
) 或字節(jié)串 (bytes
)。 由*encoding* 參數(shù)來控制。 如果 encoding 為"unicode"
,則輸出是一個字符串;否則為字節(jié)串;請注意這可能與 file 的類型相沖突,如果它是一個打開的 file object 的話;請確保你不會試圖寫入字符串到二進(jìn)制流或者反向操作。3.4 新版功能: short_empty_elements 形參。
在 3.8 版更改:
write()
方法現(xiàn)在會保留用戶指定的屬性順序。
這是將要被操作的 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)?
通用元素結(jié)構(gòu)構(gòu)建器。 此構(gòu)建器會將包含 start, data, end, comment 和 pi 方法調(diào)用的序列轉(zhuǎn)換為格式良好的元素結(jié)構(gòu)。 你可以通過這個類使用一個自定義 XML 解析器或其他 XML 類格式的解析器來構(gòu)建元素結(jié)構(gòu)。
如果給出 element_factory,它必須為接受兩個位置參數(shù)的可調(diào)用對象:一個標(biāo)記和一個屬性字典。 它預(yù)期會返回一個新的元素實例。
如果給出 comment_factory 和 pi_factory 函數(shù),它們的行為應(yīng)當(dāng)像
Comment()
和ProcessingInstruction()
函數(shù)一樣創(chuàng)建注釋和處理指令。 如果未給出,則將使用默認(rèn)工廠函數(shù)。 當(dāng) insert_comments 和/或 insert_pis 為真值時,如果 comments/pis 在根元素之中(但不在其之外)出現(xiàn)則它們將被插入到樹中。- data(data)?
將文本添加到當(dāng)前元素。 data 為要添加的文本。 這應(yīng)當(dāng)是一個字節(jié)串或 Unicode 字符串。
- end(tag)?
關(guān)閉當(dāng)前元素。 tag 是元素名稱。 返回已關(guān)閉的元素。
- start(tag, attrs)?
打開一個新元素。 tag 是元素名稱。 attrs 是包含元素屬性的字典。 返回打開的元素。
- comment(text)?
使用給定的 text 創(chuàng)建一條注釋。 如果
insert_comments
為真值,這還會將其添加到樹結(jié)構(gòu)中。3.8 新版功能.
- pi(target, text)?
使用給定的 target 名稱和 text 創(chuàng)建一條注釋。 如果
insert_pis
為真值,這還會將其添加到樹結(jié)構(gòu)中。3.8 新版功能.
此外,自定義的
TreeBuilder
對象還提供了以下方法:- doctype(name, pubid, system)?
處理一條 doctype 聲明。 name 為 doctype 名稱。 pubid 為公有標(biāo)識。 system 為系統(tǒng)標(biāo)識。 此方法不存在于默認(rèn)的
TreeBuilder
類中。3.2 新版功能.
- start_ns(prefix, uri)?
在定義了
start()
回調(diào)的打開元素的該回調(diào)被調(diào)用之前,當(dāng)解析器遇到新的命名空間聲明時都會被調(diào)用。 prefix 對于默認(rèn)命名空間為''
或者在其他情況下為被聲明的命名空間前綴名稱。 uri 是命名空間 URI。3.8 新版功能.
- end_ns(prefix)?
在聲明了命名空間前綴映射的元素的
end()
回調(diào)之后被調(diào)用,附帶超出作用域的 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 寫入器。 其參數(shù)與
canonicalize()
函數(shù)的相同。 這個類并不會構(gòu)建樹結(jié)構(gòu)而是使用 write 函數(shù)將回調(diào)事件直接轉(zhuǎn)換為序列化形式。3.8 新版功能.
XMLParser對象?
- class xml.etree.ElementTree.XMLParser(*, target=None, encoding=None)?
這個類是此模塊的低層級構(gòu)建單元。 它使用
xml.parsers.expat
來實現(xiàn)高效、基于事件的 XML 解析。 它可以通過feed()
方法增量式地收受 XML 數(shù)據(jù),并且解析事件會被轉(zhuǎn)換為推送式 API —— 通過在 target 對象上發(fā)起對回調(diào)的調(diào)用。 如果省略 target,則會使用標(biāo)準(zhǔn)的TreeBuilder
。 如果給出了 encoding 1 ,該值將覆蓋在 XML 文件中指定的編碼格式。在 3.8 版更改: 所有形參現(xiàn)在都是 僅限關(guān)鍵字形參。 html 參數(shù)不再受支持。
- close()?
結(jié)束向解析器提供數(shù)據(jù)。 返回調(diào)用在構(gòu)造期間傳入的 target 的
close()
方法的結(jié)果;在默認(rèn)情況下,這是最高層級的文檔元素。
- feed(data)?
將數(shù)據(jù)送入解析器。 data 是編碼后的數(shù)據(jù)。
XMLParser.feed()
會為每個打開的標(biāo)記調(diào)用 target 的start(tag, attrs_dict)
方法,為每個關(guān)閉的標(biāo)記調(diào)用它的end(tag)
方法,并通過data(data)
方法來處理數(shù)據(jù)。 有關(guān)更多受支持的回調(diào)方法,請參閱TreeBuilder
類。XMLParser.close()
會調(diào)用 target 的close()
方法。XMLParser
不僅僅可被用來構(gòu)建樹結(jié)構(gòu)。 下面是一個統(tǒng)計 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)?
適用于非阻塞應(yīng)用程序的拉取式解析器。 它的輸入側(cè) API 與
XMLParser
的類似,但不是向回調(diào)目標(biāo)推送調(diào)用,XMLPullParser
會收集一個解析事件的內(nèi)部列表并讓用戶來讀取它。 events 是要報告的事件序列。 受支持的事件字符串有"start"
,"end"
,"comment"
,"pi"
,"start-ns"
和"end-ns"
("ns" 事件被用于獲取詳細(xì)的命名空間信息)。 如果 events 被省略,則只報告"end"
事件。- feed(data)?
將給定的字節(jié)數(shù)據(jù)送入解析器。
- close()?
通知解析器數(shù)據(jù)流已終結(jié)。 不同于
XMLParser.close()
,此方法總是返回None
。 當(dāng)解析器被關(guān)閉時任何還未被獲取的事件仍可通過read_events()
被讀取。
- read_events()?
返回包含在送入解析器的數(shù)據(jù)中遇到的事件的迭代器。 此迭代器會產(chǎn)生
(event, elem)
對,其中 event 是代表事件類型的字符串 (例如"end"
) 而 elem 是遇到的Element
對象,或者以下的其他上下文值。start
,end
: 當(dāng)前元素。comment
,pi
: 當(dāng)前注釋 / 處理指令start-ns
: 一個指定所聲明命名空間映射的元組(prefix, uri)
。end-ns
:None
(這可能在未來版本中改變)
在之前對
read_events()
的調(diào)用中提供的事件將不會被再次產(chǎn)生。 事件僅當(dāng)它們從迭代器中被取出時才會在內(nèi)部隊列中被消費(fèi),因此多個讀取方對獲取自read_events()
的迭代器進(jìn)行平行迭代將產(chǎn)生無法預(yù)料的結(jié)果。
備注
XMLPullParser
只會確保當(dāng)發(fā)出 "start" 事件時看到了開始標(biāo)記的 ">" 字符,因而在這個點(diǎn)上屬性已被定義,但文本內(nèi)容和末尾屬性還未被定義。 這同樣適用于元素的下級;它們可能存在也可能不存在。如果你需要已完全填充的元素,請改為查找 "end" 事件。
3.4 新版功能.
在 3.8 版更改: 增加了
comment
和pi
事件。
異常?
- class xml.etree.ElementTree.ParseError?
XML 解析器錯誤,由此模塊中的多個解析方法在解析失敗時引發(fā)。 此異常的實例的字符串表示將包含用戶友好的錯誤消息。 此外,它將具有下列可用屬性:
- code?
來自外部解析器的數(shù)字錯誤代碼。 請參閱
xml.parsers.expat
的文檔查看錯誤代碼列表及它們的含義。
- position?
一個包含 line, column 數(shù)值的元組,指明錯誤發(fā)生的位置。
備注
- 1(1,2,3,4)
包括在 XML 輸出中的編碼格式字符串應(yīng)當(dāng)符合適當(dāng)?shù)臉?biāo)準(zhǔn)。 例如 "UTF-8" 是有效的,但 "UTF8" 是無效的。 請參閱 https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl 和 https://www.iana.org/assignments/character-sets/character-sets.xhtml。