Creating referenceable objects from XML

Gerard Flanagan grflanagan at yahoo.co.uk
Mon Dec 5 14:34:04 CET 2005


Michael Williams wrote:
> Hi All,
>
> I'm looking for a quality Python XML implementation.  All of the DOM
> and SAX implementations I've come across so far are rather
> convoluted.  Are there any quality implementations that will (after
> parsing the XML) return an object that is accessible by name? Such as
> the following:
>
>
>
>
> xml = """
> <book>
> 	<title>MyBook</title>
> 	<author>the author</author>
> </book>
> """
>
>
>
>
>
> And after parsing the XML allow me to access it as so:
>
> book.title
>
> I need it to somehow convert my XML to intuitively referenceable
> object.  Any ideas?  I could even do it myself if I knew the
> mechanism by which python classes do this (create variables on the fly).
>
> Thanks in advance!

Michael

Here's an approach to ElementTree that worked for me.  It's not generic
or anything and a bit brittle (eg. it won't handle missing nodes) but
maybe for a simple, flat schema or for a prototype?

All the best

Gerard

(TOY CODE - NOT TESTED MUCH)

from elementtree import ElementTree

class ElementWrapper(object):

    def __tostring(self):
        return ElementTree.tostring(self.element)

    def __fromstring(self, xml):
        self.element = ElementTree.fromstring(xml)

    xml = property( __tostring, __fromstring )

    def __init__(self, element=None):
        self.element = element

    def __str__(self):
        return self.xml

    def parse(self, infile):
        tree = ElementTree.parse(infile)
        self.element = tree.getroot()

    def write(self, outfile):
        ElementTree.ElementTree(self.element).write(outfile)

###########


from elementtree.ElementTree import Element
from elementwrapper import ElementWrapper

xmlns = 'http://schemas/email/0.1'


class MailDocument(ElementWrapper):

    def __build_element(self):
        root = Element('{%s}Mail' % xmlns)
        root.append( Element('{%s}Date' % xmlns) )
        root.append( Element('{%s}From' % xmlns) )
        root.append( Element('{%s}Subject' % xmlns) )
        root.append( Element('{%s}To' % xmlns) )
        root.append( Element('{%s}Cc' % xmlns) )
        root.append( Element('{%s}Body' % xmlns) )
        root.append( Element('{%s}Attachments' % xmlns) )
        self.element =  root

    #####################################################
    #    Properties
    #
    def __get_uid(self):
        return self.element.get('id')

    def __set_uid(self, id=''):
        self.element.set('id', id)

    def __get_date(self):
        return self.element[0].text

    def __set_date(self, value=''):
        self.element[0].text = value

    def __get_from(self):
        addr = self.element[1].get('address')
        nm = self.element[1].get('name')
        return addr, nm

    def __get_subject(self):
        return self.element[2].text

    def __set_subject(self, value=''):
        self.element[2].text = value

    def __get_body(self):
        return self.element[5].text

    def __set_body(self, value=''):
        self.element[5].text = value

    uid = property( __get_uid, __set_uid )
    From = property( __get_from)
    subject = property( __get_subject, __set_subject )
    date = property( __get_date, __set_date )
    body = property( __get_body, __set_body )

    def set_from_header(self, address='', name=''):
        self.element[1].set('address', address)
        self.element[1].set('name', name)
    #
    #    End Properties
    #####################################################

    #####################################################
    #    Lists
    #
    def add_to_header(self, address='', name=''):
        self.__add_mailto( self.element[3], address, name )

    def remove_to_header(self, index):
        elem = self.element[3][index]
        self.element[3].remove(elem)

    def add_cc_header(self, address='', name=''):
        self.__add_mailto( self.element[4], address, name )

    def remove_cc_header(self, index):
        elem = self.element[4][index]
        self.element[4].remove(elem)

    def add_attachment(self, filename='', fileuri='', filetype=''):
        elem = Element("{%s}Uri" % xmlns, value=fileuri, type=filetype
)
        elem.text = filename
        self.element[6].append( elem )

    def remove_attachment(self, index):
        elem = self.element[6][index]
        self.element[6].remove(elem)

    def __add_mailto(self, element, Address='', Name=''):
        element.append( Element("{%s}mailto" % xmlns, address=Address,
name=Name ) )

    def get_to_headers(self):
        hdrs = []
        for item in self.element[3]:
            hdrs.append( ( item.get('address'), item.get('name') ) )
        return hdrs

    def get_cc_headers(self):
        hdrs = []
        for item in self.element[4]:
            hdrs.append( (item.get('address'), item.get('name') ) )
        return hdrs

    def get_attachments(self):
        ret = []
        for item in self.__element[6]:
            hdrs.append( (item.text, item.get('value'),
item.get('type') ) )
        return hdrs
    #
    #    End Lists
    ########################################################

    ########################################################
    #    Initialise
    #
    def __init__(self):
        self.__build_element()
        self.__set_uid()
        self.__set_date()
        self.__set_subject()
        self.set_from_header()
        self.__set_body()
    #
    #    End Initialise
    ########################################################

xml_test ='''
<mail:Mail xmlns:mail="http://schemas/email/0.1">
<mail:Date>10/10/05</mail:Date>
<mail:From address='me at org.org' name='Mr. Jones'/>
<mail:Subject>just a note</mail:Subject>
<mail:To>
    <mail:mailto address='you at org.org' name='Mrs Jones' />
    <mail:mailto address='a.nother at org.org' name='Alan Nother' />
</mail:To>
<mail:Cc></mail:Cc>
<mail:Body>hi there,
just a note to say hi there!</mail:Body>
<mail:Attachments></mail:Attachments>
</mail:Mail>
'''
if __name__ == '__main__':
    mail = MailDocument()
    mail.xml = xml_test
    #mail.parse('test/data/test.xml')
    print 'From: ' + mail.From[0]
    print 'Subject: ' + mail.subject
    mail.set_from_header('new at new.com')
    print 'From: ' + mail.From[0]
    mail.add_to_header('aaa.bbb at ccc', 'aaaaaa')
    mail.add_to_header('fff.ggg at hhh', 'ffffff')
    print 'To:'
    for hdr in mail.get_to_headers():
        print hdr
    mail.remove_to_header(1)
    print 'To:'
    for hdr in mail.get_to_headers():
        print hdr
    #mail.write('test_copy.xml')




More information about the Python-list mailing list