筆記中單純紀錄讀取及 parse 的部份,修改及建立的內容請參閱 Document
儘量使用 xml.etree.cElementTree,因為速度快且消耗的內存小。從 Python3.3 之後,Element 會自動尋找可用的 C 函式庫來加快速度。
範例 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 parse 成 tree root 的 Element;其他 parsing function 則可能會將 XML parse 成一棵樹。
>>> for child in root:
... print child.tag, child.attrib
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}
>>> root[0][1].text
'2008'
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()
>>> for country in root.findall('country'):
... rank = country.find('rank').text
... name = country.get('name')
... print name, rank
...
Liechtenstein 1
Singapore 4
Panama 68
{uri}sometag
的型式XML 範例
<?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>
有兩個方法可以 parse
人工加上 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
當字串過長時,可以使用 string format。
(Better) 使用 xpath
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
關於 xpath 請參閱 XPath expressions
Output
John Cleese
|--> Lancelot
|--> Archie Leach
Eric Idle
|--> Sir Robin
|--> Gunther
|--> Commander Clement
Syntax | Meaning |
---|---|
tag | 選擇所有符合 tag 的 child elements。 Ex. spam 選擇所有 name 為 spam 的 child elements; spam/egg 選擇所有在 name 為 spam 的 child elements 中的 name 為 egg 的 grandchildren elements。 |
* | 選擇所有 child elements。 |
. | 選擇當前節點 |
// | 選擇所有 subelements。 Ex. .//egg 選擇 tree 中所有 name 為 egg 的 elements。 |
.. | 選擇 parent element。 |
[@attrib] | 選擇有 given attribute 的 element。 |
[@attrib='value'] | 選擇所有 given attribute 等於 value 的 elements。(value 不能有引號) |
[tag] | 選擇 child element 有 given tag 的 element。(限第1層的 child element) |
[tag='text'] | 選擇 child element 的 tag 等於 given text 的 element。(所有後代 element) |
[position] | index 的作用,可以使用 last() 。(1 為起始位置) |
所有的 Predicates (使用中括號) 前面必須要有 tag name、* 或 其他Predicates。
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]")
Output
[<Element 'data' at 0x7fd5ace7e818>]
[<Element 'neighbor' at 0x7fd5ab253548>, <Element 'neighbor' at 0x7fd5ab253598>, <Element 'neighbor' at 0x7fd5ab253728>, <Element 'neighbor' at 0x7fd5ab2538b8>, <Element 'neighbor' at 0x7fd5ab253908>]
[<Element 'country' at 0x7fd5ab2535e8>]
[<Element 'year' at 0x7fd5ab253688>]
[<Element 'neighbor' at 0x7fd5ab253598>, <Element 'neighbor' at 0x7fd5ab253908>]