PythonでXMLの読み込みと書き出し
PythonでXMLの読み込みと書き出しをしてみます。
目次
defusedxmlモジュール
Pythonの公式ドキュメントのxmlモジュールの節に書かれていますが、XMLにはパーサーを悪用するなどした脆弱性があります。
そこで、安全性の不明なXMLを扱うときは、Pythonの組み込みのxmlモジュールではなくdefusedxmlなどの外部モジュールの使用が推奨されています。(公式のドキュメントに書かれています。)
本投稿では、 defusedxml を使用します。defusedxmlのサイトの説明によると、組み込みのxmlモジュールと使用方法は互換性があるようです。
XMLファイルからダイレクトに読み込み、書き出す
XMLをElementTreeという木構造のオブジェクトとして扱います。
ファイルから直接読み込んでElementTreeにすることができます。
import defusedxml.ElementTree as ET
# import xml.etree.ElementTree as ET # 組み込みのxmlモジュールを使う場合
tree = ET.parse(source, [parser])
変数  | 
型  | 
内容  | 
|---|---|---|
source  | 
str, object  | 
読み込むファイル名、またはファイルオブジェクト。  | 
parser  | 
省略可。既定値はNone。XMLパーサーの指定。  | 
|
tree  | 
ElementTree  | 
ElementTreeオブジェクト。  | 
パーサーを指定しない場合は、標準のパーサーが使用されます。
得られるオブジェクトがElementではなくElementTreeオブジェクトであることに注意してください。
ファイルに書き出すときは、ElementTreeオブジェクトのwriteメソッドを使います。
import defusedxml.ElementTree as ET
# import xml.etree.ElementTree as ET # 組み込みのxmlモジュールを使う場合
tree.write(file, [encoding], [xml_declaration], [default_namespace], [method], [short_empty_elements])
変数  | 
型  | 
内容  | 
|---|---|---|
tree  | 
ElementTree  | 
書き出したいElementTreeオブジェクト。  | 
file  | 
str, object  | 
ファイル名、またはファイルオブジェクト。  | 
encoding  | 
str  | 
省略可。既定値はus-ascii。文字エンコード。  | 
xml_declaration  | 
bool  | 
省略可。既定値はNone。XML宣言を出力するかどうか。  | 
default_namespace  | 
省略可。既定値はNone。XML名前空間の指定。  | 
|
method  | 
str  | 
省略可。既定値はxml。出力方法。  | 
short_empty_elements  | 
bool  | 
省略可。既定値はTrue。空の要素の表記方法。  | 
xml_declarationは出力の最初にXML宣言をするかどうか指定する引数です。Trueの場合は常に出力する、Falseの場合は常に出力しない、Noneの場合はエンコードがus-asciiまたはutf-8およびunicode以外の場合だけ出力するという指定の仕方になっています。
methodはxml、html、textのいずれかです。
short_empty_elementsは、中身が空の要素をどのように記述するかの指定をします。Trueの場合は単独の空要素として記述されます。Falseの場合は、開く要素と閉じる要素のペアで記述されます。
実施例
試してみましょう。
下記のファイルを読み込んで、ファイルに出力します。
<?xml version="1.0" encoding="UTF-8" ?>
<tip>
    <middle id='1'>
        <bottom>content_1</bottom>
    </middle>
    <middle id='2'>
        <!--
        <bottom>content_20</bottom>
        <bottom>content_21</bottom>
        -->
        <bottom>いろは</bottom>
        <bottom>にほへと</bottom>
        <bottom></bottom>
    </middle>
    <middle id='3'>
        content_3
    </middle>
</tip>
XML宣言とコメントと空要素がありますね。
コードはこうしてみます。writeメソッドの引数は、基本的にデフォルト値です。エンコーディングだけはutf-8を指定します。日本語を含んでますからね。
import defusedxml.ElementTree as ET
tree = ET.parse('test.xml')
tree.write('out.xml', encoding='utf-8')
出力はこうなります。
<tip>
    <middle id="1">
        <bottom>content_1</bottom>
    </middle>
    <middle id="2">
        <bottom>いろは</bottom>
        <bottom>にほへと</bottom>
        <bottom />
    </middle>
    <middle id="3">
        content_3
    </middle>
</tip>
エンコーディングがutf-8なので、XML宣言が出力されていません。コメントは消えました。空要素の表記も、単一のタグになりました。
writeメソッドの引数で指定したとおりですね。
では、xml_declarationとshort_empty_elementsの指定を変えてみます。
import defusedxml.ElementTree as ET
tree = ET.parse('test.xml')
tree.write('out.xml', encoding='utf-8', xml_declaration=True, method='xml', short_empty_elements=False)
<?xml version='1.0' encoding='utf-8'?>
<tip>
    <middle id="1">
        <bottom>content_1</bottom>
    </middle>
    <middle id="2">
        <bottom>いろは</bottom>
        <bottom>にほへと</bottom>
        <bottom></bottom>
    </middle>
    <middle id="3">
        content_3
    </middle>
</tip>
XML宣言と空要素の書き方が変わりました。
methodをtextにしたらどうなるでしょうか。
import defusedxml.ElementTree as ET
tree = ET.parse('test.xml')
tree.write('out.xml', encoding='utf-8', method='text')
content_1
いろは
にほへと
content_3
要素の中身だけが出力されました。
公開日
広告
PythonとXMLカテゴリの投稿
- PythonでHTMLから特定のタグを抜き出してCSVにする
 - PythonでHTMLを加工する
 - PythonでXMLと文字列の変換
 - PythonでXMLの構造を表示してみた
 - PythonでXMLの読み込みと書き出し
 - PythonのBeautifulSoup4でHTMLに要素を追加する
 - PythonのBeautifulSoup4でHTMLの要素の内容にアクセスする
 - PythonのBeautifulSoup4でHTMLの要素の内容を削除する
 - PythonのBeautifulSoup4でHTMLの要素の囲いを外す
 - PythonのBeautifulSoup4でHTMLの要素を削除する
 - PythonのBeautifulSoup4でHTMLの要素を抜き出す
 - PythonのBeautifulSoup4でHTMLの要素を新しい要素で囲う
 - PythonのBeautifulSoup4でHTMLの要素を検索する
 - Pythonのxmlで要素を列挙する
 - PythonのxmlモジュールのElementTreeのルート要素を取得する
 - PythonのxmlモジュールのElementからElementTreeを作る