Advice for editing xml file using ElementTree and wxPython
Rick Muller
rpmuller at gmail.com
Sun Dec 9 09:20:58 EST 2007
On Dec 8, 11:57 pm, Waldemar Osuch <waldemar.os... at gmail.com> wrote:
> On Dec 8, 8:35 pm, Rick Muller <rpmul... at gmail.com> wrote:
>
>
>
> > I'm a computational chemist who frequently dabbles in Python. A
> > collaborator sent me a huge XML file that at one point was evidently
> > modified by a now defunct java application. A sample of this file
> > looks something like:
>
> > <group type="struct">
> > <name>Test</name>
> > <param type="string">
> > <name>File Name</name>
> > <cTag>fileName</cTag>
> > <desc>Name of the input file</desc>
> > <value>water</value>
> > </param>
> > <param type="int">
> > <name>Number of Atoms</name>
> > <cTag>natoms</cTag>
> > <desc>Number of atoms in the molecule</desc>
> > <value>3</value>
> > </param>
> > </group>
>
> <snip>
>
>
>
> > Seems like this is something that's probably pretty common, modifying
> > a data structure using a gui, so I'm hoping that someone has thought
> > about this and has some good advice about best practices here.
>
> The trick is to keep a reference to the actual ElementTree objects
> as you build your TreeCtrl. Ability to store arbitrary Python object
> in the TreeCtrl Item makes it easy. In an event handler modify the
> original element and you are done. Do not forget to save when
> closing.
>
> If the XML file is very large you may have performance issues since
> the whole parsed tree is kept in memory. Luckily the ElementTree
> representation is lean.
>
> A sample below shows the approach. It is very basic but I hope it
> conveys the idea. Please note that edits to the actual tags are
> ignored.
>
> -------------------------------------------------------------------
> import wx
> import xml.etree.cElementTree as ET
>
> class MainFrame(wx.Frame):
> def __init__(self, fpath):
> wx.Frame.__init__(self, None)
> self.fpath = fpath
> self.xml = ET.parse(fpath)
> self.tree = wx.TreeCtrl(self,
> style=wx.TR_HAS_BUTTONS|wx.TR_EDIT_LABELS)
> root = self.fillmeup()
> self.tree.Expand(root)
>
> self.Bind(wx.EVT_CLOSE, self.OnClose)
> self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEdit)
>
> def fillmeup(self):
> xml = self.xml.getroot()
> tree = self.tree
> root = tree.AddRoot(xml.tag)
> def add(parent, elem):
> for e in elem:
> item = tree.AppendItem(parent, e.tag, data=None)
> text = e.text.strip()
> if text:
> val = tree.AppendItem(item, text)
> tree.SetPyData(val, e)
> add(item, e)
> add(root, xml)
> return root
>
> def OnEdit(self, evt):
> elm = self.tree.GetPyData(evt.Item)
> if elm is not None:
> elm.text = evt.Label
>
> def OnClose(self, evt):
> self.xml.write(self.fpath)
> self.Destroy()
>
> if __name__=='__main__':
> app = wx.App(False)
> frame = MainFrame('sample.xml')
> frame.Show()
> app.MainLoop()
This was exactly what I was looking for! Thanks very much.
Rick
More information about the Python-list
mailing list