Skip to content

Commit d90f06a

Browse files
BUG: to_xml with index=False and offset input index
Fixes pandas-dev#42458 It was assumed that the index contains the element `0`. This led to a defect when the index of the input Dataframe has an offset, which is a common use case when streaming Dataframes via generators. This fix consists of not relying on accessing the `0` element of `frame_dicts`.
1 parent 87d7855 commit d90f06a

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

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_dict = next(iter(self.frame_dicts.values()))
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 first_dict.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(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(d.keys())
481485
self.build_elems()
482486

483487
else:

pandas/tests/io/xml/test_to_xml.py

+36
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,42 @@ def test_index_false_rename_row_root(datapath, parser):
290290
assert output == expected
291291

292292

293+
def test_index_false_with_offset_input_index(parser):
294+
"""
295+
Tests that the output does not contain the `<index>` field when the index of the
296+
input Dataframe has an offset.
297+
298+
This is a regression test for issue #42458.
299+
"""
300+
301+
expected = """\
302+
<?xml version='1.0' encoding='utf-8'?>
303+
<data>
304+
<row>
305+
<shape>square</shape>
306+
<degrees>360</degrees>
307+
<sides>4.0</sides>
308+
</row>
309+
<row>
310+
<shape>circle</shape>
311+
<degrees>360</degrees>
312+
<sides/>
313+
</row>
314+
<row>
315+
<shape>triangle</shape>
316+
<degrees>180</degrees>
317+
<sides>3.0</sides>
318+
</row>
319+
</data>"""
320+
321+
offset_geom_df = geom_df.copy()
322+
offset_geom_df.index = range(10, len(geom_df.index) + 10)
323+
output = offset_geom_df.to_xml(index=False, parser=parser)
324+
output = equalize_decl(output)
325+
326+
assert output == expected
327+
328+
293329
# NA_REP
294330

295331
na_expected = """\

0 commit comments

Comments
 (0)