From f474d378efdc754b57dedd60a9905ac5e75ee55d Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Tue, 7 Dec 2010 23:07:40 -0500 Subject: [PATCH] Add support for using xml:lang values. Support is only for adding literal XML content to stanzas. Full support for things like multiple message bodies with different xml:lang values is still in the works. --- sleekxmpp/xmlstream/stanzabase.py | 6 +++++- sleekxmpp/xmlstream/tostring/tostring.py | 13 +++++++++++-- sleekxmpp/xmlstream/tostring/tostring26.py | 15 ++++++++++++--- sleekxmpp/xmlstream/xmlstream.py | 2 +- tests/test_tostring.py | 13 ++++++++++++- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index aabd386..5551d43 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -116,6 +116,9 @@ class ElementBase(object): associated plugin stanza classes. plugin_tag_map -- A mapping of plugin stanza tag names with the associated plugin stanza classes. + xml_ns -- The XML namespace, + http://www.w3.org/XML/1998/namespace, + for use with xml:lang values. Instance Attributes: xml -- The stanza's XML contents. @@ -144,7 +147,7 @@ class ElementBase(object): _get_attr -- Return an attribute's value from the main stanza element. _get_sub_text -- Return the text contents of a subelement. - _set_sub_ext -- Set the text contents of a subelement. + _set_sub_text -- Set the text contents of a subelement. _del_sub -- Remove a subelement. match -- Compare the stanza against an XPath expression. find -- Return subelement matching an XPath expression. @@ -170,6 +173,7 @@ class ElementBase(object): plugin_attrib_map = {} plugin_tag_map = {} subitem = None + xml_ns = 'http://www.w3.org/XML/1998/namespace' def __init__(self, xml=None, parent=None): """ diff --git a/sleekxmpp/xmlstream/tostring/tostring.py b/sleekxmpp/xmlstream/tostring/tostring.py index d8f5c5b..38b08d8 100644 --- a/sleekxmpp/xmlstream/tostring/tostring.py +++ b/sleekxmpp/xmlstream/tostring/tostring.py @@ -52,9 +52,18 @@ def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): # Output escaped attribute values. for attrib, value in xml.attrib.items(): - if '{' not in attrib: - value = xml_escape(value) + value = xml_escape(value) + if '}' not in attrib: output.append(' %s="%s"' % (attrib, value)) + else: + attrib_ns = attrib.split('}')[0][1:] + attrib = attrib.split('}')[1] + if 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)) if len(xml) or xml.text: # If there are additional child elements to serialize. diff --git a/sleekxmpp/xmlstream/tostring/tostring26.py b/sleekxmpp/xmlstream/tostring/tostring26.py index 0ee432c..1150178 100644 --- a/sleekxmpp/xmlstream/tostring/tostring26.py +++ b/sleekxmpp/xmlstream/tostring/tostring26.py @@ -55,9 +55,18 @@ def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''): # Output escaped attribute values. for attrib, value in xml.attrib.items(): - if '{' not in attrib: - value = xml_escape(value) - output.append(u' %s="%s"' % (attrib, value)) + value = xml_escape(value) + if '}' not in attrib: + output.append(' %s="%s"' % (attrib, value)) + else: + attrib_ns = attrib.split('}')[0][1:] + attrib = attrib.split('}')[1] + if 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)) if len(xml) or xml.text: # If there are additional child elements to serialize. diff --git a/sleekxmpp/xmlstream/xmlstream.py b/sleekxmpp/xmlstream/xmlstream.py index 9ae31a2..fc7aff3 100644 --- a/sleekxmpp/xmlstream/xmlstream.py +++ b/sleekxmpp/xmlstream/xmlstream.py @@ -192,7 +192,7 @@ class XMLStream(object): self.send_queue = queue.Queue() self.scheduler = Scheduler(self.event_queue, self.stop) - self.namespace_map = {} + self.namespace_map = {StanzaBase.xml_ns: 'xml'} self.__thread = {} self.__root_stanza = [] diff --git a/tests/test_tostring.py b/tests/test_tostring.py index 3e9df52..5235d53 100644 --- a/tests/test_tostring.py +++ b/tests/test_tostring.py @@ -1,6 +1,6 @@ from sleekxmpp.test import * from sleekxmpp.stanza import Message -from sleekxmpp.xmlstream.stanzabase import ET +from sleekxmpp.xmlstream.stanzabase import ET, ElementBase from sleekxmpp.xmlstream.tostring import tostring, xml_escape @@ -110,5 +110,16 @@ class TestToString(SleekTest): self.failUnless(result == expected, "Stanza Unicode handling is incorrect: %s" % result) + def testXMLLang(self): + """Test that serializing xml:lang works.""" + + msg = self.Message() + msg._set_attr('{%s}lang' % msg.xml_ns, "no") + + expected = '' + result = msg.__str__() + self.failUnless(expected == result, + "Serialization with xml:lang failed: %s" % result) + suite = unittest.TestLoader().loadTestsFromTestCase(TestToString)