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