Why is there no functional xml?
Peter Otten
__peter__ at web.de
Sun Jan 21 06:20:36 EST 2018
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>
>>>
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.
More information about the Python-list
mailing list