Skip to content

Commit a5073bf

Browse files
FIX: Gracefully handle bad XML files in EGI reader (#13145)
1 parent e7a593a commit a5073bf

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

doc/changes/devel/13145.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improved the handling of problematic MFF files in `mne.io.read_raw_egi` by `Scott Huberty`_.

mne/io/egi/events.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ def _read_mff_events(filename, sfreq):
4848
orig = {}
4949
for xml_file in glob(join(filename, "*.xml")):
5050
xml_type = splitext(basename(xml_file))[0]
51-
orig[xml_type] = _parse_xml(xml_file)
51+
et = _parse_xml(xml_file)
52+
if et is not None:
53+
orig[xml_type] = et
5254
xml_files = orig.keys()
5355
xml_events = [x for x in xml_files if x[:7] == "Events_"]
5456
for item in orig["info"]:
@@ -80,10 +82,14 @@ def _read_mff_events(filename, sfreq):
8082
return events_tims, code
8183

8284

83-
def _parse_xml(xml_file):
85+
def _parse_xml(xml_file: str) -> list[dict[str, str]] | None:
8486
"""Parse XML file."""
8587
defusedxml = _soft_import("defusedxml", "reading EGI MFF data")
86-
xml = defusedxml.ElementTree.parse(xml_file)
88+
try:
89+
xml = defusedxml.ElementTree.parse(xml_file)
90+
except defusedxml.ElementTree.ParseError as e:
91+
warn(f"Could not parse the XML file {xml_file}: {e}")
92+
return
8793
root = xml.getroot()
8894
return _xml2list(root)
8995

mne/io/egi/tests/test_egi.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,16 @@ def test_set_standard_montage_mff(fname, standard_montage):
586586
# Check that the reference remained
587587
for pick in picks:
588588
assert_allclose(raw.info["chs"][pick]["loc"][3:6], ref_loc)
589+
590+
591+
@requires_testing_data
592+
def test_egi_mff_bad_xml(tmp_path):
593+
"""Test that corrupt XML files are gracefully handled."""
594+
pytest.importorskip("defusedxml")
595+
mff_fname = shutil.copytree(egi_mff_fname, tmp_path / "test_egi_bad_xml.mff")
596+
bad_xml = mff_fname / "bad.xml"
597+
bad_xml.write_text("<foo>", encoding="utf-8")
598+
with pytest.warns(RuntimeWarning, match="Could not parse the XML"):
599+
raw = read_raw_egi(mff_fname)
600+
# little check that the bad XML doesn't affect the parsing of other xml files
601+
assert "DIN1" in raw.annotations.description

0 commit comments

Comments
 (0)