diff --git a/pandas/io/formats/xml.py b/pandas/io/formats/xml.py index 5725975bb6278..ee19f27fe8df6 100644 --- a/pandas/io/formats/xml.py +++ b/pandas/io/formats/xml.py @@ -251,18 +251,11 @@ def other_namespaces(self) -> dict: """ nmsp_dict: dict[str, str] = {} - if self.namespaces and self.prefix is None: - nmsp_dict = { - "xmlns": n # noqa: RUF011 - for p, n in self.namespaces.items() - if p != "" - } - - if self.namespaces and self.prefix: + if self.namespaces: nmsp_dict = { - "xmlns": n # noqa: RUF011 + f"xmlns{p if p=='' else f':{p}'}": n for p, n in self.namespaces.items() - if p == "" + if n != self.prefix_uri[1:-1] } return nmsp_dict @@ -365,16 +358,16 @@ def build_tree(self) -> bytes: elem_row = self.build_attribs(d, elem_row) self.build_elems(d, elem_row) - self.out_xml = tostring(self.root, method="xml", encoding=self.encoding) + self.out_xml = tostring( + self.root, + method="xml", + encoding=self.encoding, + xml_declaration=self.xml_declaration, + ) if self.pretty_print: self.out_xml = self.prettify_tree() - if self.xml_declaration: - self.out_xml = self.add_declaration() - else: - self.out_xml = self.remove_declaration() - if self.stylesheet is not None: raise ValueError( "To use stylesheet, you need lxml installed and selected as parser." @@ -395,8 +388,10 @@ def get_prefix_uri(self) -> str: uri = f"{{{self.namespaces[self.prefix]}}}" except KeyError: raise KeyError(f"{self.prefix} is not included in namespaces") - else: + elif "" in self.namespaces: uri = f'{{{self.namespaces[""]}}}' + else: + uri = "" return uri @@ -418,31 +413,6 @@ def prettify_tree(self) -> bytes: return dom.toprettyxml(indent=" ", encoding=self.encoding) - def add_declaration(self) -> bytes: - """ - Add xml declaration. - - This method will add xml declaration of working tree. Currently, - xml_declaration is supported in etree starting in Python 3.8. - """ - decl = f'\n' - - return ( - self.out_xml - if self.out_xml.startswith(b" bytes: - """ - Remove xml declaration. - - This method will remove xml declaration of working tree. Currently, - pretty_print is not supported in etree. - """ - - return self.out_xml.split(b"?>")[-1].strip() - class LxmlXMLFormatter(BaseXMLFormatter): """ @@ -513,8 +483,10 @@ def get_prefix_uri(self) -> str: uri = f"{{{self.namespaces[self.prefix]}}}" except KeyError: raise KeyError(f"{self.prefix} is not included in namespaces") - else: + elif "" in self.namespaces: uri = f'{{{self.namespaces[""]}}}' + else: + uri = "" return uri diff --git a/pandas/tests/io/xml/test_to_xml.py b/pandas/tests/io/xml/test_to_xml.py index ebd52a21a00fe..a6ed15f56d8d4 100644 --- a/pandas/tests/io/xml/test_to_xml.py +++ b/pandas/tests/io/xml/test_to_xml.py @@ -154,7 +154,6 @@ def equalize_decl(doc): ' + + + 0 + square + 360 + 4.0 + + + 1 + circle + 360 + + + + 2 + triangle + 180 + 3.0 + +""" + + output = geom_df.to_xml( + namespaces={"oth": "http://other.org", "ex": "http://example.com"}, + parser=parser, + ) + output = equalize_decl(output) + + assert output == expected + + # PREFIX @@ -750,7 +782,7 @@ def test_missing_prefix_in_nmsp(parser, geom_df): def test_namespace_prefix_and_default(parser, geom_df): expected = """\ - + 0 square @@ -778,13 +810,6 @@ def test_namespace_prefix_and_default(parser, geom_df): ) output = equalize_decl(output) - if output is not None: - # etree and lxml differs on order of namespace prefixes - output = output.replace( - 'xmlns:doc="http://other.org" xmlns="http://example.com"', - 'xmlns="http://example.com" xmlns:doc="http://other.org"', - ) - assert output == expected