Skip to content

Commit 40a0cfb

Browse files
Backport PR pandas-dev#42464: BUG: to_xml with index=False and offset input index
1 parent f4278a6 commit 40a0cfb

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

doc/source/whatsnew/v1.3.1.rst

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Fixed regressions
2929
Bug fixes
3030
~~~~~~~~~
3131
- Fixed bug in :meth:`DataFrame.transpose` dropping values when the DataFrame had an Extension Array dtype and a duplicate index (:issue:`42380`)
32+
- Fixed bug in :meth:`DataFrame.to_xml` raising ``KeyError`` when called with ``index=False`` and an offset index (:issue:`42458`)
3233
-
3334

3435
.. ---------------------------------------------------------------------------

pandas/io/formats/xml.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,18 @@ def handle_indexes(self) -> None:
195195
This method will add indexes into attr_cols or elem_cols.
196196
"""
197197

198+
if not self.index:
199+
return
200+
201+
first_key = next(iter(self.frame_dicts))
198202
indexes: list[str] = [
199-
x for x in self.frame_dicts[0].keys() if x not in self.orig_cols
203+
x for x in self.frame_dicts[first_key].keys() if x not in self.orig_cols
200204
]
201205

202-
if self.attr_cols and self.index:
206+
if self.attr_cols:
203207
self.attr_cols = indexes + self.attr_cols
204208

205-
if self.elem_cols and self.index:
209+
if self.elem_cols:
206210
self.elem_cols = indexes + self.elem_cols
207211

208212
def get_prefix_uri(self) -> str:
@@ -307,7 +311,7 @@ def build_tree(self) -> bytes:
307311
self.elem_row = SubElement(self.root, f"{self.prefix_uri}{self.row_name}")
308312

309313
if not self.attr_cols and not self.elem_cols:
310-
self.elem_cols = list(self.frame_dicts[0].keys())
314+
self.elem_cols = list(self.d.keys())
311315
self.build_elems()
312316

313317
else:
@@ -477,7 +481,7 @@ def build_tree(self) -> bytes:
477481
self.elem_row = SubElement(self.root, f"{self.prefix_uri}{self.row_name}")
478482

479483
if not self.attr_cols and not self.elem_cols:
480-
self.elem_cols = list(self.frame_dicts[0].keys())
484+
self.elem_cols = list(self.d.keys())
481485
self.build_elems()
482486

483487
else:

pandas/tests/io/xml/test_to_xml.py

+43-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
from pandas.compat import PY38
1313
import pandas.util._test_decorators as td
1414

15-
from pandas import DataFrame
15+
from pandas import (
16+
DataFrame,
17+
Index,
18+
)
1619
import pandas._testing as tm
1720

1821
from pandas.io.common import get_handle
@@ -291,6 +294,45 @@ def test_index_false_rename_row_root(datapath, parser):
291294
assert output == expected
292295

293296

297+
@pytest.mark.parametrize(
298+
"offset_index", [list(range(10, 13)), [str(i) for i in range(10, 13)]]
299+
)
300+
def test_index_false_with_offset_input_index(parser, offset_index):
301+
"""
302+
Tests that the output does not contain the `<index>` field when the index of the
303+
input Dataframe has an offset.
304+
305+
This is a regression test for issue #42458.
306+
"""
307+
308+
expected = """\
309+
<?xml version='1.0' encoding='utf-8'?>
310+
<data>
311+
<row>
312+
<shape>square</shape>
313+
<degrees>360</degrees>
314+
<sides>4.0</sides>
315+
</row>
316+
<row>
317+
<shape>circle</shape>
318+
<degrees>360</degrees>
319+
<sides/>
320+
</row>
321+
<row>
322+
<shape>triangle</shape>
323+
<degrees>180</degrees>
324+
<sides>3.0</sides>
325+
</row>
326+
</data>"""
327+
328+
offset_geom_df = geom_df.copy()
329+
offset_geom_df.index = Index(offset_index)
330+
output = offset_geom_df.to_xml(index=False, parser=parser)
331+
output = equalize_decl(output)
332+
333+
assert output == expected
334+
335+
294336
# NA_REP
295337

296338
na_expected = """\

0 commit comments

Comments
 (0)