On Sunday, January 21, 2018 at 4:51:34 PM UTC+5:30, Peter Otten wrote: > Rustom Mody wrote: > > > Looking around for how to create (l)xml one sees typical tutorials like > > this: > > > > https://www.blog.pythonlibrary.org/2013/04/30/python-101-intro-to-xml-parsing-with-elementtree/ > > > > > > > > Given the requirement to build up this xml: > > <zAppointments reminder="15"> > > <appointment> > > <begin>1181251680</begin> > > <uid>040000008200E000</uid> > > <alarmTime>1181572063</alarmTime> > > <state></state> > > <location></location> > > <duration>1800</duration> > > <subject>Bring pizza home</subject> > > </appointment> > > </zAppointments> > > > > > > > > the way I would rather do it is thus: > > > > [Note in actual practice the 'contents' such as 1181251680 etc would come > > from suitable program variables/function-calls > > ] > > > > > > ex = Ea("zAppointments", {'reminder':'15'}, > > E("appointment", > > En("begin", 1181251680), > > Et("uid", "040000008200E000"), > > En("alarmTime", 1181572063), > > E("state"), > > E("location"), > > En("duration",1800), > > Et("subject", "Bring pizza home"))) > > > > > > with the following obvious definitions: > > > > [The function names are short so that the above becomes correspondingly > > [readable] > > > > > > from lxml.etree import Element > > > > def Ea(tag, attrib=None, *subnodes): > > "xml node constructor" > > root = Element(tag, attrib) > > for n in subnodes: > > root.append(n) > > return root > > > > def E(tag, *subnodes): > > "Like E but without attributes" > > root = Element(tag) > > for n in subnodes: > > root.append(n) > > return root > > > > def Et(tag, text): > > "A pure text node" > > root = E(tag) > > root.text = text > > return root > > > > def En(tag, text): > > "A node containing a integer" > > root = E(tag) > > root.text = str(text) > > return root > > > > > > This approach seems so obvious that I find it hard to believe its not > > there somewhere… Am I missing something?? > > lxml.objectify? > > >>> from lxml import etree > >>> from lxml.objectify import E > >>> appointments = E.appointments( > ... E.appointment( > ... E.begin(1181251680), > ... E.uid("040000008200E000"), > ... E.alarmTime(1181572063), > ... E.state(), > ... E.location(), > ... E.duration(1800), > ... E.subject("Bring pizza home") > ... ), > ... reminder="15" > ... ) > >>> print(etree.tostring(appointments, pretty_print=True, encoding=str)) > <appointments xmlns:py="http://codespeak.net/lxml/objectify/pytype" > xmlns:xsd="http://www.w3.org/2001/XMLSchema" > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" reminder="15"> > <appointment> > <begin py:pytype="int">1181251680</begin> > <uid py:pytype="str">040000008200E000</uid> > <alarmTime py:pytype="int">1181572063</alarmTime> > <state/> > <location/> > <duration py:pytype="int">1800</duration> > <subject py:pytype="str">Bring pizza home</subject> > </appointment> > </appointments> > > >>>
Nice! I almost liked it… Then noticed that the attribute dict is in the wrong place Here's the same without any namespace malarky: >>> E = objectify.ElementMaker(annotate=False,namespace=None,nsmap=None) >>> appointments = E.appointments( E.appointment( E.begin(1181251680), E.uid("040000008200E000"), E.alarmTime(1181572063), E.state(), E.location(), E.duration(1800), E.subject("Bring pizza home") ), reminder="15" ) >>> print(et.tostring(appointments,pretty_print=1).decode('ascii')) <appointments reminder="15"> <appointment> <begin>1181251680</begin> <uid>040000008200E000</uid> <alarmTime>1181572063</alarmTime> <state/> <location/> <duration>1800</duration> <subject>Bring pizza home</subject> </appointment> </appointments> >>> Its obviously easier in python to put optional/vararg parameters on the right side rather than on the left of a parameter list. But its not impossible to get it in the desired order — one just has to 'hand-parse' the parameter list received as a *param Thusly: appointments = E.appointments( {"reminder":"15"}, E.appointment( E.begin(1181251680), E.uid("040000008200E000"), E.alarmTime(1181572063), E.state(), E.location(), E.duration(1800), E.subject("Bring pizza home") ) ) > > Personally I'd probably avoid the extra layer and write a function that > directly maps dataclasses or database records to xml using the conventional > elementtree API. I dont understand… [I find the OO/imperative style of making a half-done node and then throwing piece-by-piece of contents in/at it highly aggravating] -- https://mail.python.org/mailman/listinfo/python-list