【初心者向け】PythonでXMLを読み込む方法まとめ|ElementTree・lxmlの使い方とサンプル付き

目次

1. PythonでXMLを読み込む前に知っておきたいこと

PythonでXMLを扱う場面とは?

Pythonは多くの用途で使われる汎用的なプログラミング言語ですが、その中でも「XMLファイルの読み込み」はデータ処理の現場でよく使われる技術の一つです。特に以下のようなケースで、PythonによるXMLの読み込みが必要になります。

  • Web APIから取得したXMLデータを解析したい
  • 他システムからエクスポートされたXMLファイルを処理したい
  • コンフィグ(設定)ファイルとして利用されているXMLを読み取りたい

XMLはタグ構造によってデータの階層や意味を明確に表現できるため、さまざまな業界で利用されています。Pythonを使えば、これらのXMLデータを簡単に読み込み、加工、解析することが可能です。

XMLとは?簡単におさらい

XML(Extensible Markup Language)は、データの構造を柔軟に定義できるマークアップ言語です。HTMLと似た構造を持ちますが、用途が異なります。HTMLが「見た目(表示)」に使われるのに対し、XMLは「データの構造や意味」を記述するためのフォーマットです。

例えば以下のような形式が典型的なXMLです:

<book>
  <title>Python入門</title>
  <author>山田 太郎</author>
  <price>2800</price>
</book>

このような形式のデータをPythonで読み込んで利用するためには、専用のライブラリを使う必要があります。

PythonでXMLを読み込むためのライブラリ紹介

Pythonには、標準ライブラリおよび外部ライブラリで、XMLを読み込むための手段がいくつか用意されています。代表的なものは以下の通りです。

  • xml.etree.ElementTree(標準ライブラリ)
  • xml.dom.minidom(標準ライブラリ)
  • lxml(外部ライブラリ、XPathやバリデーション対応)

本記事では、これらのライブラリを使ってPythonでXMLファイルを読み込む方法を、サンプルコード付きでわかりやすく解説していきます。初心者の方でも読み進められるよう、基礎から丁寧に紹介していきますのでご安心ください。

2. PythonでXMLを読み込む基本

ElementTreeを使ったXMLファイルの読み込み

まずは、実際のXMLファイルを用いて、ElementTreeで読み込む方法を見てみましょう。

サンプルXML(sample.xml):

<books>
  <book>
    <title>Python入門</title>
    <author>山田太郎</author>
    <price>2800</price>
  </book>
  <book>
    <title>AIの未来</title>
    <author>鈴木一郎</author>
    <price>3500</price>
  </book>
</books>

Pythonコード:

import xml.etree.ElementTree as ET

# XMLファイルの読み込み
tree = ET.parse('sample.xml')
root = tree.getroot()

# ルート要素のタグを確認
print(f"ルート要素: {root.tag}")

# 各book要素をループ処理
for book in root.findall('book'):
    title = book.find('title').text
    author = book.find('author').text
    price = int(book.find('price').text)

    print(f"タイトル: {title}, 著者: {author}, 価格: {price}円")

実行結果:

ルート要素: books
タイトル: Python入門, 著者: 山田太郎, 価格: 2800円
タイトル: AIの未来, 著者: 鈴木一郎, 価格: 3500円

このように、ElementTree.parse() でXMLファイルを読み込み、getroot() でルート要素を取得し、find()findall() で必要な要素を抽出していくのが基本的な流れです。

文字列からXMLを読み込む方法

XMLがファイルではなく文字列で与えられることもあります。その場合は ET.fromstring() を使って解析します。

例:

xml_data = '''
<user>
  <name>佐川翔太</name>
  <email>sagawa@example.com</email>
</user>
'''

root = ET.fromstring(xml_data)

name = root.find('name').text
email = root.find('email').text

print(f"名前: {name}, メール: {email}")

こちらも同様に、ルート要素から必要な子要素を find() で取得して値を取り出すことができます。

属性の取得とテキストの扱い

