From c52518f2d2aee382870d44ac3ca178cebae4f59b Mon Sep 17 00:00:00 2001 From: Petr Prikryl Date: Tue, 1 Feb 2022 10:21:02 +0100 Subject: [PATCH 1/2] Fix ElementTree.write XML prolog for encoding 'utf-8-sig' When ElementTree object is to be written to the file, and when BOM is needed, the 'utf-8-sig' can be used for the purpose. However, the XML prolog then looks like... ... and that encoding in the prolog makes no sense. Therefore, the utf-8-sig is changed to utf-8 for the purpose. --- Lib/xml/etree/ElementTree.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index e9409fd29a11572..802ddbc965caa24 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -738,6 +738,8 @@ def write(self, file_or_filename, # Retrieve the default encoding for the xml declaration import locale declared_encoding = locale.getpreferredencoding() + elif enc_lower == "utf-8-sig": + declared_encoding = "utf-8" write("\n" % ( declared_encoding,)) if method == "text": From 34fae67f84b1bd8811236faf5bc18560218fb19b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 12 Aug 2026 22:24:27 +0300 Subject: [PATCH 2/2] Omit the XML declaration for utf-8-sig, and add tests and NEWS Normalize the declared encoding before deciding whether to write the declaration, so that utf-8-sig is treated as utf-8: the BOM already determines the encoding. Co-Authored-By: Claude Opus 5 (1M context) --- Lib/test/test_xml_etree.py | 4 ++++ Lib/xml/etree/ElementTree.py | 4 ++-- .../Library/2026-08-12-22-15-00.gh-issue-90756.Qn7dLm.rst | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-08-12-22-15-00.gh-issue-90756.Qn7dLm.rst diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 0c944516ae115f1..2af2d1fd64520b1 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -933,6 +933,7 @@ def test_tostring_xml_declaration_cases(self): (b"\n" b"\xf8", 'ISO-8859-1', None), ('ø', 'unicode', None), + (b"\xef\xbb\xbf\xc3\xb8", 'utf-8-sig', None), # ... xml_declaration = False (b"ø", None, False), @@ -940,6 +941,7 @@ def test_tostring_xml_declaration_cases(self): (b"ø", 'US-ASCII', False), (b"\xf8", 'ISO-8859-1', False), ("ø", 'unicode', False), + (b"\xef\xbb\xbf\xc3\xb8", 'utf-8-sig', False), # ... xml_declaration = True (b"\n" @@ -952,6 +954,8 @@ def test_tostring_xml_declaration_cases(self): b"\xf8", 'ISO-8859-1', True), ("\n" "ø", 'unicode', True), + (b"\xef\xbb\xbf\n" + b"\xc3\xb8", 'utf-8-sig', True), ] for expected_retval, encoding, xml_declaration in TESTCASES: diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 2b9f061eb9b7d24..951540eb9f45e90 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -732,12 +732,12 @@ def write(self, file_or_filename, if not encoding: encoding = "us-ascii" with _get_writer(file_or_filename, encoding) as (write, declared_encoding): + if declared_encoding.lower() == "utf-8-sig": + declared_encoding = "utf-8" if method == "xml" and (xml_declaration or (xml_declaration is None and encoding.lower() != "unicode" and declared_encoding.lower() not in ("utf-8", "us-ascii"))): - if declared_encoding.lower() == "utf-8-sig": - declared_encoding = "utf-8" write("\n" % ( declared_encoding,)) if method == "text": diff --git a/Misc/NEWS.d/next/Library/2026-08-12-22-15-00.gh-issue-90756.Qn7dLm.rst b/Misc/NEWS.d/next/Library/2026-08-12-22-15-00.gh-issue-90756.Qn7dLm.rst new file mode 100644 index 000000000000000..dc15291d54a4ea4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-12-22-15-00.gh-issue-90756.Qn7dLm.rst @@ -0,0 +1,2 @@ +:meth:`xml.etree.ElementTree.ElementTree.write` now treats the ``utf-8-sig`` +encoding as ``utf-8`` in the XML declaration.