diff --git a/odml/fileio.py b/odml/fileio.py index ba10b97a..00d54da9 100644 --- a/odml/fileio.py +++ b/odml/fileio.py @@ -25,7 +25,7 @@ def load(filename, backend="xml", show_warnings=True): return reader.from_file(filename) -def save(obj, filename, backend="xml"): +def save(obj, filename, backend="xml", **kwargs): """ Save an open odML document to file of a specified format. :param obj: odML document do be saved. @@ -33,11 +33,15 @@ def save(obj, filename, backend="xml"): should be saved. :param backend: Format in which the odML document is to be saved. The default format is XML. + :param kwargs: Writer backend keyword arguments e.g. for adding specific + stylesheets for xml documents or specifying an RDF format. + Refer to the documentation of the available parsers to check + which arguments are supported. """ writer = ODMLWriter(backend) if "." not in filename.split(os.pathsep)[-1]: filename = filename + ".%s" % backend - return writer.write_file(obj, filename) + return writer.write_file(obj, filename, **kwargs) def display(obj, backend="xml"): diff --git a/odml/tools/odmlparser.py b/odml/tools/odmlparser.py index 1e3f8f6a..a0d76728 100644 --- a/odml/tools/odmlparser.py +++ b/odml/tools/odmlparser.py @@ -46,7 +46,7 @@ def __init__(self, parser='XML'): self.parser = parser - def write_file(self, odml_document, filename): + def write_file(self, odml_document, filename, **kwargs): """ Writes an odml.Document to a file using the format defined in the ODMLWriter.parser property. Supported formats are @@ -55,6 +55,8 @@ def write_file(self, odml_document, filename): :param odml_document: odml.Document. :param filename: path and filename of the output file. + :param kwargs: Writer backend keyword arguments. Refer to the documentation + of the available parsers to check which arguments are supported. """ # Write document only if it does not contain validation errors. @@ -74,30 +76,44 @@ def write_file(self, odml_document, filename): msg += " Run the Documents 'validate' method to access them.\n%s" % report warnings.warn(msg) - with open(filename, 'w') as file: - # Add XML header to support odML stylesheets. - if self.parser == 'XML': - file.write(xmlparser.XMLWriter.header) - - file.write(self.to_string(odml_document)) + # Allow kwargs when writing XML documents to support individual style sheets + if self.parser == 'XML': + local_style = False + custom_template = None + + if "local_style" in kwargs and isinstance(kwargs["local_style"], bool): + local_style = kwargs["local_style"] + if "custom_template" in kwargs and isinstance(kwargs["custom_template"], str): + custom_template = kwargs["custom_template"] + xmlparser.XMLWriter(odml_document).write_file(filename, local_style=local_style, + custom_template=custom_template) + else: + with open(filename, 'w') as file: + file.write(self.to_string(odml_document, **kwargs)) - def to_string(self, odml_document): + def to_string(self, odml_document, **kwargs): """ Parses an odml.Document to a string in the file format defined in the ODMLWriter.parser property. Supported formats are - JSON, XML, YAML and RDF. + JSON, YAML and RDF. :param odml_document: odml.Document. + :param kwargs: Writer backend keyword arguments e.g. for adding specific + stylesheets for xml documents or specifying an RDF format. + Refer to the documentation of the available parsers to check + which arguments are supported. + :return: string containing the content of the odml.Document in the specified format. """ string_doc = '' - if self.parser == 'XML': - string_doc = unicode(xmlparser.XMLWriter(odml_document)) - elif self.parser == "RDF": - # Use XML as default output format for now. - string_doc = RDFWriter(odml_document).get_rdf_str("xml") + if self.parser == "RDF": + rdf_format = "xml" + if "rdf_format" in kwargs and isinstance(kwargs["rdf_format"], str): + rdf_format = kwargs["rdf_format"] + + string_doc = RDFWriter(odml_document).get_rdf_str(rdf_format) else: self.parsed_doc = DictWriter().to_dict(odml_document) diff --git a/test/test_fileio.py b/test/test_fileio.py index 5f2ff54a..041c3379 100644 --- a/test/test_fileio.py +++ b/test/test_fileio.py @@ -27,6 +27,14 @@ def test_load_save(self): odml.save(doc, file_name) os.remove(file_name) + def test_save_kwargs(self): + doc = odml.load(self.file) + file_name = "%s_copy" % self.file + + # Test unsupported kwarg does not raise an exception + odml.save(doc, file_name, unsupported_kwarg="I do not matter") + os.remove(file_name) + def test_display(self): doc = odml.load(self.file) odml.display(doc) diff --git a/test/test_parser_odml.py b/test/test_parser_odml.py index ba233109..93674eb8 100644 --- a/test/test_parser_odml.py +++ b/test/test_parser_odml.py @@ -68,6 +68,39 @@ def test_xml_file(self): self.assertEqual(xml_doc, self.odml_doc) + def test_xml_file_kwargs(self): + # Check unsupported kwargs + self.xml_writer.write_file(self.odml_doc, self.xml_file, + invalid_a=False, invalid_b=None, invalid_c="naughty") + xml_doc = self.xml_reader.from_file(self.xml_file) + + self.assertEqual(xml_doc, self.odml_doc) + + # Check invalid local_style + self.xml_writer.write_file(self.odml_doc, self.xml_file, local_style="this is not good") + xml_doc = self.xml_reader.from_file(self.xml_file) + + self.assertEqual(xml_doc, self.odml_doc) + + # Check valid local_style + self.xml_writer.write_file(self.odml_doc, self.xml_file, local_style=True) + xml_doc = self.xml_reader.from_file(self.xml_file) + + self.assertEqual(xml_doc, self.odml_doc) + + # Check invalid custom template + self.xml_writer.write_file(self.odml_doc, self.xml_file, custom_template=True) + xml_doc = self.xml_reader.from_file(self.xml_file) + + self.assertEqual(xml_doc, self.odml_doc) + + # Check custom template + custom = "" + self.xml_writer.write_file(self.odml_doc, self.xml_file, custom_template=custom) + xml_doc = self.xml_reader.from_file(self.xml_file) + + self.assertEqual(xml_doc, self.odml_doc) + def test_yaml_file(self): self.yaml_writer.write_file(self.odml_doc, self.yaml_file) yaml_doc = self.yaml_reader.from_file(self.yaml_file) @@ -143,6 +176,22 @@ def test_rdf_file(self): self.assertIn(doc.sections[2].properties[1].name, rdf_sec3.properties) self.assertIn(doc.sections[2].properties[1].name, rdf_sec3.properties) + def test_rdf_file_kwargs(self): + + # Check unsupported kwarg + self.rdf_writer.write_file(self.odml_doc, self.rdf_file, + invalid_a=False, invalid_b=None, invalid_c="naughty") + self.rdf_reader.from_file(self.rdf_file, "xml") + + # Check unsupported backend + with self.assertRaises(ValueError): + self.rdf_writer.write_file(self.odml_doc, self.rdf_file, rdf_format="i do not exist") + + # Check supported backend different from xml + rdf_format = "turtle" + self.rdf_writer.write_file(self.odml_doc, self.rdf_file, rdf_format=rdf_format) + self.rdf_reader.from_file(self.rdf_file, rdf_format) + def test_xml_string(self): # Read from string author = "HPL"