diff --git a/src/tablib/formats/__init__.py b/src/tablib/formats/__init__.py index 5162a866..f24b637a 100644 --- a/src/tablib/formats/__init__.py +++ b/src/tablib/formats/__init__.py @@ -11,6 +11,7 @@ from ._csv import CSVFormat from ._json import JSONFormat from ._tsv import TSVFormat +from ._xml import XMLFormat uninstalled_format_messages = { "cli": {"package_name": "tabulate package", "extras_name": "cli"}, @@ -110,6 +111,7 @@ def register_builtins(self): self.register('rst', 'tablib.formats._rst.ReSTFormat') if find_spec('tabulate'): self.register('cli', 'tablib.formats._cli.CLIFormat') + self.register('xml', XMLFormat()) def formats(self): for key, frm in self._formats.items(): diff --git a/src/tablib/formats/_xml.py b/src/tablib/formats/_xml.py new file mode 100644 index 00000000..5a93d239 --- /dev/null +++ b/src/tablib/formats/_xml.py @@ -0,0 +1,32 @@ +""" Tablib - XML support. +""" + +import xml.etree.ElementTree as ET + + +class XMLFormat: + title = 'xml' + extensions = ('xml',) + + # TODO implement + # @classmethod + # def import_set(cls, dset, in_stream): + # dset.wipe() + + @classmethod + def export_set(cls, dataset): + root = ET.Element('dataset') + + for row_index, row in enumerate(dataset.dict): + row_node = ET.Element('row') + tags = dataset._data[row_index].tags + if tags: + row_node.set('tags', ','.join(tags)) + for header, value in row.items(): + value_node = ET.Element(header) + value_node.text = str(value) + row_node.append(value_node) + + root.append(row_node) + + return ET.tostring(root).decode() diff --git a/tests/test_tablib.py b/tests/test_tablib.py index ca57d00b..45467abf 100755 --- a/tests/test_tablib.py +++ b/tests/test_tablib.py @@ -1350,3 +1350,34 @@ def test_cli_export_grid(self): '+---+---+---+\n| a | b | c |\n+---+---+---+', tablib.Dataset(['a', 'b', 'c']).export('cli', tablefmt='grid') ) + + +class XMLTests(BaseTestCase): + def test_xml_export(self): + """Verify exporting dataset object as XML.""" + + xml = '' + for row in self.founders: + xml += '' + for i, header in enumerate(self.founders.headers): + xml += '<{}>{}'.format(header, row[i], header) + xml += '' + xml += '' + + self.assertEqual(xml, self.founders.xml) + + def test_xml_export_row_with_tag(self): + """Verify exporting dataset with row tags object as XML.""" + + local_data = tablib.Dataset(headers=['A', 'B']) + local_data.append(('a', 'b'), tags=['tag 1', 'tag 2']) + + xml = '' + for row_index, row in enumerate(local_data): + xml += ''.format(','.join(local_data._data[row_index].tags)) + for header_index, header in enumerate(local_data.headers): + xml += '<{}>{}'.format(header, row[header_index], header) + xml += '' + xml += '' + + self.assertEqual(xml, local_data.xml)