Why is there no functional xml?
Rustom Mody
rustompmody at gmail.com
Sun Jan 21 10:24:31 EST 2018
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]
More information about the Python-list
mailing list