pythonの、辞書型->XML変換器
いわゆる、「シリアライズ」ってことで。辞書型をXMLに書き換えることをしたかったんですが、調べてもいいのが出てこない。XMLから辞書型に変換するプログラムは見つけたんですけどね。
Google Code Archive - Long-term storage for Google Code Project Hosting.
探したんですがよくわからなかったので、自分で作りました。
#! usr/local/bin/python # encoding=EUC-JP # Dictionary->XML変換 # Dict->XML変換器 class Converter: def __init__(self, dictionary): self.dict = dictionary; self.root = self.make_tree(self.dict, self.dict.keys()[0]); # ツリー構造にする関数 def make_tree(self,data,me): n = Node(me); # Nodeオブジェクト生成 childs = []; # 子ノードリスト value = None; # このノードの値 # data[me]がリストなら、別処理 if type(data[me]) == type(list()): for i in xrange(len(data[me])): if type(data[me][i]) != type(dict()): break; # 本当はいらないはずだが。 for c in data[me][i].keys(): childs.append(self.make_tree(data[me][i], c)); n.child = childs[:]; return n; # このノードの値が辞書でないなら、値を挿入 elif type(data[me]) != type(dict()): if data[me] == None: n.value = ""; else: n.value = data[me]; return n; # 子ノードを作る for c in data[me].keys(): childs.append(self.make_tree(data[me], c)); # 再帰的に n.child = childs[:]; return n; # ファイルをXML形式で出力 def write_xml(self, file="sample.xml"): X = XML(self.root); f = open(file, "w"); f.write(X.doc); f.close(); # 文字としてXMLを出力 def tostring(self): X = XML(self.root); return X.doc.encode("euc-jp", "ignore"); # XML形式に変換するクラス class XML: def __init__(self, root): self.root = root; self.doc =""; self.make(root); def make(self, current, width=0): self.doc += "\t"*width + "<%s>"%current.tag; if current.value != None: self.doc += "%s</%s>"%(current.value,current.tag); elif current.child != None: for c in current.child: self.doc += "\n"; self.make(c, width+1); self.doc += "\n" + "\t"*width + "</%s>"%current.tag; return; # 1つのノードを表すクラス class Node: def __init__(self,tag,value=None,child=None,parent=None): self.tag = tag; self.value = value; self.child = child; self.parent = parent; if __name__ == '__main__': sample = {'html': {'head': {'title':'タイトルでーす'}, 'body':'本文でーす' } } C = Converter(sample); print C.tostring();
twitterの取得データをXML形式で保存するときなどに使用済みなので、おそらく使えるものになっています。
ただ、悪いところとして、属性の順番などは無視してしまうところです。なので、if __name__=='__main__'以下のような辞書をXMLに変換すると、headタグよりbodyタグの方が上に来てしまうということが起こります。
あと、気をつけなければいけないのは、以下のようなデータを作りたいとき。
<html> <head> <title>タイトル</title> </head> <body> <p>あいうえお</p> <p>さしすせそ</p> </body> </html>
bodyタグ内にpタグが2つ入っているような場合、素直にはできません。こういう時は、
{'html': {'head': {'title': u'タイトル'}, 'body': [{'p': u'あいうえお'},{'p':u'さしすせそ'}] } }
みたいな辞書を作ってください。すると、こんな結果になります。
<html> <body> <p>あいうえお</p> <p>さしすせそ</p> </body> <head> <title>タイトル</title> </head> </html>
案の定、bodyとheadの位置が逆転しますが、一応抜けなく作ることができます。