103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
# w.c.s. - web application for online forms
|
|
# Copyright (C) 2005-2014 Entr'ouvert
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program 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 General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from quixote import get_publisher
|
|
|
|
from .misc import indent_xml
|
|
from .storage import StorableObject
|
|
|
|
class XmlStorableObject(StorableObject):
|
|
XML_NODES = []
|
|
|
|
@classmethod
|
|
def storage_load(cls, fd):
|
|
first_byte = fd.read(1)
|
|
fd.seek(0)
|
|
if first_byte == '<':
|
|
return cls.import_from_xml(fd, include_id=True)
|
|
else:
|
|
return StorableObject.storage_load(fd)
|
|
|
|
@classmethod
|
|
def storage_dumps(cls, object):
|
|
return object.export_to_xml_string(include_id=True)
|
|
|
|
def export_to_xml(self, include_id=False):
|
|
charset = get_publisher().site_charset
|
|
root = ET.Element(self._xml_tagname)
|
|
if include_id and self.id:
|
|
root.attrib['id'] = str(self.id)
|
|
for attribute in self.XML_NODES:
|
|
attribute_name, attribute_type = attribute
|
|
if not getattr(self, attribute_name, None):
|
|
continue
|
|
element = ET.SubElement(root, attribute_name)
|
|
getattr(self, 'export_%s_to_xml' % attribute_type)(element,
|
|
attribute_name, charset=charset)
|
|
return root
|
|
|
|
def export_str_to_xml(self, element, attribute_name, charset):
|
|
element.text = unicode(getattr(self, attribute_name), charset)
|
|
|
|
def export_int_to_xml(self, element, attribute_name, charset):
|
|
element.text = str(getattr(self, attribute_name))
|
|
|
|
def export_to_xml_string(self, include_id=False):
|
|
x = self.export_to_xml(include_id=include_id)
|
|
indent_xml(x)
|
|
return ET.tostring(x)
|
|
|
|
def import_from_xml(cls, fd, charset=None, include_id=False):
|
|
try:
|
|
tree = ET.parse(fd)
|
|
except:
|
|
raise ValueError()
|
|
return cls.import_from_xml_tree(tree, charset=charset,
|
|
include_id=include_id)
|
|
import_from_xml = classmethod(import_from_xml)
|
|
|
|
def import_from_xml_tree(cls, tree, include_id=False, charset=None):
|
|
if charset is None:
|
|
charset = get_publisher().site_charset
|
|
obj = cls()
|
|
|
|
# if the tree we get is actually a ElementTree for real, we get its
|
|
# root element and go on happily.
|
|
if not ET.iselement(tree):
|
|
tree = tree.getroot()
|
|
|
|
if include_id and tree.attrib.get('id'):
|
|
obj.id = tree.attrib.get('id')
|
|
|
|
for attribute in cls.XML_NODES:
|
|
attribute_name, attribute_type = attribute
|
|
element = tree.find(attribute_name)
|
|
if element is None:
|
|
continue
|
|
setattr(obj, attribute_name,
|
|
getattr(obj, 'import_%s_from_xml' %
|
|
attribute_type)(element, charset=charset))
|
|
return obj
|
|
import_from_xml_tree = classmethod(import_from_xml_tree)
|
|
|
|
def import_str_from_xml(self, element, charset):
|
|
return element.text.encode(charset)
|
|
|
|
def import_int_from_xml(self, element, charset):
|
|
return int(element.text)
|