wcs/wcs/qommon/xml_storage.py

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)