1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2010 Nathanael C. Fritz
This file is part of SleekXMPP.
See the file LICENSE for copying permission.
"""
def tostring(xml=None, xmlns='', stanza_ns='', stream=None, outbuffer=''):
"""
Serialize an XML object to a Unicode string.
If namespaces are provided using xmlns or stanza_ns, then elements
that use those namespaces will not include the xmlns attribute in
the output.
Arguments:
xml -- The XML object to serialize. If the value is None,
then the XML object contained in this stanza
object will be used.
xmlns -- Optional namespace of an element wrapping the XML
object.
stanza_ns -- The namespace of the stanza object that contains
the XML object.
stream -- The XML stream that generated the XML object.
outbuffer -- Optional buffer for storing serializations during
recursive calls.
"""
# Add previous results to the start of the output.
output = [outbuffer]
# Extract the element's tag name.
tag_name = xml.tag.split('}', 1)[-1]
# Extract the element's namespace if it is defined.
if '}' in xml.tag:
tag_xmlns = xml.tag.split('}', 1)[0][1:]
else:
tag_xmlns = ''
# Output the tag name and derived namespace of the element.
namespace = ''
if tag_xmlns not in ['', xmlns, stanza_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)
output.append("<%s" % tag_name)
output.append(namespace)
# Output escaped attribute values.
for attrib, value in xml.attrib.items():
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.
output.append(">")
if xml.text:
output.append(xml_escape(xml.text))
if len(xml):
for child in xml.getchildren():
output.append(tostring(child, tag_xmlns, stanza_ns, stream))
output.append("</%s>" % tag_name)
elif xml.text:
# If we only have text content.
output.append(">%s</%s>" % (xml_escape(xml.text), tag_name))
else:
# Empty element.
output.append(" />")
if xml.tail:
# If there is additional text after the element.
output.append(xml_escape(xml.tail))
return ''.join(output)
def xml_escape(text):
"""
Convert special characters in XML to escape sequences.
Arguments:
text -- The XML text to convert.
"""
text = list(text)
escapes = {'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'}
for i, c in enumerate(text):
text[i] = escapes.get(c, c)
return ''.join(text)
|