Pythonのxml.etree.ElementTree
のテンプレートからの読み込みサンプル
前回のライブドアブログへの投稿(Pythonでライブドアブログに記事を投稿・取得する | ikapblog)についてテンプレートを使って投稿するサンプルをメモしておく。 xmlの操作なので、可読性があまり良くない。
複雑なのを作るなら、テンプレートエンジンを使った方が早いかも。
xmlファイルのテンプレートの中身
まずはテンプレートとなるxmlファイルの中身を紹介する。
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app">
<title>ここにタイトルを埋め込む</title>
<author><name>author_name</name></author>
<content type="text/html">ここにコンテンツの中身</content>
<category term="カテゴリ名" />
<category term="カテゴリ名2" />
<app:control>
<app:draft>no</app:draft>
</app:control>
</entry>
カテゴリ名は複数設定できるようだ。author_name
は前回のブログID相当。
これをファイルとして保存しておく。
テンプレートを読み込む
悪意のあるファイルをうっかり読み込んでしまってもダメージを受けないように、defusedxml · PyPIを利用する。
インストールは、pip install defusedxml
などで。
パース自体はファイルのパスを指定するだけで済むので、関数として使うことにした。
import xml.etree.ElementTree as ET
import defusedxml.ElementTree as DET
def gen_constructed_xml_root(filepath: str) -> ET.Element:
"""指定されたxmlファイルをパースし、ルートノードを返す。"""
tree = DET.parse(filepath)
return tree.getroot()
基本的にはgen_constructed_xml_root()
関数を呼び、ルートノードを保持していればOK。
置き換えたり埋め込んだりする箇所はルートノードからたどることが出来る。
defusedxml
を使ってパースし、xmlのルートノードであるxml.etree.ElementTree.Element
のインスタンスを受け取る。というだけ。パースして返ってくるのはxml.etree.ElementTree
の標準ライブラリのものであることは注意しておいた方がいいだろう。
埋め込む部分を探して埋め込む
xml内の特定要素を探索し、値を埋め込むための関数を定義する。
def set_title_content_in_xml(xml_root: ET.Element, title: str,
content: str) -> str:
"""xmlのtitleとcontentを設定する。"""
title_elm = xml_root.find('{*}title')
content_elm = xml_root.find('{*}content')
title_elm.text = title
content_elm.text = content
return ET.tostring(xml_root, encoding='unicode', xml_declaration=True)
{*}name
は名前空間の有無に関わらずname
を選択するという意味。
発見したら、.text
でコンテンツを埋め込む。埋め込みが終わったらET.tostring()
でunicode
のstr文字列に変換して返す。
文字通りだが、xml_declaration=True
を指定すると<?xml version='1.0' encoding='UTF-8'?>
が先頭に付加される。
str
文字列に変換できればあとは好きに出来る。
まとめ
これまでの関数を使えば以下のようなことが出来る。
# ...これまでの関数は省略
if __name__ == '__main__':
xml_root = gen_constructed_xml_root('somefile.xml')
# どこかでタイトルを生成
title = create_title()
# どこかでコンテンツを生成
content = create_content()
xml = set_title_content_in_xml(xml_root, title, content)
# 保存・送信するなど
send_xml(xml)
簡単便利。
シンプルな投稿くらいならこれでサクッと行うことができる。
便利なライブラリなどがすでにありそうだが、自分でやってみるのも大事だと思って色々試してみた。 しかし試したのが結構前なので抜けている部分もありそうなのが少しもどかしい。 しっかりとメモを残しながら試していくことにしよう。
以上です。
広告