blob: 85c1cfef00d86e86be295024b00d8b1edf490e11 [file] [log] [blame]
Antoine Pitroud72402e2010-10-27 18:52:48 +00001# regression test for SAX 2.0
Lars Gustäbel96753b32000-09-24 12:24:24 +00002# $Id$
3
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004from xml.sax import make_parser, ContentHandler, \
5 SAXException, SAXReaderNotAvailable, SAXParseException
R David Murraya846f5a2013-03-18 00:18:12 -04006import unittest
Martin v. Löwis962c9e72000-10-06 17:41:52 +00007try:
8 make_parser()
Martin v. Löwis80670bc2000-10-06 21:13:23 +00009except SAXReaderNotAvailable:
Martin v. Löwis962c9e72000-10-06 17:41:52 +000010 # don't try to test this module if we cannot create a parser
R David Murraya846f5a2013-03-18 00:18:12 -040011 raise unittest.SkipTest("no XML parsers available")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000012from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +030013 XMLFilterBase, prepare_input_source
Thomas Wouters0e3f5912006-08-11 14:57:12 +000014from xml.sax.expatreader import create_parser
Antoine Pitrou6b03ee62010-10-27 18:33:30 +000015from xml.sax.handler import feature_namespaces
Thomas Wouters0e3f5912006-08-11 14:57:12 +000016from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
Serhiy Storchaka88efc522013-02-10 14:29:52 +020017from io import BytesIO, StringIO
Georg Brandlc502df42013-05-12 11:41:12 +020018import codecs
Serhiy Storchaka13e41c52015-04-02 23:05:57 +030019import gc
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +020020import os.path
Serhiy Storchakad5202392013-02-02 10:31:17 +020021import shutil
22from test import support
Serhiy Storchaka13e41c52015-04-02 23:05:57 +030023from test.support import findfile, run_unittest, TESTFN
Florent Xiclunaf15351d2010-03-13 23:24:31 +000024
25TEST_XMLFILE = findfile("test.xml", subdir="xmltestdata")
26TEST_XMLFILE_OUT = findfile("test.xml.out", subdir="xmltestdata")
Victor Stinner6c6f8512010-08-07 10:09:35 +000027try:
Marc-André Lemburg8f36af72011-02-25 15:42:01 +000028 TEST_XMLFILE.encode("utf-8")
29 TEST_XMLFILE_OUT.encode("utf-8")
Victor Stinner6c6f8512010-08-07 10:09:35 +000030except UnicodeEncodeError:
31 raise unittest.SkipTest("filename is not encodable to utf8")
Lars Gustäbel96753b32000-09-24 12:24:24 +000032
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +020033supports_nonascii_filenames = True
34if not os.path.supports_unicode_filenames:
35 try:
36 support.TESTFN_UNICODE.encode(support.TESTFN_ENCODING)
37 except (UnicodeError, TypeError):
38 # Either the file system encoding is None, or the file name
39 # cannot be encoded in the file system encoding.
40 supports_nonascii_filenames = False
41requires_nonascii_filenames = unittest.skipUnless(
42 supports_nonascii_filenames,
43 'Requires non-ascii filenames support')
44
Guido van Rossumd8faa362007-04-27 19:54:29 +000045ns_uri = "http://www.python.org/xml-ns/saxtest/"
Lars Gustäbel96753b32000-09-24 12:24:24 +000046
Guido van Rossumd8faa362007-04-27 19:54:29 +000047class XmlTestBase(unittest.TestCase):
48 def verify_empty_attrs(self, attrs):
49 self.assertRaises(KeyError, attrs.getValue, "attr")
50 self.assertRaises(KeyError, attrs.getValueByQName, "attr")
51 self.assertRaises(KeyError, attrs.getNameByQName, "attr")
52 self.assertRaises(KeyError, attrs.getQNameByName, "attr")
53 self.assertRaises(KeyError, attrs.__getitem__, "attr")
Ezio Melottib3aedd42010-11-20 19:04:17 +000054 self.assertEqual(attrs.getLength(), 0)
55 self.assertEqual(attrs.getNames(), [])
56 self.assertEqual(attrs.getQNames(), [])
57 self.assertEqual(len(attrs), 0)
Ezio Melottib58e0bd2010-01-23 15:40:09 +000058 self.assertNotIn("attr", attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +000059 self.assertEqual(list(attrs.keys()), [])
60 self.assertEqual(attrs.get("attrs"), None)
61 self.assertEqual(attrs.get("attrs", 25), 25)
62 self.assertEqual(list(attrs.items()), [])
63 self.assertEqual(list(attrs.values()), [])
Lars Gustäbel96753b32000-09-24 12:24:24 +000064
Guido van Rossumd8faa362007-04-27 19:54:29 +000065 def verify_empty_nsattrs(self, attrs):
66 self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
67 self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
68 self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
69 self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
70 self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
Ezio Melottib3aedd42010-11-20 19:04:17 +000071 self.assertEqual(attrs.getLength(), 0)
72 self.assertEqual(attrs.getNames(), [])
73 self.assertEqual(attrs.getQNames(), [])
74 self.assertEqual(len(attrs), 0)
Ezio Melottib58e0bd2010-01-23 15:40:09 +000075 self.assertNotIn((ns_uri, "attr"), attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +000076 self.assertEqual(list(attrs.keys()), [])
77 self.assertEqual(attrs.get((ns_uri, "attr")), None)
78 self.assertEqual(attrs.get((ns_uri, "attr"), 25), 25)
79 self.assertEqual(list(attrs.items()), [])
80 self.assertEqual(list(attrs.values()), [])
Lars Gustäbel96753b32000-09-24 12:24:24 +000081
Guido van Rossumd8faa362007-04-27 19:54:29 +000082 def verify_attrs_wattr(self, attrs):
Ezio Melottib3aedd42010-11-20 19:04:17 +000083 self.assertEqual(attrs.getLength(), 1)
84 self.assertEqual(attrs.getNames(), ["attr"])
85 self.assertEqual(attrs.getQNames(), ["attr"])
86 self.assertEqual(len(attrs), 1)
Benjamin Peterson577473f2010-01-19 00:09:57 +000087 self.assertIn("attr", attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +000088 self.assertEqual(list(attrs.keys()), ["attr"])
89 self.assertEqual(attrs.get("attr"), "val")
90 self.assertEqual(attrs.get("attr", 25), "val")
91 self.assertEqual(list(attrs.items()), [("attr", "val")])
92 self.assertEqual(list(attrs.values()), ["val"])
93 self.assertEqual(attrs.getValue("attr"), "val")
94 self.assertEqual(attrs.getValueByQName("attr"), "val")
95 self.assertEqual(attrs.getNameByQName("attr"), "attr")
96 self.assertEqual(attrs["attr"], "val")
97 self.assertEqual(attrs.getQNameByName("attr"), "attr")
Lars Gustäbel96753b32000-09-24 12:24:24 +000098
Serhiy Storchaka13e41c52015-04-02 23:05:57 +030099
100def xml_str(doc, encoding=None):
101 if encoding is None:
102 return doc
103 return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, doc)
104
105def xml_bytes(doc, encoding, decl_encoding=...):
106 if decl_encoding is ...:
107 decl_encoding = encoding
108 return xml_str(doc, decl_encoding).encode(encoding, 'xmlcharrefreplace')
109
110def make_xml_file(doc, encoding, decl_encoding=...):
111 if decl_encoding is ...:
112 decl_encoding = encoding
113 with open(TESTFN, 'w', encoding=encoding, errors='xmlcharrefreplace') as f:
114 f.write(xml_str(doc, decl_encoding))
115
116
117class ParseTest(unittest.TestCase):
118 data = '<money value="$\xa3\u20ac\U0001017b">$\xa3\u20ac\U0001017b</money>'
119
120 def tearDown(self):
121 support.unlink(TESTFN)
122
123 def check_parse(self, f):
124 from xml.sax import parse
125 result = StringIO()
126 parse(f, XMLGenerator(result, 'utf-8'))
127 self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8'))
128
129 def test_parse_text(self):
130 encodings = ('us-ascii', 'iso-8859-1', 'utf-8',
131 'utf-16', 'utf-16le', 'utf-16be')
132 for encoding in encodings:
133 self.check_parse(StringIO(xml_str(self.data, encoding)))
134 make_xml_file(self.data, encoding)
135 with open(TESTFN, 'r', encoding=encoding) as f:
136 self.check_parse(f)
137 self.check_parse(StringIO(self.data))
138 make_xml_file(self.data, encoding, None)
139 with open(TESTFN, 'r', encoding=encoding) as f:
140 self.check_parse(f)
141
142 def test_parse_bytes(self):
143 # UTF-8 is default encoding, US-ASCII is compatible with UTF-8,
144 # UTF-16 is autodetected
145 encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be')
146 for encoding in encodings:
147 self.check_parse(BytesIO(xml_bytes(self.data, encoding)))
148 make_xml_file(self.data, encoding)
149 self.check_parse(TESTFN)
150 with open(TESTFN, 'rb') as f:
151 self.check_parse(f)
152 self.check_parse(BytesIO(xml_bytes(self.data, encoding, None)))
153 make_xml_file(self.data, encoding, None)
154 self.check_parse(TESTFN)
155 with open(TESTFN, 'rb') as f:
156 self.check_parse(f)
157 # accept UTF-8 with BOM
158 self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', 'utf-8')))
159 make_xml_file(self.data, 'utf-8-sig', 'utf-8')
160 self.check_parse(TESTFN)
161 with open(TESTFN, 'rb') as f:
162 self.check_parse(f)
163 self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', None)))
164 make_xml_file(self.data, 'utf-8-sig', None)
165 self.check_parse(TESTFN)
166 with open(TESTFN, 'rb') as f:
167 self.check_parse(f)
168 # accept data with declared encoding
169 self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1')))
170 make_xml_file(self.data, 'iso-8859-1')
171 self.check_parse(TESTFN)
172 with open(TESTFN, 'rb') as f:
173 self.check_parse(f)
174 # fail on non-UTF-8 incompatible data without declared encoding
175 with self.assertRaises(SAXException):
176 self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None)))
177 make_xml_file(self.data, 'iso-8859-1', None)
178 with support.check_warnings(('unclosed file', ResourceWarning)):
179 # XXX Failed parser leaks an opened file.
180 with self.assertRaises(SAXException):
181 self.check_parse(TESTFN)
182 # Collect leaked file.
183 gc.collect()
184 with open(TESTFN, 'rb') as f:
185 with self.assertRaises(SAXException):
186 self.check_parse(f)
187
188 def test_parse_InputSource(self):
189 # accept data without declared but with explicitly specified encoding
190 make_xml_file(self.data, 'iso-8859-1', None)
191 with open(TESTFN, 'rb') as f:
192 input = InputSource()
193 input.setByteStream(f)
194 input.setEncoding('iso-8859-1')
195 self.check_parse(input)
196
197 def check_parseString(self, s):
198 from xml.sax import parseString
199 result = StringIO()
200 parseString(s, XMLGenerator(result, 'utf-8'))
201 self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8'))
202
Serhiy Storchaka778db282015-04-04 10:12:26 +0300203 def test_parseString_text(self):
204 encodings = ('us-ascii', 'iso-8859-1', 'utf-8',
205 'utf-16', 'utf-16le', 'utf-16be')
206 for encoding in encodings:
207 self.check_parseString(xml_str(self.data, encoding))
208 self.check_parseString(self.data)
209
Serhiy Storchaka13e41c52015-04-02 23:05:57 +0300210 def test_parseString_bytes(self):
211 # UTF-8 is default encoding, US-ASCII is compatible with UTF-8,
212 # UTF-16 is autodetected
213 encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be')
214 for encoding in encodings:
215 self.check_parseString(xml_bytes(self.data, encoding))
216 self.check_parseString(xml_bytes(self.data, encoding, None))
217 # accept UTF-8 with BOM
218 self.check_parseString(xml_bytes(self.data, 'utf-8-sig', 'utf-8'))
219 self.check_parseString(xml_bytes(self.data, 'utf-8-sig', None))
220 # accept data with declared encoding
221 self.check_parseString(xml_bytes(self.data, 'iso-8859-1'))
222 # fail on non-UTF-8 incompatible data without declared encoding
223 with self.assertRaises(SAXException):
224 self.check_parseString(xml_bytes(self.data, 'iso-8859-1', None))
225
Guido van Rossumd8faa362007-04-27 19:54:29 +0000226class MakeParserTest(unittest.TestCase):
227 def test_make_parser2(self):
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000228 # Creating parsers several times in a row should succeed.
229 # Testing this because there have been failures of this kind
230 # before.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000231 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000232 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000233 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000234 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000235 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000236 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000237 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000238 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000239 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000240 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000241 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000242 p = make_parser()
Tim Petersd2bf3b72001-01-18 02:22:22 +0000243
244
Lars Gustäbel96753b32000-09-24 12:24:24 +0000245# ===========================================================================
246#
247# saxutils tests
248#
249# ===========================================================================
250
Guido van Rossumd8faa362007-04-27 19:54:29 +0000251class SaxutilsTest(unittest.TestCase):
252 # ===== escape
253 def test_escape_basic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000254 self.assertEqual(escape("Donald Duck & Co"), "Donald Duck &amp; Co")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000255
Guido van Rossumd8faa362007-04-27 19:54:29 +0000256 def test_escape_all(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000257 self.assertEqual(escape("<Donald Duck & Co>"),
258 "&lt;Donald Duck &amp; Co&gt;")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000259
Guido van Rossumd8faa362007-04-27 19:54:29 +0000260 def test_escape_extra(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000261 self.assertEqual(escape("Hei på deg", {"å" : "&aring;"}),
262 "Hei p&aring; deg")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000263
Guido van Rossumd8faa362007-04-27 19:54:29 +0000264 # ===== unescape
265 def test_unescape_basic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000266 self.assertEqual(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000267
Guido van Rossumd8faa362007-04-27 19:54:29 +0000268 def test_unescape_all(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000269 self.assertEqual(unescape("&lt;Donald Duck &amp; Co&gt;"),
270 "<Donald Duck & Co>")
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000271
Guido van Rossumd8faa362007-04-27 19:54:29 +0000272 def test_unescape_extra(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000273 self.assertEqual(unescape("Hei på deg", {"å" : "&aring;"}),
274 "Hei p&aring; deg")
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000275
Guido van Rossumd8faa362007-04-27 19:54:29 +0000276 def test_unescape_amp_extra(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000277 self.assertEqual(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000278
Guido van Rossumd8faa362007-04-27 19:54:29 +0000279 # ===== quoteattr
280 def test_quoteattr_basic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000281 self.assertEqual(quoteattr("Donald Duck & Co"),
282 '"Donald Duck &amp; Co"')
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000283
Guido van Rossumd8faa362007-04-27 19:54:29 +0000284 def test_single_quoteattr(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000285 self.assertEqual(quoteattr('Includes "double" quotes'),
286 '\'Includes "double" quotes\'')
Fred Drake32f3add2002-10-28 17:58:48 +0000287
Guido van Rossumd8faa362007-04-27 19:54:29 +0000288 def test_double_quoteattr(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000289 self.assertEqual(quoteattr("Includes 'single' quotes"),
290 "\"Includes 'single' quotes\"")
Fred Drakeacd32d32001-07-19 16:10:15 +0000291
Guido van Rossumd8faa362007-04-27 19:54:29 +0000292 def test_single_double_quoteattr(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000293 self.assertEqual(quoteattr("Includes 'single' and \"double\" quotes"),
294 "\"Includes 'single' and &quot;double&quot; quotes\"")
Fred Drakeacd32d32001-07-19 16:10:15 +0000295
Guido van Rossumd8faa362007-04-27 19:54:29 +0000296 # ===== make_parser
297 def test_make_parser(self):
Martin v. Löwis962c9e72000-10-06 17:41:52 +0000298 # Creating a parser should succeed - it should fall back
299 # to the expatreader
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000300 p = make_parser(['xml.parsers.no_such_parser'])
Martin v. Löwis962c9e72000-10-06 17:41:52 +0000301
302
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300303class PrepareInputSourceTest(unittest.TestCase):
304
305 def setUp(self):
306 self.file = support.TESTFN
307 with open(self.file, "w") as tmp:
308 tmp.write("This was read from a file.")
309
310 def tearDown(self):
311 support.unlink(self.file)
312
313 def make_byte_stream(self):
314 return BytesIO(b"This is a byte stream.")
315
Serhiy Storchaka61de0872015-04-02 21:00:13 +0300316 def make_character_stream(self):
317 return StringIO("This is a character stream.")
318
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300319 def checkContent(self, stream, content):
320 self.assertIsNotNone(stream)
321 self.assertEqual(stream.read(), content)
322 stream.close()
323
324
Serhiy Storchaka61de0872015-04-02 21:00:13 +0300325 def test_character_stream(self):
326 # If the source is an InputSource with a character stream, use it.
327 src = InputSource(self.file)
328 src.setCharacterStream(self.make_character_stream())
329 prep = prepare_input_source(src)
330 self.assertIsNone(prep.getByteStream())
331 self.checkContent(prep.getCharacterStream(),
332 "This is a character stream.")
333
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300334 def test_byte_stream(self):
335 # If the source is an InputSource that does not have a character
336 # stream but does have a byte stream, use the byte stream.
337 src = InputSource(self.file)
338 src.setByteStream(self.make_byte_stream())
339 prep = prepare_input_source(src)
340 self.assertIsNone(prep.getCharacterStream())
341 self.checkContent(prep.getByteStream(),
342 b"This is a byte stream.")
343
344 def test_system_id(self):
345 # If the source is an InputSource that has neither a character
346 # stream nor a byte stream, open the system ID.
347 src = InputSource(self.file)
348 prep = prepare_input_source(src)
349 self.assertIsNone(prep.getCharacterStream())
350 self.checkContent(prep.getByteStream(),
351 b"This was read from a file.")
352
353 def test_string(self):
354 # If the source is a string, use it as a system ID and open it.
355 prep = prepare_input_source(self.file)
356 self.assertIsNone(prep.getCharacterStream())
357 self.checkContent(prep.getByteStream(),
358 b"This was read from a file.")
359
360 def test_binary_file(self):
361 # If the source is a binary file-like object, use it as a byte
362 # stream.
363 prep = prepare_input_source(self.make_byte_stream())
364 self.assertIsNone(prep.getCharacterStream())
365 self.checkContent(prep.getByteStream(),
366 b"This is a byte stream.")
367
Serhiy Storchaka61de0872015-04-02 21:00:13 +0300368 def test_text_file(self):
369 # If the source is a text file-like object, use it as a character
370 # stream.
371 prep = prepare_input_source(self.make_character_stream())
372 self.assertIsNone(prep.getByteStream())
373 self.checkContent(prep.getCharacterStream(),
374 "This is a character stream.")
375
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300376
Lars Gustäbel96753b32000-09-24 12:24:24 +0000377# ===== XMLGenerator
378
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200379class XmlgenTest:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000380 def test_xmlgen_basic(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200381 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000382 gen = XMLGenerator(result)
383 gen.startDocument()
384 gen.startElement("doc", {})
385 gen.endElement("doc")
386 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000387
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200388 self.assertEqual(result.getvalue(), self.xml("<doc></doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000389
R. David Murraya90032a2010-10-17 22:46:45 +0000390 def test_xmlgen_basic_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200391 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000392 gen = XMLGenerator(result, short_empty_elements=True)
393 gen.startDocument()
394 gen.startElement("doc", {})
395 gen.endElement("doc")
396 gen.endDocument()
397
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200398 self.assertEqual(result.getvalue(), self.xml("<doc/>"))
R. David Murraya90032a2010-10-17 22:46:45 +0000399
Guido van Rossumd8faa362007-04-27 19:54:29 +0000400 def test_xmlgen_content(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200401 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000402 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000403
Guido van Rossumd8faa362007-04-27 19:54:29 +0000404 gen.startDocument()
405 gen.startElement("doc", {})
406 gen.characters("huhei")
407 gen.endElement("doc")
408 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000409
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200410 self.assertEqual(result.getvalue(), self.xml("<doc>huhei</doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000411
R. David Murraya90032a2010-10-17 22:46:45 +0000412 def test_xmlgen_content_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200413 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000414 gen = XMLGenerator(result, short_empty_elements=True)
415
416 gen.startDocument()
417 gen.startElement("doc", {})
418 gen.characters("huhei")
419 gen.endElement("doc")
420 gen.endDocument()
421
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200422 self.assertEqual(result.getvalue(), self.xml("<doc>huhei</doc>"))
R. David Murraya90032a2010-10-17 22:46:45 +0000423
Guido van Rossumd8faa362007-04-27 19:54:29 +0000424 def test_xmlgen_pi(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200425 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000426 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000427
Guido van Rossumd8faa362007-04-27 19:54:29 +0000428 gen.startDocument()
429 gen.processingInstruction("test", "data")
430 gen.startElement("doc", {})
431 gen.endElement("doc")
432 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000433
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200434 self.assertEqual(result.getvalue(),
435 self.xml("<?test data?><doc></doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000436
Guido van Rossumd8faa362007-04-27 19:54:29 +0000437 def test_xmlgen_content_escape(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200438 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000439 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000440
Guido van Rossumd8faa362007-04-27 19:54:29 +0000441 gen.startDocument()
442 gen.startElement("doc", {})
443 gen.characters("<huhei&")
444 gen.endElement("doc")
445 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000446
Ezio Melottib3aedd42010-11-20 19:04:17 +0000447 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200448 self.xml("<doc>&lt;huhei&amp;</doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000449
Guido van Rossumd8faa362007-04-27 19:54:29 +0000450 def test_xmlgen_attr_escape(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200451 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000452 gen = XMLGenerator(result)
Fred Drakec9fadf92001-08-07 19:17:06 +0000453
Guido van Rossumd8faa362007-04-27 19:54:29 +0000454 gen.startDocument()
455 gen.startElement("doc", {"a": '"'})
456 gen.startElement("e", {"a": "'"})
457 gen.endElement("e")
458 gen.startElement("e", {"a": "'\""})
459 gen.endElement("e")
460 gen.startElement("e", {"a": "\n\r\t"})
461 gen.endElement("e")
462 gen.endElement("doc")
463 gen.endDocument()
Fred Drakec9fadf92001-08-07 19:17:06 +0000464
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200465 self.assertEqual(result.getvalue(), self.xml(
466 "<doc a='\"'><e a=\"'\"></e>"
467 "<e a=\"'&quot;\"></e>"
468 "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
469
470 def test_xmlgen_encoding(self):
471 encodings = ('iso-8859-15', 'utf-8', 'utf-8-sig',
472 'utf-16', 'utf-16be', 'utf-16le',
473 'utf-32', 'utf-32be', 'utf-32le')
474 for encoding in encodings:
475 result = self.ioclass()
476 gen = XMLGenerator(result, encoding=encoding)
477
478 gen.startDocument()
479 gen.startElement("doc", {"a": '\u20ac'})
480 gen.characters("\u20ac")
481 gen.endElement("doc")
482 gen.endDocument()
483
484 self.assertEqual(result.getvalue(),
485 self.xml('<doc a="\u20ac">\u20ac</doc>', encoding=encoding))
486
487 def test_xmlgen_unencodable(self):
488 result = self.ioclass()
489 gen = XMLGenerator(result, encoding='ascii')
490
491 gen.startDocument()
492 gen.startElement("doc", {"a": '\u20ac'})
493 gen.characters("\u20ac")
494 gen.endElement("doc")
495 gen.endDocument()
496
497 self.assertEqual(result.getvalue(),
498 self.xml('<doc a="&#8364;">&#8364;</doc>', encoding='ascii'))
Fred Drakec9fadf92001-08-07 19:17:06 +0000499
Guido van Rossumd8faa362007-04-27 19:54:29 +0000500 def test_xmlgen_ignorable(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200501 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000502 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000503
Guido van Rossumd8faa362007-04-27 19:54:29 +0000504 gen.startDocument()
505 gen.startElement("doc", {})
506 gen.ignorableWhitespace(" ")
507 gen.endElement("doc")
508 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000509
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200510 self.assertEqual(result.getvalue(), self.xml("<doc> </doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000511
R. David Murraya90032a2010-10-17 22:46:45 +0000512 def test_xmlgen_ignorable_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200513 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000514 gen = XMLGenerator(result, short_empty_elements=True)
515
516 gen.startDocument()
517 gen.startElement("doc", {})
518 gen.ignorableWhitespace(" ")
519 gen.endElement("doc")
520 gen.endDocument()
521
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200522 self.assertEqual(result.getvalue(), self.xml("<doc> </doc>"))
R. David Murraya90032a2010-10-17 22:46:45 +0000523
Serhiy Storchaka3eab6b32013-05-12 17:31:16 +0300524 def test_xmlgen_encoding_bytes(self):
525 encodings = ('iso-8859-15', 'utf-8', 'utf-8-sig',
526 'utf-16', 'utf-16be', 'utf-16le',
527 'utf-32', 'utf-32be', 'utf-32le')
528 for encoding in encodings:
529 result = self.ioclass()
530 gen = XMLGenerator(result, encoding=encoding)
531
532 gen.startDocument()
533 gen.startElement("doc", {"a": '\u20ac'})
534 gen.characters("\u20ac".encode(encoding))
535 gen.ignorableWhitespace(" ".encode(encoding))
536 gen.endElement("doc")
537 gen.endDocument()
538
539 self.assertEqual(result.getvalue(),
540 self.xml('<doc a="\u20ac">\u20ac </doc>', encoding=encoding))
541
Guido van Rossumd8faa362007-04-27 19:54:29 +0000542 def test_xmlgen_ns(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200543 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000544 gen = XMLGenerator(result)
Lars Gustäbel96753b32000-09-24 12:24:24 +0000545
Guido van Rossumd8faa362007-04-27 19:54:29 +0000546 gen.startDocument()
547 gen.startPrefixMapping("ns1", ns_uri)
548 gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
549 # add an unqualified name
550 gen.startElementNS((None, "udoc"), None, {})
551 gen.endElementNS((None, "udoc"), None)
552 gen.endElementNS((ns_uri, "doc"), "ns1:doc")
553 gen.endPrefixMapping("ns1")
554 gen.endDocument()
Fred Drake004d5e62000-10-23 17:22:08 +0000555
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200556 self.assertEqual(result.getvalue(), self.xml(
557 '<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
Guido van Rossumd8faa362007-04-27 19:54:29 +0000558 ns_uri))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000559
R. David Murraya90032a2010-10-17 22:46:45 +0000560 def test_xmlgen_ns_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200561 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000562 gen = XMLGenerator(result, short_empty_elements=True)
563
564 gen.startDocument()
565 gen.startPrefixMapping("ns1", ns_uri)
566 gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
567 # add an unqualified name
568 gen.startElementNS((None, "udoc"), None, {})
569 gen.endElementNS((None, "udoc"), None)
570 gen.endElementNS((ns_uri, "doc"), "ns1:doc")
571 gen.endPrefixMapping("ns1")
572 gen.endDocument()
573
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200574 self.assertEqual(result.getvalue(), self.xml(
575 '<ns1:doc xmlns:ns1="%s"><udoc/></ns1:doc>' %
R. David Murraya90032a2010-10-17 22:46:45 +0000576 ns_uri))
577
Guido van Rossumd8faa362007-04-27 19:54:29 +0000578 def test_1463026_1(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200579 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000580 gen = XMLGenerator(result)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000581
Guido van Rossumd8faa362007-04-27 19:54:29 +0000582 gen.startDocument()
583 gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
584 gen.endElementNS((None, 'a'), 'a')
585 gen.endDocument()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000586
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200587 self.assertEqual(result.getvalue(), self.xml('<a b="c"></a>'))
Thomas Wouterscf297e42007-02-23 15:07:44 +0000588
R. David Murraya90032a2010-10-17 22:46:45 +0000589 def test_1463026_1_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200590 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000591 gen = XMLGenerator(result, short_empty_elements=True)
592
593 gen.startDocument()
594 gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
595 gen.endElementNS((None, 'a'), 'a')
596 gen.endDocument()
597
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200598 self.assertEqual(result.getvalue(), self.xml('<a b="c"/>'))
R. David Murraya90032a2010-10-17 22:46:45 +0000599
Guido van Rossumd8faa362007-04-27 19:54:29 +0000600 def test_1463026_2(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200601 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000602 gen = XMLGenerator(result)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000603
Guido van Rossumd8faa362007-04-27 19:54:29 +0000604 gen.startDocument()
605 gen.startPrefixMapping(None, 'qux')
606 gen.startElementNS(('qux', 'a'), 'a', {})
607 gen.endElementNS(('qux', 'a'), 'a')
608 gen.endPrefixMapping(None)
609 gen.endDocument()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000610
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200611 self.assertEqual(result.getvalue(), self.xml('<a xmlns="qux"></a>'))
Thomas Wouterscf297e42007-02-23 15:07:44 +0000612
R. David Murraya90032a2010-10-17 22:46:45 +0000613 def test_1463026_2_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200614 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000615 gen = XMLGenerator(result, short_empty_elements=True)
616
617 gen.startDocument()
618 gen.startPrefixMapping(None, 'qux')
619 gen.startElementNS(('qux', 'a'), 'a', {})
620 gen.endElementNS(('qux', 'a'), 'a')
621 gen.endPrefixMapping(None)
622 gen.endDocument()
623
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200624 self.assertEqual(result.getvalue(), self.xml('<a xmlns="qux"/>'))
R. David Murraya90032a2010-10-17 22:46:45 +0000625
Guido van Rossumd8faa362007-04-27 19:54:29 +0000626 def test_1463026_3(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200627 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000628 gen = XMLGenerator(result)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000629
Guido van Rossumd8faa362007-04-27 19:54:29 +0000630 gen.startDocument()
631 gen.startPrefixMapping('my', 'qux')
632 gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
633 gen.endElementNS(('qux', 'a'), 'a')
634 gen.endPrefixMapping('my')
635 gen.endDocument()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000636
Ezio Melottib3aedd42010-11-20 19:04:17 +0000637 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200638 self.xml('<my:a xmlns:my="qux" b="c"></my:a>'))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000639
R. David Murraya90032a2010-10-17 22:46:45 +0000640 def test_1463026_3_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200641 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000642 gen = XMLGenerator(result, short_empty_elements=True)
643
644 gen.startDocument()
645 gen.startPrefixMapping('my', 'qux')
646 gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
647 gen.endElementNS(('qux', 'a'), 'a')
648 gen.endPrefixMapping('my')
649 gen.endDocument()
650
Ezio Melottib3aedd42010-11-20 19:04:17 +0000651 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200652 self.xml('<my:a xmlns:my="qux" b="c"/>'))
R. David Murraya90032a2010-10-17 22:46:45 +0000653
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000654 def test_5027_1(self):
655 # The xml prefix (as in xml:lang below) is reserved and bound by
656 # definition to http://www.w3.org/XML/1998/namespace. XMLGenerator had
Andrew Svetlov737fb892012-12-18 21:14:22 +0200657 # a bug whereby a KeyError is raised because this namespace is missing
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000658 # from a dictionary.
659 #
660 # This test demonstrates the bug by parsing a document.
661 test_xml = StringIO(
662 '<?xml version="1.0"?>'
663 '<a:g1 xmlns:a="http://example.com/ns">'
664 '<a:g2 xml:lang="en">Hello</a:g2>'
665 '</a:g1>')
666
667 parser = make_parser()
668 parser.setFeature(feature_namespaces, True)
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200669 result = self.ioclass()
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000670 gen = XMLGenerator(result)
671 parser.setContentHandler(gen)
672 parser.parse(test_xml)
673
Ezio Melottib3aedd42010-11-20 19:04:17 +0000674 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200675 self.xml(
Ezio Melottib3aedd42010-11-20 19:04:17 +0000676 '<a:g1 xmlns:a="http://example.com/ns">'
677 '<a:g2 xml:lang="en">Hello</a:g2>'
678 '</a:g1>'))
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000679
680 def test_5027_2(self):
681 # The xml prefix (as in xml:lang below) is reserved and bound by
682 # definition to http://www.w3.org/XML/1998/namespace. XMLGenerator had
Andrew Svetlov737fb892012-12-18 21:14:22 +0200683 # a bug whereby a KeyError is raised because this namespace is missing
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000684 # from a dictionary.
685 #
686 # This test demonstrates the bug by direct manipulation of the
687 # XMLGenerator.
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200688 result = self.ioclass()
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000689 gen = XMLGenerator(result)
690
691 gen.startDocument()
692 gen.startPrefixMapping('a', 'http://example.com/ns')
693 gen.startElementNS(('http://example.com/ns', 'g1'), 'g1', {})
694 lang_attr = {('http://www.w3.org/XML/1998/namespace', 'lang'): 'en'}
695 gen.startElementNS(('http://example.com/ns', 'g2'), 'g2', lang_attr)
696 gen.characters('Hello')
697 gen.endElementNS(('http://example.com/ns', 'g2'), 'g2')
698 gen.endElementNS(('http://example.com/ns', 'g1'), 'g1')
699 gen.endPrefixMapping('a')
700 gen.endDocument()
701
Ezio Melottib3aedd42010-11-20 19:04:17 +0000702 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200703 self.xml(
Ezio Melottib3aedd42010-11-20 19:04:17 +0000704 '<a:g1 xmlns:a="http://example.com/ns">'
705 '<a:g2 xml:lang="en">Hello</a:g2>'
706 '</a:g1>'))
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000707
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200708 def test_no_close_file(self):
709 result = self.ioclass()
710 def func(out):
711 gen = XMLGenerator(out)
712 gen.startDocument()
713 gen.startElement("doc", {})
714 func(result)
715 self.assertFalse(result.closed)
716
Serhiy Storchakaa5f13d22013-02-25 13:46:10 +0200717 def test_xmlgen_fragment(self):
718 result = self.ioclass()
719 gen = XMLGenerator(result)
720
721 # Don't call gen.startDocument()
722 gen.startElement("foo", {"a": "1.0"})
723 gen.characters("Hello")
724 gen.endElement("foo")
725 gen.startElement("bar", {"b": "2.0"})
726 gen.endElement("bar")
727 # Don't call gen.endDocument()
728
729 self.assertEqual(result.getvalue(),
730 self.xml('<foo a="1.0">Hello</foo><bar b="2.0"></bar>')[len(self.xml('')):])
731
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200732class StringXmlgenTest(XmlgenTest, unittest.TestCase):
733 ioclass = StringIO
734
735 def xml(self, doc, encoding='iso-8859-1'):
736 return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, doc)
737
738 test_xmlgen_unencodable = None
739
740class BytesXmlgenTest(XmlgenTest, unittest.TestCase):
741 ioclass = BytesIO
742
743 def xml(self, doc, encoding='iso-8859-1'):
744 return ('<?xml version="1.0" encoding="%s"?>\n%s' %
745 (encoding, doc)).encode(encoding, 'xmlcharrefreplace')
746
747class WriterXmlgenTest(BytesXmlgenTest):
748 class ioclass(list):
749 write = list.append
750 closed = False
751
752 def seekable(self):
753 return True
754
755 def tell(self):
756 # return 0 at start and not 0 after start
757 return len(self)
758
759 def getvalue(self):
760 return b''.join(self)
761
Georg Brandlc502df42013-05-12 11:41:12 +0200762class StreamWriterXmlgenTest(XmlgenTest, unittest.TestCase):
763 def ioclass(self):
764 raw = BytesIO()
765 writer = codecs.getwriter('ascii')(raw, 'xmlcharrefreplace')
766 writer.getvalue = raw.getvalue
767 return writer
768
769 def xml(self, doc, encoding='iso-8859-1'):
770 return ('<?xml version="1.0" encoding="%s"?>\n%s' %
771 (encoding, doc)).encode('ascii', 'xmlcharrefreplace')
772
773class StreamReaderWriterXmlgenTest(XmlgenTest, unittest.TestCase):
774 fname = support.TESTFN + '-codecs'
775
776 def ioclass(self):
777 writer = codecs.open(self.fname, 'w', encoding='ascii',
778 errors='xmlcharrefreplace', buffering=0)
Antoine Pitrou2adb6fe2013-05-13 22:34:21 +0200779 def cleanup():
780 writer.close()
781 support.unlink(self.fname)
782 self.addCleanup(cleanup)
Richard Oudkerk90a24272013-05-18 18:11:30 +0100783 def getvalue():
784 # Windows will not let use reopen without first closing
785 writer.close()
786 with open(writer.name, 'rb') as f:
787 return f.read()
788 writer.getvalue = getvalue
Georg Brandlc502df42013-05-12 11:41:12 +0200789 return writer
790
Georg Brandlc502df42013-05-12 11:41:12 +0200791 def xml(self, doc, encoding='iso-8859-1'):
792 return ('<?xml version="1.0" encoding="%s"?>\n%s' %
793 (encoding, doc)).encode('ascii', 'xmlcharrefreplace')
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200794
795start = b'<?xml version="1.0" encoding="iso-8859-1"?>\n'
796
Fred Drake004d5e62000-10-23 17:22:08 +0000797
Guido van Rossumd8faa362007-04-27 19:54:29 +0000798class XMLFilterBaseTest(unittest.TestCase):
799 def test_filter_basic(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200800 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000801 gen = XMLGenerator(result)
802 filter = XMLFilterBase()
803 filter.setContentHandler(gen)
Lars Gustäbel96753b32000-09-24 12:24:24 +0000804
Guido van Rossumd8faa362007-04-27 19:54:29 +0000805 filter.startDocument()
806 filter.startElement("doc", {})
807 filter.characters("content")
808 filter.ignorableWhitespace(" ")
809 filter.endElement("doc")
810 filter.endDocument()
811
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200812 self.assertEqual(result.getvalue(), start + b"<doc>content </doc>")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000813
814# ===========================================================================
815#
816# expatreader tests
817#
818# ===========================================================================
819
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200820with open(TEST_XMLFILE_OUT, 'rb') as f:
Benjamin Petersond5df36d2010-10-31 18:23:23 +0000821 xml_test_out = f.read()
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000822
Guido van Rossumd8faa362007-04-27 19:54:29 +0000823class ExpatReaderTest(XmlTestBase):
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000824
Guido van Rossumd8faa362007-04-27 19:54:29 +0000825 # ===== XMLReader support
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000826
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300827 def test_expat_binary_file(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000828 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200829 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000830 xmlgen = XMLGenerator(result)
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000831
Guido van Rossumd8faa362007-04-27 19:54:29 +0000832 parser.setContentHandler(xmlgen)
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200833 with open(TEST_XMLFILE, 'rb') as f:
Benjamin Petersond5df36d2010-10-31 18:23:23 +0000834 parser.parse(f)
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000835
Ezio Melottib3aedd42010-11-20 19:04:17 +0000836 self.assertEqual(result.getvalue(), xml_test_out)
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000837
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300838 def test_expat_text_file(self):
839 parser = create_parser()
840 result = BytesIO()
841 xmlgen = XMLGenerator(result)
842
843 parser.setContentHandler(xmlgen)
844 with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f:
845 parser.parse(f)
846
847 self.assertEqual(result.getvalue(), xml_test_out)
848
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +0200849 @requires_nonascii_filenames
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300850 def test_expat_binary_file_nonascii(self):
Serhiy Storchakad5202392013-02-02 10:31:17 +0200851 fname = support.TESTFN_UNICODE
852 shutil.copyfile(TEST_XMLFILE, fname)
853 self.addCleanup(support.unlink, fname)
854
855 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200856 result = BytesIO()
Serhiy Storchakad5202392013-02-02 10:31:17 +0200857 xmlgen = XMLGenerator(result)
858
859 parser.setContentHandler(xmlgen)
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300860 parser.parse(open(fname, 'rb'))
Serhiy Storchakad5202392013-02-02 10:31:17 +0200861
862 self.assertEqual(result.getvalue(), xml_test_out)
863
Serhiy Storchakafc8e9b02014-11-27 22:13:16 +0200864 def test_expat_binary_file_bytes_name(self):
865 fname = os.fsencode(TEST_XMLFILE)
866 parser = create_parser()
867 result = BytesIO()
868 xmlgen = XMLGenerator(result)
869
870 parser.setContentHandler(xmlgen)
871 with open(fname, 'rb') as f:
872 parser.parse(f)
873
874 self.assertEqual(result.getvalue(), xml_test_out)
875
876 def test_expat_binary_file_int_name(self):
877 parser = create_parser()
878 result = BytesIO()
879 xmlgen = XMLGenerator(result)
880
881 parser.setContentHandler(xmlgen)
882 with open(TEST_XMLFILE, 'rb') as f:
883 with open(f.fileno(), 'rb', closefd=False) as f2:
884 parser.parse(f2)
885
886 self.assertEqual(result.getvalue(), xml_test_out)
887
Guido van Rossumd8faa362007-04-27 19:54:29 +0000888 # ===== DTDHandler support
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000889
Guido van Rossumd8faa362007-04-27 19:54:29 +0000890 class TestDTDHandler:
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000891
Guido van Rossumd8faa362007-04-27 19:54:29 +0000892 def __init__(self):
893 self._notations = []
894 self._entities = []
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000895
Guido van Rossumd8faa362007-04-27 19:54:29 +0000896 def notationDecl(self, name, publicId, systemId):
897 self._notations.append((name, publicId, systemId))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000898
Guido van Rossumd8faa362007-04-27 19:54:29 +0000899 def unparsedEntityDecl(self, name, publicId, systemId, ndata):
900 self._entities.append((name, publicId, systemId, ndata))
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000901
Guido van Rossumd8faa362007-04-27 19:54:29 +0000902 def test_expat_dtdhandler(self):
903 parser = create_parser()
904 handler = self.TestDTDHandler()
905 parser.setDTDHandler(handler)
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000906
Guido van Rossumd8faa362007-04-27 19:54:29 +0000907 parser.feed('<!DOCTYPE doc [\n')
908 parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
909 parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
910 parser.feed(']>\n')
911 parser.feed('<doc></doc>')
912 parser.close()
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000913
Ezio Melottib3aedd42010-11-20 19:04:17 +0000914 self.assertEqual(handler._notations,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000915 [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
Ezio Melottib3aedd42010-11-20 19:04:17 +0000916 self.assertEqual(handler._entities, [("img", None, "expat.gif", "GIF")])
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000917
Guido van Rossumd8faa362007-04-27 19:54:29 +0000918 # ===== EntityResolver support
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000919
Guido van Rossumd8faa362007-04-27 19:54:29 +0000920 class TestEntityResolver:
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000921
Guido van Rossumd8faa362007-04-27 19:54:29 +0000922 def resolveEntity(self, publicId, systemId):
923 inpsrc = InputSource()
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200924 inpsrc.setByteStream(BytesIO(b"<entity/>"))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000925 return inpsrc
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000926
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927 def test_expat_entityresolver(self):
928 parser = create_parser()
929 parser.setEntityResolver(self.TestEntityResolver())
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200930 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000931 parser.setContentHandler(XMLGenerator(result))
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000932
Guido van Rossumd8faa362007-04-27 19:54:29 +0000933 parser.feed('<!DOCTYPE doc [\n')
934 parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
935 parser.feed(']>\n')
936 parser.feed('<doc>&test;</doc>')
937 parser.close()
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000938
Ezio Melottib3aedd42010-11-20 19:04:17 +0000939 self.assertEqual(result.getvalue(), start +
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200940 b"<doc><entity></entity></doc>")
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000941
Guido van Rossumd8faa362007-04-27 19:54:29 +0000942 # ===== Attributes support
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000943
Guido van Rossumd8faa362007-04-27 19:54:29 +0000944 class AttrGatherer(ContentHandler):
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000945
Guido van Rossumd8faa362007-04-27 19:54:29 +0000946 def startElement(self, name, attrs):
947 self._attrs = attrs
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000948
Guido van Rossumd8faa362007-04-27 19:54:29 +0000949 def startElementNS(self, name, qname, attrs):
950 self._attrs = attrs
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000951
Guido van Rossumd8faa362007-04-27 19:54:29 +0000952 def test_expat_attrs_empty(self):
953 parser = create_parser()
954 gather = self.AttrGatherer()
955 parser.setContentHandler(gather)
956
957 parser.feed("<doc/>")
958 parser.close()
959
960 self.verify_empty_attrs(gather._attrs)
961
962 def test_expat_attrs_wattr(self):
963 parser = create_parser()
964 gather = self.AttrGatherer()
965 parser.setContentHandler(gather)
966
967 parser.feed("<doc attr='val'/>")
968 parser.close()
969
970 self.verify_attrs_wattr(gather._attrs)
971
972 def test_expat_nsattrs_empty(self):
973 parser = create_parser(1)
974 gather = self.AttrGatherer()
975 parser.setContentHandler(gather)
976
977 parser.feed("<doc/>")
978 parser.close()
979
980 self.verify_empty_nsattrs(gather._attrs)
981
982 def test_expat_nsattrs_wattr(self):
983 parser = create_parser(1)
984 gather = self.AttrGatherer()
985 parser.setContentHandler(gather)
986
987 parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
988 parser.close()
989
990 attrs = gather._attrs
991
Ezio Melottib3aedd42010-11-20 19:04:17 +0000992 self.assertEqual(attrs.getLength(), 1)
993 self.assertEqual(attrs.getNames(), [(ns_uri, "attr")])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000994 self.assertTrue((attrs.getQNames() == [] or
995 attrs.getQNames() == ["ns:attr"]))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000996 self.assertEqual(len(attrs), 1)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000997 self.assertIn((ns_uri, "attr"), attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000998 self.assertEqual(attrs.get((ns_uri, "attr")), "val")
999 self.assertEqual(attrs.get((ns_uri, "attr"), 25), "val")
1000 self.assertEqual(list(attrs.items()), [((ns_uri, "attr"), "val")])
1001 self.assertEqual(list(attrs.values()), ["val"])
1002 self.assertEqual(attrs.getValue((ns_uri, "attr")), "val")
1003 self.assertEqual(attrs[(ns_uri, "attr")], "val")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001004
1005 # ===== InputSource support
1006
Benjamin Petersona7f4f5a2008-09-04 02:22:52 +00001007 def test_expat_inpsource_filename(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001008 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001009 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001010 xmlgen = XMLGenerator(result)
1011
1012 parser.setContentHandler(xmlgen)
Florent Xiclunaf15351d2010-03-13 23:24:31 +00001013 parser.parse(TEST_XMLFILE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001014
Ezio Melottib3aedd42010-11-20 19:04:17 +00001015 self.assertEqual(result.getvalue(), xml_test_out)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001016
Benjamin Petersona7f4f5a2008-09-04 02:22:52 +00001017 def test_expat_inpsource_sysid(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001018 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001019 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001020 xmlgen = XMLGenerator(result)
1021
1022 parser.setContentHandler(xmlgen)
Florent Xiclunaf15351d2010-03-13 23:24:31 +00001023 parser.parse(InputSource(TEST_XMLFILE))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001024
Ezio Melottib3aedd42010-11-20 19:04:17 +00001025 self.assertEqual(result.getvalue(), xml_test_out)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001026
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +02001027 @requires_nonascii_filenames
Serhiy Storchakad5202392013-02-02 10:31:17 +02001028 def test_expat_inpsource_sysid_nonascii(self):
1029 fname = support.TESTFN_UNICODE
1030 shutil.copyfile(TEST_XMLFILE, fname)
1031 self.addCleanup(support.unlink, fname)
1032
1033 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001034 result = BytesIO()
Serhiy Storchakad5202392013-02-02 10:31:17 +02001035 xmlgen = XMLGenerator(result)
1036
1037 parser.setContentHandler(xmlgen)
1038 parser.parse(InputSource(fname))
1039
1040 self.assertEqual(result.getvalue(), xml_test_out)
1041
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +03001042 def test_expat_inpsource_byte_stream(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001043 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001044 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001045 xmlgen = XMLGenerator(result)
1046
1047 parser.setContentHandler(xmlgen)
1048 inpsrc = InputSource()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001049 with open(TEST_XMLFILE, 'rb') as f:
Benjamin Petersond5df36d2010-10-31 18:23:23 +00001050 inpsrc.setByteStream(f)
1051 parser.parse(inpsrc)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001052
Ezio Melottib3aedd42010-11-20 19:04:17 +00001053 self.assertEqual(result.getvalue(), xml_test_out)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001054
Serhiy Storchaka61de0872015-04-02 21:00:13 +03001055 def test_expat_inpsource_character_stream(self):
1056 parser = create_parser()
1057 result = BytesIO()
1058 xmlgen = XMLGenerator(result)
1059
1060 parser.setContentHandler(xmlgen)
1061 inpsrc = InputSource()
1062 with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f:
1063 inpsrc.setCharacterStream(f)
1064 parser.parse(inpsrc)
1065
1066 self.assertEqual(result.getvalue(), xml_test_out)
1067
Guido van Rossumd8faa362007-04-27 19:54:29 +00001068 # ===== IncrementalParser support
1069
1070 def test_expat_incremental(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001071 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001072 xmlgen = XMLGenerator(result)
1073 parser = create_parser()
1074 parser.setContentHandler(xmlgen)
1075
1076 parser.feed("<doc>")
1077 parser.feed("</doc>")
1078 parser.close()
1079
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001080 self.assertEqual(result.getvalue(), start + b"<doc></doc>")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001081
1082 def test_expat_incremental_reset(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001083 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001084 xmlgen = XMLGenerator(result)
1085 parser = create_parser()
1086 parser.setContentHandler(xmlgen)
1087
1088 parser.feed("<doc>")
1089 parser.feed("text")
1090
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001091 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001092 xmlgen = XMLGenerator(result)
1093 parser.setContentHandler(xmlgen)
1094 parser.reset()
1095
1096 parser.feed("<doc>")
1097 parser.feed("text")
1098 parser.feed("</doc>")
1099 parser.close()
1100
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001101 self.assertEqual(result.getvalue(), start + b"<doc>text</doc>")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001102
1103 # ===== Locator support
1104
1105 def test_expat_locator_noinfo(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001106 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001107 xmlgen = XMLGenerator(result)
1108 parser = create_parser()
1109 parser.setContentHandler(xmlgen)
1110
1111 parser.feed("<doc>")
1112 parser.feed("</doc>")
1113 parser.close()
1114
Ezio Melottib3aedd42010-11-20 19:04:17 +00001115 self.assertEqual(parser.getSystemId(), None)
1116 self.assertEqual(parser.getPublicId(), None)
1117 self.assertEqual(parser.getLineNumber(), 1)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001118
Benjamin Petersona7f4f5a2008-09-04 02:22:52 +00001119 def test_expat_locator_withinfo(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001120 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001121 xmlgen = XMLGenerator(result)
1122 parser = create_parser()
1123 parser.setContentHandler(xmlgen)
Florent Xiclunaf15351d2010-03-13 23:24:31 +00001124 parser.parse(TEST_XMLFILE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001125
Ezio Melottib3aedd42010-11-20 19:04:17 +00001126 self.assertEqual(parser.getSystemId(), TEST_XMLFILE)
1127 self.assertEqual(parser.getPublicId(), None)
Lars Gustäbel2fc52942000-10-24 15:35:07 +00001128
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +02001129 @requires_nonascii_filenames
Serhiy Storchakad5202392013-02-02 10:31:17 +02001130 def test_expat_locator_withinfo_nonascii(self):
1131 fname = support.TESTFN_UNICODE
1132 shutil.copyfile(TEST_XMLFILE, fname)
1133 self.addCleanup(support.unlink, fname)
1134
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001135 result = BytesIO()
Serhiy Storchakad5202392013-02-02 10:31:17 +02001136 xmlgen = XMLGenerator(result)
1137 parser = create_parser()
1138 parser.setContentHandler(xmlgen)
1139 parser.parse(fname)
1140
1141 self.assertEqual(parser.getSystemId(), fname)
1142 self.assertEqual(parser.getPublicId(), None)
1143
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001144
1145# ===========================================================================
1146#
1147# error reporting
1148#
1149# ===========================================================================
1150
Guido van Rossumd8faa362007-04-27 19:54:29 +00001151class ErrorReportingTest(unittest.TestCase):
1152 def test_expat_inpsource_location(self):
1153 parser = create_parser()
1154 parser.setContentHandler(ContentHandler()) # do nothing
1155 source = InputSource()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001156 source.setByteStream(BytesIO(b"<foo bar foobar>")) #ill-formed
Guido van Rossumd8faa362007-04-27 19:54:29 +00001157 name = "a file name"
1158 source.setSystemId(name)
1159 try:
1160 parser.parse(source)
1161 self.fail()
1162 except SAXException as e:
Ezio Melottib3aedd42010-11-20 19:04:17 +00001163 self.assertEqual(e.getSystemId(), name)
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001164
Guido van Rossumd8faa362007-04-27 19:54:29 +00001165 def test_expat_incomplete(self):
1166 parser = create_parser()
1167 parser.setContentHandler(ContentHandler()) # do nothing
1168 self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001169
Guido van Rossumd8faa362007-04-27 19:54:29 +00001170 def test_sax_parse_exception_str(self):
1171 # pass various values from a locator to the SAXParseException to
1172 # make sure that the __str__() doesn't fall apart when None is
1173 # passed instead of an integer line and column number
1174 #
1175 # use "normal" values for the locator:
1176 str(SAXParseException("message", None,
1177 self.DummyLocator(1, 1)))
1178 # use None for the line number:
1179 str(SAXParseException("message", None,
1180 self.DummyLocator(None, 1)))
1181 # use None for the column number:
1182 str(SAXParseException("message", None,
1183 self.DummyLocator(1, None)))
1184 # use None for both:
1185 str(SAXParseException("message", None,
1186 self.DummyLocator(None, None)))
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001187
Guido van Rossumd8faa362007-04-27 19:54:29 +00001188 class DummyLocator:
1189 def __init__(self, lineno, colno):
1190 self._lineno = lineno
1191 self._colno = colno
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001192
Guido van Rossumd8faa362007-04-27 19:54:29 +00001193 def getPublicId(self):
1194 return "pubid"
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001195
Guido van Rossumd8faa362007-04-27 19:54:29 +00001196 def getSystemId(self):
1197 return "sysid"
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001198
Guido van Rossumd8faa362007-04-27 19:54:29 +00001199 def getLineNumber(self):
1200 return self._lineno
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001201
Guido van Rossumd8faa362007-04-27 19:54:29 +00001202 def getColumnNumber(self):
1203 return self._colno
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001204
Lars Gustäbelab647872000-09-24 18:40:52 +00001205# ===========================================================================
1206#
1207# xmlreader tests
1208#
1209# ===========================================================================
1210
Guido van Rossumd8faa362007-04-27 19:54:29 +00001211class XmlReaderTest(XmlTestBase):
Lars Gustäbelab647872000-09-24 18:40:52 +00001212
Guido van Rossumd8faa362007-04-27 19:54:29 +00001213 # ===== AttributesImpl
1214 def test_attrs_empty(self):
1215 self.verify_empty_attrs(AttributesImpl({}))
Lars Gustäbelab647872000-09-24 18:40:52 +00001216
Guido van Rossumd8faa362007-04-27 19:54:29 +00001217 def test_attrs_wattr(self):
1218 self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
Lars Gustäbelab647872000-09-24 18:40:52 +00001219
Guido van Rossumd8faa362007-04-27 19:54:29 +00001220 def test_nsattrs_empty(self):
1221 self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
Lars Gustäbelab647872000-09-24 18:40:52 +00001222
Guido van Rossumd8faa362007-04-27 19:54:29 +00001223 def test_nsattrs_wattr(self):
1224 attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
1225 {(ns_uri, "attr") : "ns:attr"})
Fred Drake004d5e62000-10-23 17:22:08 +00001226
Ezio Melottib3aedd42010-11-20 19:04:17 +00001227 self.assertEqual(attrs.getLength(), 1)
1228 self.assertEqual(attrs.getNames(), [(ns_uri, "attr")])
1229 self.assertEqual(attrs.getQNames(), ["ns:attr"])
1230 self.assertEqual(len(attrs), 1)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001231 self.assertIn((ns_uri, "attr"), attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001232 self.assertEqual(list(attrs.keys()), [(ns_uri, "attr")])
1233 self.assertEqual(attrs.get((ns_uri, "attr")), "val")
1234 self.assertEqual(attrs.get((ns_uri, "attr"), 25), "val")
1235 self.assertEqual(list(attrs.items()), [((ns_uri, "attr"), "val")])
1236 self.assertEqual(list(attrs.values()), ["val"])
1237 self.assertEqual(attrs.getValue((ns_uri, "attr")), "val")
1238 self.assertEqual(attrs.getValueByQName("ns:attr"), "val")
1239 self.assertEqual(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
1240 self.assertEqual(attrs[(ns_uri, "attr")], "val")
1241 self.assertEqual(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
Fred Drake004d5e62000-10-23 17:22:08 +00001242
Lars Gustäbelab647872000-09-24 18:40:52 +00001243
Christian Heimesbbe741d2008-03-28 10:53:29 +00001244def test_main():
Guido van Rossumd8faa362007-04-27 19:54:29 +00001245 run_unittest(MakeParserTest,
Serhiy Storchaka13e41c52015-04-02 23:05:57 +03001246 ParseTest,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001247 SaxutilsTest,
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +03001248 PrepareInputSourceTest,
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001249 StringXmlgenTest,
1250 BytesXmlgenTest,
1251 WriterXmlgenTest,
Georg Brandlc502df42013-05-12 11:41:12 +02001252 StreamWriterXmlgenTest,
1253 StreamReaderWriterXmlgenTest,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001254 ExpatReaderTest,
1255 ErrorReportingTest,
1256 XmlReaderTest)
Lars Gustäbelb7536d52000-09-24 18:53:56 +00001257
Guido van Rossumd8faa362007-04-27 19:54:29 +00001258if __name__ == "__main__":
Christian Heimesbbe741d2008-03-28 10:53:29 +00001259 test_main()