# HG changeset patch
# Parent 32d3770c19586a67b5f60ec69e5bb5fd2d59b84d
Issue #13378: use non global namespaces for the serializer.
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1717,6 +1717,8 @@
>>> s = ET.SubElement(e, "{not-default}elem")
>>> serialize(e, default_namespace="default") # 2
''
+ >>> serialize(e, namespaces={"default": ""})
+ ''
>>> e = ET.Element("{default}elem")
>>> s = ET.SubElement(e, "{default}elem")
@@ -1724,6 +1726,9 @@
>>> serialize(e, default_namespace="default") # 3
Traceback (most recent call last):
ValueError: cannot use non-qualified names with default_namespace option
+ >>> serialize(e, namespaces={"default": ""})
+ Traceback (most recent call last):
+ ValueError: cannot use non-qualified names with default_namespace option
"""
@@ -1851,6 +1856,20 @@
>>> ET.register_namespace('test10777', 'http://myuri/')
"""
+def check_issue13378():
+ """
+ Pass specific, non-global namespaces to the serializer.
+
+ >>> elem = ET.XML('')
+ >>> serialize(elem, namespaces={'http://localhost/house': 'house'})
+ ''
+ >>> serialize(elem)
+ ''
+ >>> serialize(elem, namespaces={'http://localhost/house': 'home'})
+ ''
+
+ """
+
# --------------------------------------------------------------------
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -813,7 +813,8 @@
encoding=None,
xml_declaration=None,
default_namespace=None,
- method=None):
+ method=None,
+ namespaces=None):
# assert self._root is not None
if not method:
method = "xml"
@@ -857,7 +858,11 @@
if method == "text":
_serialize_text(write, self._root)
else:
- qnames, namespaces = _namespaces(self._root, default_namespace)
+ # if custom namespaces...
+ namespaces = dict(namespaces or {})
+ if default_namespace:
+ namespaces[default_namespace] = ""
+ qnames = _qnames(self._root, namespaces)
serialize = _serialize[method]
serialize(write, self._root, qnames, namespaces)
if file_or_filename is not file:
@@ -870,17 +875,23 @@
# --------------------------------------------------------------------
# serialization support
-def _namespaces(elem, default_namespace=None):
+def _qnames(elem, namespaces):
# identify namespaces used in this tree
# maps qnames to *encoded* prefix:local names
qnames = {None: None}
+ # any uri is mapped to ""?
+ has_default_namespace = ("" in namespaces.values())
+
+ if namespaces:
+ namespace_map = _namespace_map.copy()
+ namespace_map.update(namespaces)
+ namespaces.clear()
+ else:
+ namespace_map = _namespace_map
+
# maps uri:s to prefixes
- namespaces = {}
- if default_namespace:
- namespaces[default_namespace] = ""
-
def add_qname(qname):
# calculate serialized qname representation
try:
@@ -888,7 +899,7 @@
uri, tag = qname[1:].rsplit("}", 1)
prefix = namespaces.get(uri)
if prefix is None:
- prefix = _namespace_map.get(uri)
+ prefix = namespace_map.get(uri)
if prefix is None:
prefix = "ns%d" % len(namespaces)
if prefix != "xml":
@@ -898,7 +909,7 @@
else:
qnames[qname] = tag # default element
else:
- if default_namespace:
+ if has_default_namespace:
# FIXME: can this be handled in XML 1.0?
raise ValueError(
"cannot use non-qualified names with "
@@ -909,11 +920,7 @@
_raise_serialization_error(qname)
# populate qname and namespaces table
- try:
- iterate = elem.iter
- except AttributeError:
- iterate = elem.getiterator # cET compatibility
- for elem in iterate():
+ for elem in elem.iter():
tag = elem.tag
if isinstance(tag, QName):
if tag.text not in qnames:
@@ -933,7 +940,7 @@
text = elem.text
if isinstance(text, QName) and text.text not in qnames:
add_qname(text.text)
- return qnames, namespaces
+ return qnames
def _serialize_xml(write, elem, qnames, namespaces):
tag = elem.tag
@@ -1152,13 +1159,13 @@
# @return An (optionally) encoded string containing the XML data.
# @defreturn string
-def tostring(element, encoding=None, method=None):
+def tostring(element, encoding=None, method=None, **kw):
class dummy:
pass
data = []
file = dummy()
file.write = data.append
- ElementTree(element).write(file, encoding, method=method)
+ ElementTree(element).write(file, encoding, method=method, **kw)
if encoding in (str, "unicode"):
return "".join(data)
else:
@@ -1179,13 +1186,13 @@
# @defreturn sequence
# @since 1.3
-def tostringlist(element, encoding=None, method=None):
+def tostringlist(element, encoding=None, method=None, **kw):
class dummy:
pass
data = []
file = dummy()
file.write = data.append
- ElementTree(element).write(file, encoding, method=method)
+ ElementTree(element).write(file, encoding, method=method, **kw)
# FIXME: merge small fragments into larger parts
return data