summaryrefslogtreecommitdiff
path: root/sleekxmpp/xmlstream
diff options
context:
space:
mode:
Diffstat (limited to 'sleekxmpp/xmlstream')
-rw-r--r--sleekxmpp/xmlstream/stanzabase.py52
-rw-r--r--sleekxmpp/xmlstream/tostring.py35
2 files changed, 55 insertions, 32 deletions
diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py
index 120373db..97107098 100644
--- a/sleekxmpp/xmlstream/stanzabase.py
+++ b/sleekxmpp/xmlstream/stanzabase.py
@@ -3,7 +3,7 @@
sleekxmpp.xmlstream.stanzabase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- This module implements a wrapper layer for XML objects
+ module implements a wrapper layer for XML objects
that allows them to be treated like dictionaries.
Part of SleekXMPP: The Sleek XMPP Library
@@ -141,7 +141,7 @@ def multifactory(stanza, plugin_attrib):
parent.loaded_plugins.remove(plugin_attrib)
try:
parent.xml.remove(self.xml)
- except:
+ except ValueError:
pass
else:
for stanza in list(res):
@@ -596,31 +596,39 @@ class ElementBase(object):
iterable_interfaces = [p.plugin_attrib for \
p in self.plugin_iterables]
+ if 'lang' in values:
+ self['lang'] = values['lang']
+
+ if 'substanzas' in values:
+ # Remove existing substanzas
+ for stanza in self.iterables:
+ try:
+ self.xml.remove(stanza.xml)
+ except ValueError:
+ pass
+ self.iterables = []
+
+ # Add new substanzas
+ for subdict in values['substanzas']:
+ if '__childtag__' in subdict:
+ for subclass in self.plugin_iterables:
+ child_tag = "{%s}%s" % (subclass.namespace,
+ subclass.name)
+ if subdict['__childtag__'] == child_tag:
+ sub = subclass(parent=self)
+ sub.values = subdict
+ self.iterables.append(sub)
+
for interface, value in values.items():
full_interface = interface
interface_lang = ('%s|' % interface).split('|')
interface = interface_lang[0]
lang = interface_lang[1] or self.get_lang()
- if interface == 'substanzas':
- # Remove existing substanzas
- for stanza in self.iterables:
- self.xml.remove(stanza.xml)
- self.iterables = []
-
- # Add new substanzas
- for subdict in value:
- if '__childtag__' in subdict:
- for subclass in self.plugin_iterables:
- child_tag = "{%s}%s" % (subclass.namespace,
- subclass.name)
- if subdict['__childtag__'] == child_tag:
- sub = subclass(parent=self)
- sub.values = subdict
- self.iterables.append(sub)
- break
- elif interface == 'lang':
- self[interface] = value
+ if interface == 'lang':
+ continue
+ elif interface == 'substanzas':
+ continue
elif interface in self.interfaces:
self[full_interface] = value
elif interface in self.plugin_attrib_map:
@@ -866,7 +874,7 @@ class ElementBase(object):
self.loaded_plugins.remove(attrib)
try:
self.xml.remove(plugin.xml)
- except:
+ except ValueError:
pass
return self
diff --git a/sleekxmpp/xmlstream/tostring.py b/sleekxmpp/xmlstream/tostring.py
index 08d7ad02..c49abd3e 100644
--- a/sleekxmpp/xmlstream/tostring.py
+++ b/sleekxmpp/xmlstream/tostring.py
@@ -24,8 +24,8 @@ if sys.version_info < (3, 0):
XML_NS = 'http://www.w3.org/XML/1998/namespace'
-def tostring(xml=None, xmlns='', stream=None,
- outbuffer='', top_level=False, open_only=False):
+def tostring(xml=None, xmlns='', stream=None, outbuffer='',
+ top_level=False, open_only=False, namespaces=None):
"""Serialize an XML object to a Unicode string.
If an outer xmlns is provided using ``xmlns``, then the current element's
@@ -41,7 +41,8 @@ def tostring(xml=None, xmlns='', stream=None,
during recursive calls.
:param bool top_level: Indicates that the element is the outermost
element.
-
+ :param set namespaces: Track which namespaces are in active use so
+ that new ones can be declared when needed.
:type xml: :py:class:`~xml.etree.ElementTree.Element`
:type stream: :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream`
@@ -63,6 +64,7 @@ def tostring(xml=None, xmlns='', stream=None,
default_ns = ''
stream_ns = ''
use_cdata = False
+
if stream:
default_ns = stream.default_ns
stream_ns = stream.stream_ns
@@ -82,6 +84,7 @@ def tostring(xml=None, xmlns='', stream=None,
output.append(namespace)
# Output escaped attribute values.
+ new_namespaces = set()
for attrib, value in xml.attrib.items():
value = escape(value, use_cdata)
if '}' not in attrib:
@@ -89,14 +92,20 @@ def tostring(xml=None, xmlns='', stream=None,
else:
attrib_ns = attrib.split('}')[0][1:]
attrib = attrib.split('}')[1]
- if stream and attrib_ns in stream.namespace_map:
+ if attrib_ns == XML_NS:
+ output.append(' xml:%s="%s"' % (attrib, value))
+ elif stream and attrib_ns in stream.namespace_map:
mapped_ns = stream.namespace_map[attrib_ns]
if mapped_ns:
- output.append(' %s:%s="%s"' % (mapped_ns,
- attrib,
- value))
- elif attrib_ns == XML_NS:
- output.append(' xml:%s="%s"' % (attrib, value))
+ if namespaces is None:
+ namespaces = set()
+ if attrib_ns not in namespaces:
+ namespaces.add(attrib_ns)
+ new_namespaces.add(attrib_ns)
+ output.append(' xmlns:%s="%s"' % (
+ mapped_ns, attrib_ns))
+ output.append(' %s:%s="%s"' % (
+ mapped_ns, attrib, value))
if open_only:
# Only output the opening tag, regardless of content.
@@ -110,7 +119,8 @@ def tostring(xml=None, xmlns='', stream=None,
output.append(escape(xml.text, use_cdata))
if len(xml):
for child in xml:
- output.append(tostring(child, tag_xmlns, stream))
+ output.append(tostring(child, tag_xmlns, stream,
+ namespaces=namespaces))
output.append("</%s>" % tag_name)
elif xml.text:
# If we only have text content.
@@ -121,6 +131,11 @@ def tostring(xml=None, xmlns='', stream=None,
if xml.tail:
# If there is additional text after the element.
output.append(escape(xml.tail, use_cdata))
+ for ns in new_namespaces:
+ # Remove namespaces introduced in this context. This is necessary
+ # because the namespaces object continues to be shared with other
+ # contexts.
+ namespaces.remove(ns)
return ''.join(output)