XML要素には、タグの中に属性が定義されている場合もあります。Pythonでは .attrib を使ってアクセス可能です。

例(属性付きXML):

<user id="101">
  <name>佐川翔太</name>
</user>

Pythonコード:

root = ET.fromstring('''
<user id="101">
  <name>佐川翔太</name>
</user>
''')

print(f"ユーザーID: {root.attrib['id']}")

3. 他のXML解析ライブラリの紹介

minidom:DOMベースの標準ライブラリ

xml.dom.minidom は、Pythonに標準で含まれているXMLパーサで、W3CのDOM(Document Object Model)仕様に基づいてXMLを扱うことができます。

ElementTree に比べてやや扱いづらい印象を持たれることもありますが、ノードの種類や構造を細かく操作したい場合に便利です。

例:

from xml.dom import minidom

xml_data = '''
<user>
  <name>佐川翔太</name>
  <email>sagawa@example.com</email>
</user>
'''

dom = minidom.parseString(xml_data)
name = dom.getElementsByTagName('name')[0].firstChild.nodeValue
email = dom.getElementsByTagName('email')[0].firstChild.nodeValue

print(f"名前: {name}, メール: {email}")

特徴とメリット:

  • 細かいノード構造にアクセスしやすい
  • 属性や子ノードの型が明確に分類されている
  • XMLを整形して出力(pretty print)しやすい

デメリット:

  • コードが冗長になりがち
  • 大規模なXMLの処理には向かない(メモリ消費が大きい)

lxml:高速かつ強力な外部ライブラリ

lxml はC言語ベースで実装された高速なXMLパーサで、XPathやXSLTなどの高度なXML機能にも対応しています。ElementTree に似たAPIを提供しているため、学習コストも低めです。

インストール方法:

pip install lxml

基本的な使い方:

from lxml import etree

xml_data = '''
<books>
  <book>
    <title>Python実践</title>
    <price>3000</price>
  </book>
</books>
'''

root = etree.fromstring(xml_data)
title = root.xpath('//book/title/text()')[0]
price = root.xpath('//book/price/text()')[0]

print(f"タイトル: {title}, 価格: {price}円")

特徴とメリット:

  • XPathが使えるため柔軟な検索が可能
  • 高速で大量のXML処理に適している
  • HTMLとの互換性もあり、スクレイピングにも応用可能

デメリット:

  • 外部ライブラリのインストールが必要
  • 若干の初期学習が必要(XPathなど)

ライブラリの選び方まとめ

ライブラリ特徴向いているケース
ElementTree標準で使える、基本的な読み書きが可能小規模・中規模XMLの読み込み
minidomDOM操作に強く、整形出力が得意ノード構造を細かく操作したいとき
lxml高速・XPath対応、柔軟性が高い大規模データ、高度な検索が必要なとき

 

4. 実用的なサンプルコード

このセクションでは、PythonでXMLを読み込む処理を、実際の業務やデータ処理に近い形で実践的に紹介します。具体的には「複数ノードの繰り返し処理」「条件によるフィルタリング」「XMLファイルへの書き出し」など、よく使われるパターンに対応したコード例を示します。

複数ノードの繰り返し処理

XML内に同じ構造のデータ(たとえば複数の <book> 要素)が繰り返されている場合、findall() を使ってループ処理を行います。

サンプルXML:

<books>
  <book>
    <title>Python入門</title>
    <author>山田太郎</author>
    <price>2800</price>
  </book>
  <book>
    <title>AIの未来</title>
    <author>鈴木一郎</author>
    <price>3500</price>
  </book>
</books>

Pythonコード(ElementTree使用):

import xml.etree.ElementTree as ET

tree = ET.parse('books.xml')
root = tree.getroot()

for book in root.findall('book'):
    title = book.find('title').text
    author = book.find('author').text
    price = int(book.find('price').text)

    print(f"タイトル: {title}, 著者: {author}, 価格: {price}円")

このようにループ内で個々の要素にアクセスすることで、XMLからデータを抽出して処理できます。

