【Python】XMLファイルをPandasのDataFrameに変換する

2020年5月26日


APIを叩けばJSONでデータが返ってくる
最近は、そんなAPIが主流であると思いますが
まだまだ現役の古いAPIであるとXMLでデータが返ってくると思います。

今回はPythonでXMLデータを扱って
Pandasのデータフレーム形式に変換する方法について紹介します。


XMLデータをPandasのデータフレーム形式に変換する

入力するXMLデータ

今回扱うXMLのデータは以下のようなものです。

sample.xml

<?xml version="1.0" encoding="UTF-8" ?>
<books>
    <library>ンゴ図書館</library>
    <book>
        <title>金正日入門</title>
        <authors>
            <author>
                <name>金正恩</name>
                <age>38</age>
            </author>
            <author>
                <name>ドナルド・トランプ</name>
                <age>74</age>
            </author>
        </authors>
    </book>
    <book>
        <title>人工無能入門</title>
        <authors>
            <author>
                <name>あくのんご</name>
                <age>16</age>
            </author>
            <author>
                <name>山田太郎</name>
                <age>46</age>
            </author>
        </authors>
    </book>
</books>

ライブラリのインストール

今回はXMLデータの読み込みと変換にlxmlとxmljsonを用います。

pip install xmljson
pip install lxml

インストールするには上記のコマンドを実行してください。

pip install pandas

Pandasがインストールされていない場合は、上記のコマンドを実行してPandasをインストールしてください。

ライブラリの読み込み

始めにpandas、xmljson、lxmlをインポートします。

import pandas as pd
import xmljson
from lxml import etree

上記のコードでライブラリをインポートします。

XMLファイルの読み込みとdict型(辞書型)への変換

# xmlの読み込み
xml_tree = etree.parse('sample.xml')
# すべてのタグの取得
xml_root = xml_tree.getroot()
# xmlデータをdict型に変換
xml_dict = xmljson.yahoo.data(xml_root)

上記のようなコードでXMLファイルを読み込んでdict型へ変換します。

OrderedDict([('books', OrderedDict([('library', 'ンゴ図書館'), ('book', [OrderedDict([('title', '金正日入門'), ('authors', OrderedDict([('author', [OrderedDict([('name', '金正恩'), ('age', '38')]), OrderedDict([('name', 'ドナルド・トランプ'), ('age', '74')])])]))]), OrderedDict([('title', '人工無能入門'), ('authors', OrderedDict([('author', [OrderedDict([('name', 'あくのんご'), ('age', '16')]), OrderedDict([('name', '山田太郎'), ('age', '46')])])]))])])]))])

xml_dictの中身は上記のようになります。
これをループなどを使って必要なデータを取り出します。

データを取り出してリストへ格納

xmlデータを取り出してリストへ格納します。

# xmlデータから本の情報リストを抜き出す
xml_books = xml_dict['books']['book']
# 本の情報を入れるリスト
book_data = []
 
for xml_book in xml_books:
   # 本の情報を格納する辞書
   book = {'book_title': xml_book['title']}
 
   # xmlから著者の情報リストを抜き出す
   xml_authors = xml_book['authors']['author']
   for i, xml_author in enumerate(xml_authors):
       book['author_name_' + str(i+1)] = xml_author['name']
       book['author_age_' + str(i+1)] = xml_author['age']
   book_data.append(book)

上記のようなコードでループを回してゴニョゴニョしてデータを取り出します。
どのようなデータが格納してあるかによって書くコードは変わってきますが
今回のサンプルXMLであればこのようなコードでデータが取り出せます。

リストからデータフレームへ変換

先ほど作成したリストからPandasのデータフレームへ変換します。

# リストをデータフレームへ変換
df = pd.DataFrame(book_data)

上記のようなコードで変換します。

book_title author_name_1 author_age_1author_name_2 author_age_2
金正日入門 金正恩 38 ドナルド・トランプ 74
人工無能入門 あくのんご 16 山田太郎 46

データフレームに変換すると上記のようなデータとして取り出せます。

コード全体

コードをまとめると下記のようなコードになります。

import pandas as pd
import xmljson
from lxml import etree
 
# xmlの読み込み
xml_tree = etree.parse('sample.xml')
# すべてのタグの取得
xml_root = xml_tree.getroot()
# xmlデータをdict型に変換
xml_dict = xmljson.yahoo.data(xml_root)
print(xml_dict)
 
# xmlデータから本の情報リストを抜き出す
xml_books = xml_dict['books']['book']
# 本の情報を入れるリスト
book_data = []
 
for xml_book in xml_books:
   # 本の情報を格納する辞書
   book = {'book_title': xml_book['title']}
 
   # xmlから著者の情報リストを抜き出す
   xml_authors = xml_book['authors']['author']
   for i, xml_author in enumerate(xml_authors):
       book['author_name_' + str(i+1)] = xml_author['name']
       book['author_age_' + str(i+1)] = xml_author['age']
   book_data.append(book)
 
# リストをデータフレームへ変換
df = pd.DataFrame(book_data)

これでXMLをデータフレームへ変換できます。