ET.Elementを書き出せるDictっぽいものを作る
あらすじ
電気設備の計算をpythonでやる - suzukiyou blog
xml.etree.ElementTree.ElementTree.write()に関して - suzukiyou blog
以下略
ポイント
- プログラム上ではdict型(らしきもの)でいろいろ動かせるようにする
- 保存するときにElement型にしてtree.write()で出力する
- 読出するときはET.parse()で読んでdict型(らしきもの)に入れる。
- Dictでは動的型付けのまましたい。
- ただし変換した時にtagにあたるものや、ファイル内での唯一keyとなるnameとかはstrかunicodeとする。
- Elementに変換するときに型チェックを行いたい。intとかfloatはプログラム上での型情報を付加した上でstrに変換する。
- 読み出し時にDictを復元する。intとかは元通りに戻す。
- 保存・読出時にめんどくさそうなのでDictを要素に持つDictとかは作らない。再帰して終わらなさそう。
- とはいえ最低Dictには前者・後者が欲しい。プログラム上ではイテレータっぽい動きをしたい。
- とすれば、Dictはリストに前者・後者のポインタを持っときたい。
- 唯一keyがわかっていればポインタを再構成できる。
- fileハンドルを作ろう。そうすればファイルネームとかヘッダとかの管理もさせられる。
実際にやってみた
#EDsys.py #coding:utf-8 import xml.etree.ElementTree as ET from is_ETwritable import is_ETwritable from is_numeric import is_numeric class FileHandle(object): def __init__(self,filename): self.dict={} self.dict["filename"]=filename self.Items={} def __getitem__(self,key): return self.dict[key] def __setitem__(self,key,value): if is_ETwritable(key): self.dict[key]=value else: raise def setItem(self,item): if type(item)==Item: self.Items[item["name"]]=item else: raise def getItem(self,key): return self.Items[key] def write(self): a=ET.Element(self["filename"]) td=dict(self.dict) del td["filename"] for i in td: aa=ET.Element(i) if is_ETwritable(td[i]): aa.text=td[i] elif is_numeric(td[i]): aa.text=str(td[i]) aa.attrib["progtype"]=str(type(td[i])) else: raise a.append(aa) for i in self.Items: a.append(self.getItem(i).toElement()) t=ET.ElementTree(a) print self["filename"] t.write(self["filename"],"utf-8") class Item(object): def __init__(self,Itemtype,name): if is_ETwritable(Itemtype) and is_ETwritable(name): self.dict={} self.dict["Itemtype"]=Itemtype self.dict["name"]=name self.before=[] self.next=[] else: raise def __getitem__(self,key): return self.dict[key] def __setitem__(self,key,value): if is_ETwritable(key): self.dict[key]=value else: raise def setnext(self,node): if type(node)==Item: self.next.append(node) node.before.append(self) else: raise def setbefore(self,node): if type(node)==Item: self.before.append(node) node.next.append(self) else: raise """def dictprint(self): print self.dict.__repr__() def fullprint(self): self.dictprint() print "before" for i in self.before: i.dictprint() print "next" for i in self.next: i.dictprint()""" def toElement(self): a=ET.Element("Item") #print self.dict td=dict(self.dict) #print td for i in td: aa=ET.Element(i) #print i if is_ETwritable(td[i]): aa.text=td[i] elif is_numeric(td[i]): aa.text=str(td[i]) aa.attrib["progtype"]=str(type(td[i])) else: raise a.append(aa) for i in self.before: aa=ET.Element("before") aa.attrib["name"]=i["name"] a.append(aa) for i in self.next: aa=ET.Element("next") aa.attrib["name"]=i["name"] a.append(aa) return a def parse(filename): EL=ET.parse(filename).getroot() fh=FileHandle(filename) for i in EL.getchildren(): if i.tag =="Item": itemtype=None name=None somedict={} for j in i.getchildren(): if j.tag=="Itemtype": itemtype=j.text elif j.tag=="name": name=j.text elif j.tag=="next" or j.tag=="before": continue else: if "progtype" in j.attrib: somedict[j.tag]=typedecode(j.attrib["progtype"],j.text) assert not itemtype==None assert not name==None a=Item(itemtype,name) for i in somedict: a[i]=somedict[i] fh.setItem(a) else: fh[i.tag]=i.text for i in EL.findall("Item"): x=fh.getItem(i.find("name").text) for j in i.findall("before"): x.before.append(fh.getItem(j.attrib["name"])) for j in i.findall("next"): x.next.append(fh.getItem(j.attrib["name"])) return fh,EL def typedecode(str,value): if str=="<type 'int'>": return int(value) if str=="<type 'float'>": return float(value)
あとis_ETwritable.pyに関しては
#coding:utf-8 def is_ETwritable(string): if type(string)==str or type(str)==unicode: return True else: return False
おもむろに
これからこれつかいます。