条件によるフィルタリング

次に、価格が3000円以上の書籍だけを抽出したい場合の条件付き処理です。

Pythonコード:

for book in root.findall('book'):
    price = int(book.find('price').text)
    if price >= 3000:
        title = book.find('title').text
        print(f"高額本: {title}({price}円)")

このように、if 文を組み合わせることで、任意の条件にマッチした要素だけを扱うことができます。

XMLファイルへの書き出し(保存)

読み込んだXMLに手を加えて、新たにファイルとして保存するケースもよくあります。

書き出しの例:

# 新しいルート要素を作成
root = ET.Element('users')

# 子要素の追加
user1 = ET.SubElement(root, 'user', attrib={'id': '1'})
ET.SubElement(user1, 'name').text = '佐川翔太'
ET.SubElement(user1, 'email').text = 'sagawa@example.com'

# ツリー構造として保存
tree = ET.ElementTree(root)
tree.write('users.xml', encoding='utf-8', xml_declaration=True)

これにより、以下のようなXMLファイルが生成されます:

<?xml version='1.0' encoding='utf-8'?>
<users>
  <user id="1">
    <name>佐川翔太</name>
    <email>sagawa@example.com</email>
  </user>
</users>

応用:XPathを使った抽出(lxml)

もし lxml を使っている場合は、より柔軟で強力な検索が可能です。

from lxml import etree

tree = etree.parse('books.xml')
titles = tree.xpath('//book[price >= 3000]/title/text()')

for title in titles:
    print(f"高額本タイトル: {title}")

XPathを活用すれば、複雑な条件でも直感的にデータを抽出できます。

年収訴求

5. よくあるエラーと対処法

PythonでXMLを読み込む際には、構文エラーや文字コードの問題など、さまざまなエラーが発生することがあります。このセクションでは、初心者がつまずきやすい代表的なエラーとその対処法を紹介します。

UnicodeDecodeError:文字コードの違いによる読み込み失敗

エラー内容:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 10

原因:
XMLファイルがUTF-8以外(Shift_JISやUTF-16など)の文字コードで保存されている場合、Pythonが正しくデコードできずエラーになります。

対処法:
ファイルを読み込む際に明示的にエンコーディングを指定しましょう。

with open('sample.xml', encoding='shift_jis') as f:
    data = f.read()

import xml.etree.ElementTree as ET
root = ET.fromstring(data)

または、ElementTree.parse() に直接バイナリモードで渡す方法も有効です。

ParseError:XML構文が不正

エラー内容:

xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 3, column 15

原因:
XMLファイル内のタグが閉じられていない、特殊文字(例:&)がエスケープされていない、構文ミスがある等の場合に発生します。

対処法:

  • 該当の行番号と列をエラーメッセージから特定する
  • エディタでXMLの整形表示をして構文ミスを確認
  • 特殊文字(例:&&amp;)の変換を行う

例:誤ったXML

<note>
  <text>5 & 3</text>
</note>

修正後:

<note>
  <text>5 &amp; 3</text>
</note>

NoneType Attribute Error:存在しない要素にアクセス

エラー内容:

AttributeError: 'NoneType' object has no attribute 'text'

原因:
指定したタグがXML内に存在しない場合、find()None を返し、そのまま .text にアクセスするとエラーになります。

対処法:
要素が存在するかをチェックしてから値を取得するようにしましょう。

title_elem = book.find('title')
if title_elem is not None:
    title = title_elem.text
else:
    title = 'タイトル不明'

または、Python 3.8以降であればウォルラス演算子(:=)を使うと簡潔に書けます。

if (title_elem := book.find('title')) is not None:
    print(title_elem.text)

XMLファイルが壊れている or 空の場合

症状:

  • エラーは出ないが、getroot()None が返る
  • findall() で何も取得できない

原因:

  • XMLファイルが空(0バイト)
  • データが途中で切れている(ダウンロード失敗など)

