diff --git a/sleekxmpp/basexmpp.py b/sleekxmpp/basexmpp.py index 3cf949a..a490510 100644 --- a/sleekxmpp/basexmpp.py +++ b/sleekxmpp/basexmpp.py @@ -106,6 +106,7 @@ class BaseXMPP(XMLStream): self.default_ns = default_ns self.stream_ns = 'http://etherx.jabber.org/streams' + self.namespace_map[self.stream_ns] = 'stream' self.boundjid = JID("") @@ -119,6 +120,8 @@ class BaseXMPP(XMLStream): self.sentpresence = False + self.stanza = sleekxmpp.stanza + self.register_handler( Callback('IM', MatchXPath('{%s}message/{%s}body' % (self.default_ns, diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 3937a7a..83d8699 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -1007,7 +1007,9 @@ class ElementBase(object): """ Return a string serialization of the underlying XML object. """ - return tostring(self.xml, xmlns='', stanza_ns=self.namespace) + return tostring(self.xml, xmlns='', + stanza_ns=self.namespace, + top_level=True) def __repr__(self): """ @@ -1217,4 +1219,5 @@ class StanzaBase(ElementBase): """Serialize the stanza's XML to a string.""" return tostring(self.xml, xmlns='', stanza_ns=self.namespace, - stream=self.stream) + stream=self.stream, + top_level = True) diff --git a/sleekxmpp/xmlstream/tostring/tostring.py b/sleekxmpp/xmlstream/tostring/tostring.py index 38b08d8..a6bb6eb 100644 --- a/sleekxmpp/xmlstream/tostring/tostring.py +++ b/sleekxmpp/xmlstream/tostring/tostring.py @@ -7,7 +7,8 @@ """ -def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): +def tostring(xml=None, xmlns='', stanza_ns='', stream=None, + outbuffer='', top_level=False): """ Serialize an XML object to a Unicode string. @@ -26,6 +27,8 @@ def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): stream -- The XML stream that generated the XML object. outbuffer -- Optional buffer for storing serializations during recursive calls. + top_level -- Indicates that the element is the outermost + element. """ # Add previous results to the start of the output. output = [outbuffer] @@ -39,14 +42,21 @@ def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): else: tag_xmlns = '' + default_ns = '' + stream_ns = '' + if stream: + default_ns = stream.default_ns + stream_ns = stream.stream_ns + # Output the tag name and derived namespace of the element. namespace = '' - if tag_xmlns not in ['', xmlns, stanza_ns]: + if top_level and tag_xmlns not in ['', default_ns, stream_ns] or \ + tag_xmlns not in ['', xmlns, stanza_ns, stream_ns]: namespace = ' xmlns="%s"' % tag_xmlns - if stream and tag_xmlns in stream.namespace_map: - mapped_namespace = stream.namespace_map[tag_xmlns] - if mapped_namespace: - tag_name = "%s:%s" % (mapped_namespace, tag_name) + if stream and tag_xmlns in stream.namespace_map: + mapped_namespace = stream.namespace_map[tag_xmlns] + if mapped_namespace: + tag_name = "%s:%s" % (mapped_namespace, tag_name) output.append("<%s" % tag_name) output.append(namespace) diff --git a/sleekxmpp/xmlstream/tostring/tostring26.py b/sleekxmpp/xmlstream/tostring/tostring26.py index 1150178..3d1ca3d 100644 --- a/sleekxmpp/xmlstream/tostring/tostring26.py +++ b/sleekxmpp/xmlstream/tostring/tostring26.py @@ -10,7 +10,8 @@ from __future__ import unicode_literals import types -def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): +def tostring(xml=None, xmlns='', stanza_ns='', stream=None, + outbuffer='', top_level=False): """ Serialize an XML object to a Unicode string. @@ -29,6 +30,8 @@ def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): stream -- The XML stream that generated the XML object. outbuffer -- Optional buffer for storing serializations during recursive calls. + top_level -- Indicates that the element is the outermost + element. """ # Add previous results to the start of the output. output = [outbuffer] @@ -42,14 +45,21 @@ def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): else: tag_xmlns = u'' + default_ns = '' + stream_ns = '' + if stream: + default_ns = stream.default_ns + stream_ns = stream.stream_ns + # Output the tag name and derived namespace of the element. namespace = u'' - if tag_xmlns not in ['', xmlns, stanza_ns]: + if top_level and tag_xmlns not in ['', default_ns, stream_ns] or \ + tag_xmlns not in ['', xmlns, stanza_ns, stream_ns]: namespace = u' xmlns="%s"' % tag_xmlns - if stream and tag_xmlns in stream.namespace_map: - mapped_namespace = stream.namespace_map[tag_xmlns] - if mapped_namespace: - tag_name = u"%s:%s" % (mapped_namespace, tag_name) + if stream and tag_xmlns in stream.namespace_map: + mapped_namespace = stream.namespace_map[tag_xmlns] + if mapped_namespace: + tag_name = u"%s:%s" % (mapped_namespace, tag_name) output.append(u"<%s" % tag_name) output.append(namespace) diff --git a/tests/test_tostring.py b/tests/test_tostring.py index 638e613..e456d28 100644 --- a/tests/test_tostring.py +++ b/tests/test_tostring.py @@ -102,11 +102,13 @@ class TestToString(SleekTest): """ Test that stanza objects are serialized properly. """ + self.stream_start() + utf8_message = '\xe0\xb2\xa0_\xe0\xb2\xa0' if not hasattr(utf8_message, 'decode'): # Python 3 utf8_message = bytes(utf8_message, encoding='utf-8') - msg = Message() + msg = self.Message() msg['body'] = utf8_message.decode('utf-8') expected = '\xe0\xb2\xa0_\xe0\xb2\xa0' result = msg.__str__()