Python で simpleXML ライク。

SimpleXML は、PHPXML を簡単に扱うためのモジュールで、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))


急用があるので、今回はここまで。
説明が不十分ですが、お許し下さい。