From e9cceb26a27928bd05073dee8dca22f5c2dd7c4f Mon Sep 17 00:00:00 2001 From: Vyron Vasileiadis Date: Fri, 25 Sep 2026 22:26:17 -0400 Subject: [PATCH 1/2] gh-158208: Don't write a duplicate xmlns attribute in xml.dom.minidom Since gh-44376, _fixup_namespaces() adds xmlns="" to an element in no namespace under a default namespace. When the element declares the default namespace itself, as one built with createElement() and setAttribute("xmlns", ...) does, its own xmlns attribute was written too, so the output was not well-formed. Do not add the undeclaration if the element already has an xmlns attribute. The default namespace is still treated as undeclared for its children, so they are written as before. --- Lib/test/test_minidom.py | 22 ++++++++++++++++++++++ Lib/xml/dom/minidom.py | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index 446bbe096bd19dc..8b213f3437bda35 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -702,6 +702,28 @@ def testWriteXMLNotANamespaceDeclaration(self): '') dom.unlink() + def testWriteXMLOwnDefaultNamespaceDeclaration(self): + # An element in no namespace which declares the default namespace + # itself is written with that declaration only. + dom = Document() + svg = dom.appendChild(dom.createElement("svg")) + svg.setAttribute("xmlns", "http://www.w3.org/2000/svg") + svg.appendChild(dom.createElement("g")) + self.assertEqual(dom.documentElement.toxml(), + '') + dom.unlink() + + dom = Document() + root = dom.appendChild( + dom.createElementNS("http://xml.python.org/ns", "root")) + svg = root.appendChild(dom.createElement("svg")) + svg.setAttribute("xmlns", "http://www.w3.org/2000/svg") + svg.appendChild(dom.createElement("g")) + self.assertEqual(dom.documentElement.toxml(), + '' + '') + dom.unlink() + def testWriteXMLDoesNotModifyDocument(self): dom = Document() root = dom.appendChild( diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index 7cb652a323dcc22..652e0365efcc67e 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -449,7 +449,8 @@ def _fixup_namespaces(element, nsmap): elif nsmap.get(None) and ':' not in element.tagName: # The element is in no namespace, undeclare the default one. nsmap = _bind_namespace(nsmap, inherited, None, None) - declarations.append(("xmlns", "")) + if not element.hasAttribute("xmlns"): + declarations.append(("xmlns", "")) items = [] prefixes = None # namespace URI -> prefix, built only when needed From aae55a50732beec08c8101844392d3fa76ef8ae8 Mon Sep 17 00:00:00 2001 From: Vyron Vasileiadis Date: Tue, 3 Nov 2026 17:53:56 +0200 Subject: [PATCH 2/2] Add a NEWS entry --- .../next/Library/2026-11-03-17-53-55.gh-issue-158208.ZOQnym.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-11-03-17-53-55.gh-issue-158208.ZOQnym.rst diff --git a/Misc/NEWS.d/next/Library/2026-11-03-17-53-55.gh-issue-158208.ZOQnym.rst b/Misc/NEWS.d/next/Library/2026-11-03-17-53-55.gh-issue-158208.ZOQnym.rst new file mode 100644 index 000000000000000..424f2338e2af8ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-11-03-17-53-55.gh-issue-158208.ZOQnym.rst @@ -0,0 +1,2 @@ +Fix :mod:`xml.dom.minidom` writing a duplicate ``xmlns`` attribute for an +element in no namespace that has its own ``xmlns`` attribute.