'''
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)