diff -r 1f1498fe50e5 Lib/test/test_xml_etree.py
--- a/Lib/test/test_xml_etree.py Wed Dec 04 23:29:51 2013 +0100
+++ b/Lib/test/test_xml_etree.py Thu Dec 05 00:30:46 2013 -0800
@@ -1612,6 +1612,24 @@
ET.register_namespace('test10777', 'http://myuri/')
ET.register_namespace('test10777', 'http://myuri/')
+ def test_issue17088(self):
+ # Unprefixed attributes are unqualified even if a default namespace is in
+ # effect.
+ e = ET.XML(''
+ '')
+ self.assertEqual(e.tag, '{space1}name1')
+ self.assertEqual(e[0].attrib, { 'attr': 'value2', '{space2}attr': 'value3' })
+
+ pi = b"\n"
+ self.assertEqual(serialize(e),
+ ''
+ '')
+ self.assertEqual(serialize(e, default_namespace="space1"),
+ ''
+ '')
+ #self.assertEqual(serialize(e, default_namespace="space2"),
+ # ''
+ # '')
# --------------------------------------------------------------------
diff -r 1f1498fe50e5 Lib/xml/etree/ElementTree.py
--- a/Lib/xml/etree/ElementTree.py Wed Dec 04 23:29:51 2013 +0100
+++ b/Lib/xml/etree/ElementTree.py Thu Dec 05 00:30:46 2013 -0800
@@ -847,7 +847,7 @@
if default_namespace:
namespaces[default_namespace] = ""
- def add_qname(qname):
+ def add_qname(qname, is_attrname):
# calculate serialized qname representation
try:
if qname[:1] == "{":
@@ -862,10 +862,24 @@
if prefix:
qnames[qname] = "%s:%s" % (prefix, tag)
else:
+ # FIXME: (if is_attrname and prefix == ''): If an
+ # attribute name is in the default namespace, we
+ # will write it out without a prefix, which is
+ # incorrect (an unprefixed attribute is always
+ # unqualified, even if a default namespace is in
+ # effect). For completely correct behavior, we
+ # would need to emit both a default namespace
+ # declaration *and* a prefix declaration for the
+ # use of attributes.
qnames[qname] = tag # default element
else:
- if default_namespace:
- # FIXME: can this be handled in XML 1.0?
+ if default_namespace and not is_attrname:
+ # A default namespace can be undeclared
+ # (see http://www.w3.org/TR/REC-xml-names/#defaulting)
+ # but only by placing an xmlns="" attribute on the
+ # element and possibly re-declaring the default
+ # namespace for child elements. Our serializers
+ # can't do that. FIXME.
raise ValueError(
"cannot use non-qualified names with "
"default_namespace option"
@@ -879,22 +893,22 @@
tag = elem.tag
if isinstance(tag, QName):
if tag.text not in qnames:
- add_qname(tag.text)
+ add_qname(tag.text, False)
elif isinstance(tag, str):
if tag not in qnames:
- add_qname(tag)
+ add_qname(tag, False)
elif tag is not None and tag is not Comment and tag is not PI:
_raise_serialization_error(tag)
for key, value in elem.items():
if isinstance(key, QName):
key = key.text
if key not in qnames:
- add_qname(key)
+ add_qname(key, True)
if isinstance(value, QName) and value.text not in qnames:
- add_qname(value.text)
+ add_qname(value.text, False)
text = elem.text
if isinstance(text, QName) and text.text not in qnames:
- add_qname(text.text)
+ add_qname(text.text, False)
return qnames, namespaces
def _serialize_xml(write, elem, qnames, namespaces,