• Facebook
  • Twitter
  • Reddit
  • StumbleUpon
  • Digg
  • email

'''
Simplified xml writing with python. Makes things more OO.
Copyright (C) 2006 James Kassemi
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
    doc = XML()
    for node, item in doc.channel('employee', list):
        node.name = item['name']
        node.date = item['date']
 
        =>
 
    <employee name="blah" date="Jan 1..." />
    <employee name="blah" date="Jan 2..." />
 
    ____________________________________________________
 
    doc = XML()
    for node, item in doc.channel('employee', list):
        node.name = item['name']
        for node2, item2 in node.channel('properties', item['eprops']):
            node2.prop1 = item2['prop1']
            node2.prop2 = item2['prop2']
            node2(item2['name'])
        =>
 
    <employee name="blah">
        <properties prop1="blah" prop2="blah">Name</properties>
    </employee>
 
    <employee name="blah">
        <properties prop1="blah2" prop2="blah3">Name2</properties>
    </employee>
 
 
'''
 
import xml.sax.saxutils
import rfc822
import time
import datetime
 
def rfc_date(dt):
    tt = int(time.mktime(dt.timetuple()))
    return rfc822.formatdate(tt)
 
class XML(object):
    def __init__(self, name='root', values=[], parent=False, encoding='iso-8859-1'):
        self.name = name
        self.encoding = encoding
        self.nodetype = 0
        self.inner = None
        self.children = []
        self.values = values
        self.value_length = len(values)
        self.index = 0
        self.parent = parent
        self.properties = {}
 
    def __call__(self, value, cdata=False):
        if isinstance(value, datetime.datetime):
            value = rfc_date(dt)
 
        value = str(value)
        if cdata:
            self.inner = '<![CDATA[\n' + value + ']]>'
        else:
            self.inner = value
 
    def __setattr__(self, name, value):
        if hasattr(self, 'properties') and not hasattr(self, name):
            self.properties[name] = value
        else:
            object.__setattr__(self, name, value)
 
    def __iter__(self):
        return self
 
    def generate(self, parent_count=0):
        if parent_count == 0:
            r = '<?xml version="1.0" encoding="%s"?>\n' % self.encoding
 
        tab = '  ' * parent_count
 
        r = '%s<%s' % (tab, self.name) + ' '.join([' %s="%s"' % (k, v) for k, v in self.properties.iteritems()])
        if self.children == [] and self.inner == None:
            r += ' />\n'
        else:
            r += '>'
            if self.children != []:
                r += '\n'
                for child in self.children:
                    r += child.generate(parent_count=(parent_count + 1))
            elif self.inner != None:
                r += self.inner
            r += '</%s>\n' % (self.name)
 
        return r
 
    def next(self):
        if self.index == self.value_length:
            self.index = 0
            raise StopIteration
 
        new = XML(self.name, parent=self)
        ret = (new, self.values[self.index])
        self.parent.children.append(new)
        self.index = self.index + 1
        return ret
 
    def channel(self, name, values):
        if self.nodetype == 2:
            raise ValueError(''' Node type already specified. ''')
        self.nodetype = 1
        return XML(name, values, parent=self)