Python で simpleXML ライク。
SimpleXML は、PHP で XML を簡単に扱うためのモジュールで、XML のデータを PHP の連想配列などのデータ型で扱うことができます。
Python でも、XML データを辞書(dict,dictionary)型やリスト(list)型で扱えたら便利です。
次に掲げるページでも、SimpleXML ライクな Python ツールを紹介しています。
PythonでSimpleXML - tomoemonの日記
joestump/python-simplexml - GitHub
ただ、ぼくの環境ではうまく動きませんでした。
Python 初心者なので、コードのどこを修正すればよいかわかりません。
それなら、自分で考えたほうが早いと思って作ったのが、次の timpleXML 関数です。
「timpleXML」は、「陳腐な SimpleXML」という意味です。
例外処理は考えていません。また、タグ名とテキストを取得することだけを前提とし、属性の取得はしません。
検証もほとんどしていないので、おかしなところがあるかもしれませんが、これでも欲しいデータは取れたので、自分用のメモとして公開することにしました。
引数には、xml.etree.ElementTree で取得した エレメントを取ります。
エレメント型が持つ、tag と text プロパティを取得し、getchildren() メソッドで取得した子エレメントを再帰的に処理します。
なお、タグ名の名前空間部分は、削除します。
def timpleXML(elm): import re re_ns = re.compile("\{.*\}") tag = re_ns.sub("",elm.tag) if len(elm.getchildren()): res = {} tags = {} for e in elm.getchildren(): etag = re_ns.sub("",e.tag) if etag in tags : if tags[etag] != 'list' : tags[etag] = 'list' res[etag] = [res[etag]] res[etag] .append(timpleXML(e)) elif not len(e.getchildren()): tags[etag] = 'text' if e.text: res[etag] = e.text else: res[etag] = '' else: tags[etag] = 'dict' res[etag] = timpleXML(e) elif elm.text: res=elm.text; else : res='' return res
辞書型またはリスト型のデータが返ります。
兄弟要素で同じタグ名が使われている場合には、そのタグ名をキーとし、値はリスト型になります。
JSON に変換したい場合は、simplejson(Django) にぶち込むと簡単です。
次に、その処理の一部を示します。
Google App Engine での利用を前提としています。念のため。
from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app import xml.etree.ElementTree as etree from django.utils import simplejson from timpleXML import timpleXML root = etree.fromstring(result_xml) result_obj = timpleXML(root) result_json = simplejson.dumps(result_obj,ensure_ascii=False) callback = self.request.get('_callback') if callback: result_json = callback + "(" + result_json + ")" self.response.headers['Content-Type'] = 'text/javascript' self.response.out.write(result_obj)
result_xml は、XML文字列です。
XMLファイルからエレメントツリーを取得する場合は、次のように記述すればよいでしょう。
xml = urlfetch.fetch(url) root = etree.fromstring(xml.content))
急用があるので、今回はここまで。
説明が不十分ですが、お許し下さい。