diff --git a/doc/source/whatsnew/v1.3.1.rst b/doc/source/whatsnew/v1.3.1.rst index 255747c3c5c6d..c1cf9d208673f 100644 --- a/doc/source/whatsnew/v1.3.1.rst +++ b/doc/source/whatsnew/v1.3.1.rst @@ -27,6 +27,7 @@ Fixed regressions Bug fixes ~~~~~~~~~ - Fixed bug in :meth:`DataFrame.transpose` dropping values when the DataFrame had an Extension Array dtype and a duplicate index (:issue:`42380`) +- Fixed bug in :meth:`DataFrame.to_xml` raising ``KeyError`` when called with ``index=False`` and an offset index (:issue:`42458`) - .. --------------------------------------------------------------------------- diff --git a/pandas/io/formats/xml.py b/pandas/io/formats/xml.py index d2b86cc458b74..f5ba8c6b53335 100644 --- a/pandas/io/formats/xml.py +++ b/pandas/io/formats/xml.py @@ -195,14 +195,18 @@ def handle_indexes(self) -> None: This method will add indexes into attr_cols or elem_cols. """ + if not self.index: + return + + first_key = next(iter(self.frame_dicts)) indexes: list[str] = [ - x for x in self.frame_dicts[0].keys() if x not in self.orig_cols + x for x in self.frame_dicts[first_key].keys() if x not in self.orig_cols ] - if self.attr_cols and self.index: + if self.attr_cols: self.attr_cols = indexes + self.attr_cols - if self.elem_cols and self.index: + if self.elem_cols: self.elem_cols = indexes + self.elem_cols def get_prefix_uri(self) -> str: @@ -307,7 +311,7 @@ def build_tree(self) -> bytes: self.elem_row = SubElement(self.root, f"{self.prefix_uri}{self.row_name}") if not self.attr_cols and not self.elem_cols: - self.elem_cols = list(self.frame_dicts[0].keys()) + self.elem_cols = list(self.d.keys()) self.build_elems() else: @@ -477,7 +481,7 @@ def build_tree(self) -> bytes: self.elem_row = SubElement(self.root, f"{self.prefix_uri}{self.row_name}") if not self.attr_cols and not self.elem_cols: - self.elem_cols = list(self.frame_dicts[0].keys()) + self.elem_cols = list(self.d.keys()) self.build_elems() else: diff --git a/pandas/tests/io/xml/test_to_xml.py b/pandas/tests/io/xml/test_to_xml.py index 478f4c803479d..4f4815b9008ad 100644 --- a/pandas/tests/io/xml/test_to_xml.py +++ b/pandas/tests/io/xml/test_to_xml.py @@ -11,7 +11,10 @@ import pandas.util._test_decorators as td -from pandas import DataFrame +from pandas import ( + DataFrame, + Index, +) import pandas._testing as tm from pandas.io.common import get_handle @@ -290,6 +293,45 @@ def test_index_false_rename_row_root(datapath, parser): assert output == expected +@pytest.mark.parametrize( + "offset_index", [list(range(10, 13)), [str(i) for i in range(10, 13)]] +) +def test_index_false_with_offset_input_index(parser, offset_index): + """ + Tests that the output does not contain the `` field when the index of the + input Dataframe has an offset. + + This is a regression test for issue #42458. + """ + + expected = """\ + + + + square + 360 + 4.0 + + + circle + 360 + + + + triangle + 180 + 3.0 + +""" + + offset_geom_df = geom_df.copy() + offset_geom_df.index = Index(offset_index) + output = offset_geom_df.to_xml(index=False, parser=parser) + output = equalize_decl(output) + + assert output == expected + + # NA_REP na_expected = """\