Python 標準ライブラリ xml.etree.ElementTree XMLのパース
Publish date: 2022-02-05
Pythonの標準にあるXMLの解析で使えるライブラリxml.etree.ElementTreeの使い方です。
概要
XML文字列を読み込んで、内容を解析(パース)した結果に以下のようにアクセスできる。
import xml.etree.ElementTree as ET
xml_string = '''\
<?xml version="1.0"?>
<rootTag attribute_sample="123">
<person some_attribute="AAA">
<name>Taro</name>
<birthDate>2000-01-01</birthDate>
</person>
<person some_attribute="BBB">
<name>Jiro</name>
<birthDate>2003-10-12</birthDate>
<items>
<item>
<name>X001</name>
<size>12.3</size>
</item>
<item>
<name>X002</name>
<size>23.4</size>
</item>
</items>
</person>
<person some_attribute="CCC">
<name>Hanako</name>
<birthDate>2001-07-10</birthDate>
</person>
</rootTag>
'''
root = ET.fromstring(xml_string) # Element
root.tag # => 'rootTag'
root.attrib # => {'attribute_sample': '123'}
for child in root:
print(f"{child.tag} {child.attrib}")
# person {'some_attribute': 'AAA'}
# person {'some_attribute': 'BBB'}
# person {'some_attribute': 'CCC'}
ElementTreeはXML要素全体に対応するオブジェクトで、 ElementはXMLの要素1つに対応するオブジェクトとなっている。
上記はXML文字列からXML要素(Element)を取得する例になっている。
XML要素 Elementの読み込み
xml.etree.ElementTree.parse(XMLファイルのパス)を使うとElementTreeのオブジェクトを取得できる。
tree = ET.parse('sample.xml') # xml.etree.ElementTree.ElementTree object
root = tree.getroot() # Element
引数にはファイルオブジェクトも指定可能。
with open('./sample.xml', mode='r', encoding='utf-8') as f:
tree = ET.parse(f) # xml.etree.ElementTree.ElementTree object
root = tree.getroot() # Element
XML要素 Element
子要素のイテレータ
Elementは子要素をイテレートする。
for child in root:
print(f"{child.tag} {child.attrib}")
# person {'some_attribute': 'AAA'}
# person {'some_attribute': 'BBB'}
# person {'some_attribute': 'CCC'}
フィールド
# タグの名称
root.tag # => 'rootTag'
# 属性の辞書
root.attrib # => {'attribute_sample': '123'}
# テキスト要素
root.text # => '\n '
メソッド
タグの名称やxPathでの要素取得は以下のように行う。
# 子要素(複数の場合最初の1つ)
root.find('person') # Element
root.find('person/items') # Element
root.find('person/items/item') # Element
root.find('items') # None
## 子要素の全て
root.findall('person') # Element
root.findall('name') # []
## テキスト
root.findtext('person/name') # 'Taro'
子孫までを繰り返しての取得は次のように行える。
for name_element in root.iter('name'):
print(f"{name_element.text}")
# Taro Jiro X001 X002 Hanako
iterfindはrootに対して条件を指定して要素を取得する。
list(root.iterfind('name')) # => []
for name_element in root.iterfind('person/name'):
print(f"{name_element.text}")
# Taro Jiro Hanako
指定した要素以下のすべてのテキストノードはitertextで取得できる。
list(root.find('person').itertext())
['\n ', 'Taro', '\n ', '2000-01-01', '\n ']
属性の設定と取得は以下の様に行う。
root.get('attribute_sample') # => '123'
root.set('attribute_sample','321')
root.items() # => [('attribute_sample', '321')]
root.keys() # => ['attribute_sample']
要素の変更は次のメソッドを使用する。
element = ET.fromstring('<root><A>aaa</A></root>')
# 新規要素作成
b_item = ET.Element('B')
sub_item = ET.SubElement(b_item,'sub')
sub_item.text = 'SS'
# 要素の追加
element.append(b_item)
ET.tostring(element) # => b'<root><A>aaa</A><B><sub>SS</sub></B></root>'
# 要素の削除
element.remove(b_item)
ET.tostring(element) # => b'<root><A>aaa</A></root>'
# 新規要素作成
new_items = list()
for i in range(3):
sub = ET.Element('item')
sub.text = str(i+1)
new_items.append(sub)
# 要素の複数追加
element.extend(new_items)
ET.tostring(element) # => b'<root><A>aaa</A><item>1</item><item>2</item><item>3</item></root>'
# 2つ目のitem要素
item_second = element.find('item[2]')
# 指定位置に要素を挿入
c_item = ET.Element('C')
element.insert(3, c_item)
ET.tostring(element) # => b'<root><A>aaa</A><item>1</item><item>2</item><C /><item>3</item></root>'
# 要素のクリア
element.clear()
ET.tostring(element) # => b'<root />'
XMLツリー ElementTree
メソッド
# ルート要素の取得
tree.getroot() # => <Element 'rootTag' at 0x000001BD56DB2EA0
# 指定した名称・XPathで取得(最初の1つのみ)
tree.find('person') # => <Element 'person' at …>
# 指定した名称・XPathで取得
tree.findall('person') # => [<Element 'person' at …>, <Element 'person' at …>, <Element 'person' at …>]
# 指定した名称・XPathのテキストノードを取得
tree.findtext('person') # => '\n '
for element in tree.iter():
print(f"{element.tag} {element.text}")
# => 全タグについて出力
for element in tree.iter('name'):
print(f"{element.text}")
# Taro Jiro X001 X002 Hanako
# 指定した全パスについて出力
for element in tree.iterfind'person/name'):
print(f"{element.text}")
# Taro Jiro Hanako
# ルートからみた指定したパスについて出力
list(tree.iterfind('name')) # => []
参考
- cpython/ElementTree.py at 3.10 · python/cpython · GitHub
- xml.etree.ElementTree — ElementTree XML API