PythonでXMLと文字列の変換
Pythonで文字列をXMLに変換(パース)したり、XMLを文字列に変換したりしてみます。
目次
defusedxmlモジュール
Pythonの公式ドキュメントのxmlモジュールの節に書かれていますが、XMLにはパーサーを悪用するなどした脆弱性があります。
そこで、安全性の不明なXMLを扱うときは、Pythonの組み込みのxmlモジュールではなくdefusedxmlなどの外部モジュールの使用が推奨されています。(公式のドキュメントに書かれています。)
本投稿では、 defusedxml を使用します。defusedxmlのサイトの説明によると、組み込みのxmlモジュールと使用方法は互換性があるようです。
文字列をXMLに変換する
XMLをElementTreeという木構造のオブジェクトとして扱います。そのために、文字列をElementに変換します。
fromstringというメソッドを使うと、文字列からElementに変換できます。
import defusedxml.ElementTree as ET
# import xml.etree.ElementTree as ET # 組み込みのxmlモジュールを使う場合
root = ET.fromstring(source, [parser])
変数  | 
型  | 
内容  | 
|---|---|---|
source  | 
str  | 
変換元の文字列。  | 
parser  | 
省略可。既定値はNone。XMLパーサーの指定。  | 
|
root  | 
Element  | 
Elementオブジェクト。  | 
パーサーを指定しない場合は、標準のパーサーが使用されます。
得られるオブジェクトがElementTreeではなくElementオブジェクトであることに注意してください。
文字列からXMLへの変換例
試してみましょう。
下記のXMLファイルをreadで文字列として読み込んで、その文字列をElementオブジェクトに変換します。そして、最上位の要素の子の要素のタグ名と属性を表示します。
<?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>
import defusedxml.ElementTree as ET
with open('test.xml', mode='rt', encoding='utf-8') as f:
    xml_string = f.read()
root = ET.fromstring(xml_string)
for i in root:
    print(i.tag, i.attrib)
出力はこうなります。
middle {'id': '1'}
middle {'id': '2'}
middle {'id': '3'}
rootの要素の下の各要素のタグ名と属性が出力されました。
XMLを文字列に変換する
XMLを文字列に変換するには、ElementTreeのtostringメソッドを使用します。
import defusedxml.ElementTree as ET
# import xml.etree.ElementTree as ET # 組み込みのxmlモジュールを使う場合
ret = ET.tostring(element, [encoding], [method], [short_empty_elements])
変数  | 
型  | 
内容  | 
|---|---|---|
element  | 
Element  | 
文字列に変換したいElementオブジェクト。  | 
encoding  | 
str  | 
省略可。既定値はus-ascii。文字エンコード。  | 
method  | 
str  | 
省略可。既定値はxml。出力方法。  | 
short_empty_elements  | 
bool  | 
省略可。既定値はTrue。空の要素の表記方法。  | 
ret  | 
str  | 
変換後の文字列。  | 
ユニコード文字列で出力したい場合は、encodingにunicodeを指定します。utf-8を指定するとバイト列になるようです。
methodはxml、html、textのいずれかです。
short_empty_elementsは、中身が空の要素をどのように記述するかの指定をします。Trueの場合は単独の空要素として記述されます。Falseの場合は、開く要素と閉じる要素のペアで記述されます。
XMLから文字列への変換例
試してみましょう。
上記のXMLファイルを読み込んで文字列に変換したものを、printで出力します。
import defusedxml.ElementTree as ET
with open('test.xml', mode='rt', encoding='utf-8') as f:
    xml_string = f.read()
root = ET.fromstring(xml_string)
ret = ET.tostring(root, encoding='unicode')
print(ret)
<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>
Python 3.7とdefusedxml 0.6の環境でですが、encodingにutf-8を指定すると文字化けして表示されます。
tostringのencoding引数をutf-8にして、変換後のデータをバイナリ-形式でファイルに出力してみます。
import defusedxml.ElementTree as ET
with open('test.xml', mode='rt', encoding='utf-8') as f:
    xml_string = f.read()
root = ET.fromstring(xml_string)
ret = ET.tostring(root, encoding='utf-8')
with open('out.xml', mode='wb') as f:
    f.write(ret)
出力用のファイルを開くときに、バイナリーモードになっていることに注意してください。バイナリーモードでは、エンコードは指定できません。(バイナリーですからね。)
出力されたファイルをエディタで開くとこうなります。
<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と判断してくれました。
公開日
広告
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を作る