Skip to content

Commit c250651

Browse files
Keep the empty prefix registered for other namespace
register_namespace("", uri) still makes it the default namespace, unless the default_namespace option is used for other uri. Serializing such tree no longer produces two xmlns attributes (pythongh-118416).
1 parent 1351010 commit c250651

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

Lib/test/test_xml_etree.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,24 @@ def test_tostring_default_namespace_attributes_round_trip(self):
947947
[sorted(e.attrib.items()) for e in elem.iter()]
948948
)
949949

950+
def test_tostring_default_namespace_registered_empty_prefix(self):
951+
# gh-118416: the empty prefix is registered for other namespace,
952+
# so it cannot be used for the default namespace
953+
nsmap = ET.register_namespace._namespace_map
954+
self.addCleanup(nsmap.pop, 'default', None)
955+
ET.register_namespace('', 'default')
956+
elem = ET.Element('{default}elem')
957+
self.assertEqual(
958+
ET.tostring(elem, encoding='unicode',
959+
default_namespace='otherdefault'),
960+
'<ns1:elem xmlns="otherdefault" xmlns:ns1="default" />'
961+
)
962+
# without the option the registered prefix is used
963+
self.assertEqual(
964+
ET.tostring(elem, encoding='unicode'),
965+
'<elem xmlns="default" />'
966+
)
967+
950968
def test_tostring_no_xml_declaration(self):
951969
elem = ET.XML('<body><tag/></body>')
952970
self.assertEqual(

Lib/xml/etree/ElementTree.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,14 +827,16 @@ def get_prefix(uri, isattr):
827827
if isattr:
828828
prefix = attr_prefixes.get(uri)
829829
if prefix is None:
830-
# the default namespace is of no use for an attribute name
830+
# the empty prefix is of no use for an attribute name
831831
prefix = prefixes.get(uri) or None
832832
else:
833833
prefix = prefixes.get(uri)
834834
if prefix is not None:
835835
return prefix
836836
prefix = _namespace_map.get(uri)
837-
if not prefix:
837+
if prefix is None or not prefix and (isattr or default_namespace):
838+
# the empty prefix is of no use for an attribute name,
839+
# and the default namespace is used for other uri
838840
prefix = "ns%d" % len(namespaces)
839841
if prefix != "xml":
840842
namespaces[prefix] = uri

0 commit comments

Comments
 (0)