対処法:

  • ファイルサイズや中身を確認する
  • XMLのバリデーションツールで構文チェックを行う
  • ダウンロード元や生成元の処理を見直す

6. よくある質問(FAQ)

このセクションでは、「PythonでXMLを読み込みたい」と考える読者からよく寄せられる疑問や不安を、Q&A形式でわかりやすく解説します。実務や学習の中でつまずきやすいポイントを事前に解消できるよう意識した内容です。

Q1. XMLファイルのエンコーディング(文字コード)はどう扱えばいい?

A.
XMLファイルには通常、最上部に以下のようなエンコーディング指定があります:

<?xml version="1.0" encoding="UTF-8"?>

Pythonの ElementTreelxml はこの宣言を自動的に読み取ってくれますが、ファイルを開く際に文字コードが一致していないとエラーになります。

日本語のXMLファイルでは Shift_JISEUC-JP のこともあるため、以下のように明示的にエンコーディングを指定するのが安全です:

with open('sample.xml', encoding='shift_jis') as f:
    data = f.read()

また、lxml を使うとエンコーディング処理がより柔軟に行えます。

Q2. 巨大なXMLファイルを処理するとメモリ不足になります。どうすればいい?

A.
大規模なXMLを一括で読み込むと、すべてをメモリに展開するため、処理が重くなるかエラーになる可能性があります。

このような場合は、逐次的に読み込める「イテレータ型パーサ」を使用するのが有効です。

import xml.etree.ElementTree as ET

for event, elem in ET.iterparse('large.xml', events=('end',)):
    if elem.tag == 'book':
        print(elem.find('title').text)
        elem.clear()  # メモリ解放

この方法なら、必要な部分だけを順番に処理でき、メモリの節約になります。

Q3. JSONではなく、XMLを使うメリットって何ですか?

A.
現在ではAPIの多くがJSONを採用していますが、XMLにも独自の強みがあります。

  • 階層構造を厳密に定義できる(DTD/XSDなど)
  • 属性と要素の使い分けが可能
  • ドキュメント指向に強く、設定ファイルや構成情報に向いている
  • 企業や自治体のシステムでは、いまだにXMLが主流

つまり、「人が読むというより、構造化された文書を定義する」ことに長けているのがXMLです。用途によっては、今後も十分現役です。

Q4. lxmlElementTree はどちらを使うべきですか?

A.
以下の基準で使い分けるとよいでしょう:

ライブラリ向いているケース
ElementTree小〜中規模のXML、標準ライブラリで十分な場合
lxmlXPathを使いたい、高速に処理したい、大量データを扱う場合

初心者には ElementTree から始めるのがおすすめですが、XPathなどで柔軟な抽出を行いたい場合や、処理速度が求められるケースでは lxml が強力です。

7. まとめ

本記事では、「PythonでXMLを読み込む方法」について、初心者にもわかりやすく、かつ実務に応用しやすい内容で解説してきました。

PythonでのXML読み込みは意外とシンプル

標準ライブラリの xml.etree.ElementTree を使えば、特別な準備なしにすぐXMLを読み込むことができます。基本的な構文やメソッド(parse()find()findall() など)を覚えてしまえば、データの取得や加工が簡単にできるようになります。

用途に応じたライブラリ選びが重要

  • 小規模・シンプルな処理: ElementTree
  • 細かなノード操作や整形出力: minidom
  • 高速処理やXPath検索: lxml

それぞれにメリット・デメリットがありますので、自分が扱うXMLのサイズや目的に応じて使い分けましょう。

よくあるエラーやトラブルにも備えよう

初心者がつまずきやすいエラーも、原因と対処法を理解しておけば慌てることはありません。特に「文字コードの違い」や「構文エラー」「要素の存在チェック」などは頻出です。

XMLは今でも現役の技術

近年はJSONの利用が増えていますが、XMLはまだ多くの業務システムや行政、データ交換の現場で使われています。PythonによるXML処理の技術を身につけておくことは、幅広い分野で役立つスキルとなります。