blob: 2eb62905ffa882ba04c181af54a51424e3132d4e [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
Victor Stinneref9c0e72017-05-05 09:46:47 +02007from unittest import mock
Martin v. Löwis962c9e72000-10-06 17:41:52 +00008try:
9 make_parser()
Martin v. Löwis80670bc2000-10-06 21:13:23 +000010except SAXReaderNotAvailable:
Martin v. Löwis962c9e72000-10-06 17:41:52 +000011 # don't try to test this module if we cannot create a parser
R David Murraya846f5a2013-03-18 00:18:12 -040012 raise unittest.SkipTest("no XML parsers available")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000013from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +030014 XMLFilterBase, prepare_input_source
Thomas Wouters0e3f5912006-08-11 14:57:12 +000015from xml.sax.expatreader import create_parser
Antoine Pitrou6b03ee62010-10-27 18:33:30 +000016from xml.sax.handler import feature_namespaces
Thomas Wouters0e3f5912006-08-11 14:57:12 +000017from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
Serhiy Storchaka88efc522013-02-10 14:29:52 +020018from io import BytesIO, StringIO
Georg Brandlc502df42013-05-12 11:41:12 +020019import codecs
Serhiy Storchaka13e41c52015-04-02 23:05:57 +030020import gc
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +020021import os.path
Serhiy Storchakad5202392013-02-02 10:31:17 +020022import shutil
23from test import support
Serhiy Storchaka13e41c52015-04-02 23:05:57 +030024from test.support import findfile, run_unittest, TESTFN
Florent Xiclunaf15351d2010-03-13 23:24:31 +000025
26TEST_XMLFILE = findfile("test.xml", subdir="xmltestdata")
27TEST_XMLFILE_OUT = findfile("test.xml.out", subdir="xmltestdata")
Victor Stinner6c6f8512010-08-07 10:09:35 +000028try:
Marc-André Lemburg8f36af72011-02-25 15:42:01 +000029 TEST_XMLFILE.encode("utf-8")
30 TEST_XMLFILE_OUT.encode("utf-8")
Victor Stinner6c6f8512010-08-07 10:09:35 +000031except UnicodeEncodeError:
32 raise unittest.SkipTest("filename is not encodable to utf8")
Lars Gustäbel96753b32000-09-24 12:24:24 +000033
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +020034supports_nonascii_filenames = True
35if not os.path.supports_unicode_filenames:
36 try:
37 support.TESTFN_UNICODE.encode(support.TESTFN_ENCODING)
38 except (UnicodeError, TypeError):
39 # Either the file system encoding is None, or the file name
40 # cannot be encoded in the file system encoding.
41 supports_nonascii_filenames = False
42requires_nonascii_filenames = unittest.skipUnless(
43 supports_nonascii_filenames,
44 'Requires non-ascii filenames support')
45
Guido van Rossumd8faa362007-04-27 19:54:29 +000046ns_uri = "http://www.python.org/xml-ns/saxtest/"
Lars Gustäbel96753b32000-09-24 12:24:24 +000047
Guido van Rossumd8faa362007-04-27 19:54:29 +000048class XmlTestBase(unittest.TestCase):
49 def verify_empty_attrs(self, attrs):
50 self.assertRaises(KeyError, attrs.getValue, "attr")
51 self.assertRaises(KeyError, attrs.getValueByQName, "attr")
52 self.assertRaises(KeyError, attrs.getNameByQName, "attr")
53 self.assertRaises(KeyError, attrs.getQNameByName, "attr")
54 self.assertRaises(KeyError, attrs.__getitem__, "attr")
Ezio Melottib3aedd42010-11-20 19:04:17 +000055 self.assertEqual(attrs.getLength(), 0)
56 self.assertEqual(attrs.getNames(), [])
57 self.assertEqual(attrs.getQNames(), [])
58 self.assertEqual(len(attrs), 0)
Ezio Melottib58e0bd2010-01-23 15:40:09 +000059 self.assertNotIn("attr", attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +000060 self.assertEqual(list(attrs.keys()), [])
61 self.assertEqual(attrs.get("attrs"), None)
62 self.assertEqual(attrs.get("attrs", 25), 25)
63 self.assertEqual(list(attrs.items()), [])
64 self.assertEqual(list(attrs.values()), [])
Lars Gustäbel96753b32000-09-24 12:24:24 +000065
Guido van Rossumd8faa362007-04-27 19:54:29 +000066 def verify_empty_nsattrs(self, attrs):
67 self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
68 self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
69 self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
70 self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
71 self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
Ezio Melottib3aedd42010-11-20 19:04:17 +000072 self.assertEqual(attrs.getLength(), 0)
73 self.assertEqual(attrs.getNames(), [])
74 self.assertEqual(attrs.getQNames(), [])
75 self.assertEqual(len(attrs), 0)
Ezio Melottib58e0bd2010-01-23 15:40:09 +000076 self.assertNotIn((ns_uri, "attr"), attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +000077 self.assertEqual(list(attrs.keys()), [])
78 self.assertEqual(attrs.get((ns_uri, "attr")), None)
79 self.assertEqual(attrs.get((ns_uri, "attr"), 25), 25)
80 self.assertEqual(list(attrs.items()), [])
81 self.assertEqual(list(attrs.values()), [])
Lars Gustäbel96753b32000-09-24 12:24:24 +000082
Guido van Rossumd8faa362007-04-27 19:54:29 +000083 def verify_attrs_wattr(self, attrs):
Ezio Melottib3aedd42010-11-20 19:04:17 +000084 self.assertEqual(attrs.getLength(), 1)
85 self.assertEqual(attrs.getNames(), ["attr"])
86 self.assertEqual(attrs.getQNames(), ["attr"])
87 self.assertEqual(len(attrs), 1)
Benjamin Peterson577473f2010-01-19 00:09:57 +000088 self.assertIn("attr", attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +000089 self.assertEqual(list(attrs.keys()), ["attr"])
90 self.assertEqual(attrs.get("attr"), "val")
91 self.assertEqual(attrs.get("attr", 25), "val")
92 self.assertEqual(list(attrs.items()), [("attr", "val")])
93 self.assertEqual(list(attrs.values()), ["val"])
94 self.assertEqual(attrs.getValue("attr"), "val")
95 self.assertEqual(attrs.getValueByQName("attr"), "val")
96 self.assertEqual(attrs.getNameByQName("attr"), "attr")
97 self.assertEqual(attrs["attr"], "val")
98 self.assertEqual(attrs.getQNameByName("attr"), "attr")
Lars Gustäbel96753b32000-09-24 12:24:24 +000099
Serhiy Storchaka13e41c52015-04-02 23:05:57 +0300100
101def xml_str(doc, encoding=None):
102 if encoding is None:
103 return doc
104 return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, doc)
105
106def xml_bytes(doc, encoding, decl_encoding=...):
107 if decl_encoding is ...:
108 decl_encoding = encoding
109 return xml_str(doc, decl_encoding).encode(encoding, 'xmlcharrefreplace')
110
111def make_xml_file(doc, encoding, decl_encoding=...):
112 if decl_encoding is ...:
113 decl_encoding = encoding
114 with open(TESTFN, 'w', encoding=encoding, errors='xmlcharrefreplace') as f:
115 f.write(xml_str(doc, decl_encoding))
116
117
118class ParseTest(unittest.TestCase):
119 data = '<money value="$\xa3\u20ac\U0001017b">$\xa3\u20ac\U0001017b</money>'
120
121 def tearDown(self):
122 support.unlink(TESTFN)
123
124 def check_parse(self, f):
125 from xml.sax import parse
126 result = StringIO()
127 parse(f, XMLGenerator(result, 'utf-8'))
128 self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8'))
129
130 def test_parse_text(self):
131 encodings = ('us-ascii', 'iso-8859-1', 'utf-8',
132 'utf-16', 'utf-16le', 'utf-16be')
133 for encoding in encodings:
134 self.check_parse(StringIO(xml_str(self.data, encoding)))
135 make_xml_file(self.data, encoding)
136 with open(TESTFN, 'r', encoding=encoding) as f:
137 self.check_parse(f)
138 self.check_parse(StringIO(self.data))
139 make_xml_file(self.data, encoding, None)
140 with open(TESTFN, 'r', encoding=encoding) as f:
141 self.check_parse(f)
142
143 def test_parse_bytes(self):
144 # UTF-8 is default encoding, US-ASCII is compatible with UTF-8,
145 # UTF-16 is autodetected
146 encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be')
147 for encoding in encodings:
148 self.check_parse(BytesIO(xml_bytes(self.data, encoding)))
149 make_xml_file(self.data, encoding)
150 self.check_parse(TESTFN)
151 with open(TESTFN, 'rb') as f:
152 self.check_parse(f)
153 self.check_parse(BytesIO(xml_bytes(self.data, encoding, None)))
154 make_xml_file(self.data, encoding, None)
155 self.check_parse(TESTFN)
156 with open(TESTFN, 'rb') as f:
157 self.check_parse(f)
158 # accept UTF-8 with BOM
159 self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', 'utf-8')))
160 make_xml_file(self.data, 'utf-8-sig', 'utf-8')
161 self.check_parse(TESTFN)
162 with open(TESTFN, 'rb') as f:
163 self.check_parse(f)
164 self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', None)))
165 make_xml_file(self.data, 'utf-8-sig', None)
166 self.check_parse(TESTFN)
167 with open(TESTFN, 'rb') as f:
168 self.check_parse(f)
169 # accept data with declared encoding
170 self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1')))
171 make_xml_file(self.data, 'iso-8859-1')
172 self.check_parse(TESTFN)
173 with open(TESTFN, 'rb') as f:
174 self.check_parse(f)
175 # fail on non-UTF-8 incompatible data without declared encoding
176 with self.assertRaises(SAXException):
177 self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None)))
178 make_xml_file(self.data, 'iso-8859-1', None)
Victor Stinneref9c0e72017-05-05 09:46:47 +0200179 with self.assertRaises(SAXException):
180 self.check_parse(TESTFN)
Serhiy Storchaka13e41c52015-04-02 23:05:57 +0300181 with open(TESTFN, 'rb') as f:
182 with self.assertRaises(SAXException):
183 self.check_parse(f)
184
185 def test_parse_InputSource(self):
186 # accept data without declared but with explicitly specified encoding
187 make_xml_file(self.data, 'iso-8859-1', None)
188 with open(TESTFN, 'rb') as f:
189 input = InputSource()
190 input.setByteStream(f)
191 input.setEncoding('iso-8859-1')
192 self.check_parse(input)
193
Victor Stinneref9c0e72017-05-05 09:46:47 +0200194 def test_parse_close_source(self):
195 builtin_open = open
196 fileobj = None
197
198 def mock_open(*args):
199 nonlocal fileobj
200 fileobj = builtin_open(*args)
201 return fileobj
202
203 with mock.patch('xml.sax.saxutils.open', side_effect=mock_open):
204 make_xml_file(self.data, 'iso-8859-1', None)
205 with self.assertRaises(SAXException):
206 self.check_parse(TESTFN)
207 self.assertTrue(fileobj.closed)
208
Serhiy Storchaka13e41c52015-04-02 23:05:57 +0300209 def check_parseString(self, s):
210 from xml.sax import parseString
211 result = StringIO()
212 parseString(s, XMLGenerator(result, 'utf-8'))
213 self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8'))
214
Serhiy Storchaka778db282015-04-04 10:12:26 +0300215 def test_parseString_text(self):
216 encodings = ('us-ascii', 'iso-8859-1', 'utf-8',
217 'utf-16', 'utf-16le', 'utf-16be')
218 for encoding in encodings:
219 self.check_parseString(xml_str(self.data, encoding))
220 self.check_parseString(self.data)
221
Serhiy Storchaka13e41c52015-04-02 23:05:57 +0300222 def test_parseString_bytes(self):
223 # UTF-8 is default encoding, US-ASCII is compatible with UTF-8,
224 # UTF-16 is autodetected
225 encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be')
226 for encoding in encodings:
227 self.check_parseString(xml_bytes(self.data, encoding))
228 self.check_parseString(xml_bytes(self.data, encoding, None))
229 # accept UTF-8 with BOM
230 self.check_parseString(xml_bytes(self.data, 'utf-8-sig', 'utf-8'))
231 self.check_parseString(xml_bytes(self.data, 'utf-8-sig', None))
232 # accept data with declared encoding
233 self.check_parseString(xml_bytes(self.data, 'iso-8859-1'))
234 # fail on non-UTF-8 incompatible data without declared encoding
235 with self.assertRaises(SAXException):
236 self.check_parseString(xml_bytes(self.data, 'iso-8859-1', None))
237
Guido van Rossumd8faa362007-04-27 19:54:29 +0000238class MakeParserTest(unittest.TestCase):
239 def test_make_parser2(self):
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000240 # Creating parsers several times in a row should succeed.
241 # Testing this because there have been failures of this kind
242 # before.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000243 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000244 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000245 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000246 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000247 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000248 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000249 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000250 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000251 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000252 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000253 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000254 p = make_parser()
Tim Petersd2bf3b72001-01-18 02:22:22 +0000255
256
Lars Gustäbel96753b32000-09-24 12:24:24 +0000257# ===========================================================================
258#
259# saxutils tests
260#
261# ===========================================================================
262
Guido van Rossumd8faa362007-04-27 19:54:29 +0000263class SaxutilsTest(unittest.TestCase):
264 # ===== escape
265 def test_escape_basic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000266 self.assertEqual(escape("Donald Duck & Co"), "Donald Duck &amp; Co")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000267
Guido van Rossumd8faa362007-04-27 19:54:29 +0000268 def test_escape_all(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000269 self.assertEqual(escape("<Donald Duck & Co>"),
270 "&lt;Donald Duck &amp; Co&gt;")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000271
Guido van Rossumd8faa362007-04-27 19:54:29 +0000272 def test_escape_extra(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000273 self.assertEqual(escape("Hei på deg", {"å" : "&aring;"}),
274 "Hei p&aring; deg")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000275
Guido van Rossumd8faa362007-04-27 19:54:29 +0000276 # ===== unescape
277 def test_unescape_basic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000278 self.assertEqual(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000279
Guido van Rossumd8faa362007-04-27 19:54:29 +0000280 def test_unescape_all(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000281 self.assertEqual(unescape("&lt;Donald Duck &amp; Co&gt;"),
282 "<Donald Duck & Co>")
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000283
Guido van Rossumd8faa362007-04-27 19:54:29 +0000284 def test_unescape_extra(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000285 self.assertEqual(unescape("Hei på deg", {"å" : "&aring;"}),
286 "Hei p&aring; deg")
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000287
Guido van Rossumd8faa362007-04-27 19:54:29 +0000288 def test_unescape_amp_extra(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000289 self.assertEqual(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000290
Guido van Rossumd8faa362007-04-27 19:54:29 +0000291 # ===== quoteattr
292 def test_quoteattr_basic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000293 self.assertEqual(quoteattr("Donald Duck & Co"),
294 '"Donald Duck &amp; Co"')
Martin v. Löwis74b51ac2002-10-26 14:50:45 +0000295
Guido van Rossumd8faa362007-04-27 19:54:29 +0000296 def test_single_quoteattr(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000297 self.assertEqual(quoteattr('Includes "double" quotes'),
298 '\'Includes "double" quotes\'')
Fred Drake32f3add2002-10-28 17:58:48 +0000299
Guido van Rossumd8faa362007-04-27 19:54:29 +0000300 def test_double_quoteattr(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000301 self.assertEqual(quoteattr("Includes 'single' quotes"),
302 "\"Includes 'single' quotes\"")
Fred Drakeacd32d32001-07-19 16:10:15 +0000303
Guido van Rossumd8faa362007-04-27 19:54:29 +0000304 def test_single_double_quoteattr(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000305 self.assertEqual(quoteattr("Includes 'single' and \"double\" quotes"),
306 "\"Includes 'single' and &quot;double&quot; quotes\"")
Fred Drakeacd32d32001-07-19 16:10:15 +0000307
Guido van Rossumd8faa362007-04-27 19:54:29 +0000308 # ===== make_parser
309 def test_make_parser(self):
Martin v. Löwis962c9e72000-10-06 17:41:52 +0000310 # Creating a parser should succeed - it should fall back
311 # to the expatreader
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000312 p = make_parser(['xml.parsers.no_such_parser'])
Martin v. Löwis962c9e72000-10-06 17:41:52 +0000313
314
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300315class PrepareInputSourceTest(unittest.TestCase):
316
317 def setUp(self):
318 self.file = support.TESTFN
319 with open(self.file, "w") as tmp:
320 tmp.write("This was read from a file.")
321
322 def tearDown(self):
323 support.unlink(self.file)
324
325 def make_byte_stream(self):
326 return BytesIO(b"This is a byte stream.")
327
Serhiy Storchaka61de0872015-04-02 21:00:13 +0300328 def make_character_stream(self):
329 return StringIO("This is a character stream.")
330
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300331 def checkContent(self, stream, content):
332 self.assertIsNotNone(stream)
333 self.assertEqual(stream.read(), content)
334 stream.close()
335
336
Serhiy Storchaka61de0872015-04-02 21:00:13 +0300337 def test_character_stream(self):
338 # If the source is an InputSource with a character stream, use it.
339 src = InputSource(self.file)
340 src.setCharacterStream(self.make_character_stream())
341 prep = prepare_input_source(src)
342 self.assertIsNone(prep.getByteStream())
343 self.checkContent(prep.getCharacterStream(),
344 "This is a character stream.")
345
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300346 def test_byte_stream(self):
347 # If the source is an InputSource that does not have a character
348 # stream but does have a byte stream, use the byte stream.
349 src = InputSource(self.file)
350 src.setByteStream(self.make_byte_stream())
351 prep = prepare_input_source(src)
352 self.assertIsNone(prep.getCharacterStream())
353 self.checkContent(prep.getByteStream(),
354 b"This is a byte stream.")
355
356 def test_system_id(self):
357 # If the source is an InputSource that has neither a character
358 # stream nor a byte stream, open the system ID.
359 src = InputSource(self.file)
360 prep = prepare_input_source(src)
361 self.assertIsNone(prep.getCharacterStream())
362 self.checkContent(prep.getByteStream(),
363 b"This was read from a file.")
364
365 def test_string(self):
366 # If the source is a string, use it as a system ID and open it.
367 prep = prepare_input_source(self.file)
368 self.assertIsNone(prep.getCharacterStream())
369 self.checkContent(prep.getByteStream(),
370 b"This was read from a file.")
371
372 def test_binary_file(self):
373 # If the source is a binary file-like object, use it as a byte
374 # stream.
375 prep = prepare_input_source(self.make_byte_stream())
376 self.assertIsNone(prep.getCharacterStream())
377 self.checkContent(prep.getByteStream(),
378 b"This is a byte stream.")
379
Serhiy Storchaka61de0872015-04-02 21:00:13 +0300380 def test_text_file(self):
381 # If the source is a text file-like object, use it as a character
382 # stream.
383 prep = prepare_input_source(self.make_character_stream())
384 self.assertIsNone(prep.getByteStream())
385 self.checkContent(prep.getCharacterStream(),
386 "This is a character stream.")
387
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300388
Lars Gustäbel96753b32000-09-24 12:24:24 +0000389# ===== XMLGenerator
390
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200391class XmlgenTest:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000392 def test_xmlgen_basic(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200393 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000394 gen = XMLGenerator(result)
395 gen.startDocument()
396 gen.startElement("doc", {})
397 gen.endElement("doc")
398 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000399
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200400 self.assertEqual(result.getvalue(), self.xml("<doc></doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000401
R. David Murraya90032a2010-10-17 22:46:45 +0000402 def test_xmlgen_basic_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200403 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000404 gen = XMLGenerator(result, short_empty_elements=True)
405 gen.startDocument()
406 gen.startElement("doc", {})
407 gen.endElement("doc")
408 gen.endDocument()
409
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200410 self.assertEqual(result.getvalue(), self.xml("<doc/>"))
R. David Murraya90032a2010-10-17 22:46:45 +0000411
Guido van Rossumd8faa362007-04-27 19:54:29 +0000412 def test_xmlgen_content(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200413 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000414 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000415
Guido van Rossumd8faa362007-04-27 19:54:29 +0000416 gen.startDocument()
417 gen.startElement("doc", {})
418 gen.characters("huhei")
419 gen.endElement("doc")
420 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000421
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200422 self.assertEqual(result.getvalue(), self.xml("<doc>huhei</doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000423
R. David Murraya90032a2010-10-17 22:46:45 +0000424 def test_xmlgen_content_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200425 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000426 gen = XMLGenerator(result, short_empty_elements=True)
427
428 gen.startDocument()
429 gen.startElement("doc", {})
430 gen.characters("huhei")
431 gen.endElement("doc")
432 gen.endDocument()
433
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200434 self.assertEqual(result.getvalue(), self.xml("<doc>huhei</doc>"))
R. David Murraya90032a2010-10-17 22:46:45 +0000435
Guido van Rossumd8faa362007-04-27 19:54:29 +0000436 def test_xmlgen_pi(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200437 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000438 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000439
Guido van Rossumd8faa362007-04-27 19:54:29 +0000440 gen.startDocument()
441 gen.processingInstruction("test", "data")
442 gen.startElement("doc", {})
443 gen.endElement("doc")
444 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000445
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200446 self.assertEqual(result.getvalue(),
447 self.xml("<?test data?><doc></doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000448
Guido van Rossumd8faa362007-04-27 19:54:29 +0000449 def test_xmlgen_content_escape(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200450 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000451 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000452
Guido van Rossumd8faa362007-04-27 19:54:29 +0000453 gen.startDocument()
454 gen.startElement("doc", {})
455 gen.characters("<huhei&")
456 gen.endElement("doc")
457 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000458
Ezio Melottib3aedd42010-11-20 19:04:17 +0000459 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200460 self.xml("<doc>&lt;huhei&amp;</doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000461
Guido van Rossumd8faa362007-04-27 19:54:29 +0000462 def test_xmlgen_attr_escape(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200463 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000464 gen = XMLGenerator(result)
Fred Drakec9fadf92001-08-07 19:17:06 +0000465
Guido van Rossumd8faa362007-04-27 19:54:29 +0000466 gen.startDocument()
467 gen.startElement("doc", {"a": '"'})
468 gen.startElement("e", {"a": "'"})
469 gen.endElement("e")
470 gen.startElement("e", {"a": "'\""})
471 gen.endElement("e")
472 gen.startElement("e", {"a": "\n\r\t"})
473 gen.endElement("e")
474 gen.endElement("doc")
475 gen.endDocument()
Fred Drakec9fadf92001-08-07 19:17:06 +0000476
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200477 self.assertEqual(result.getvalue(), self.xml(
478 "<doc a='\"'><e a=\"'\"></e>"
479 "<e a=\"'&quot;\"></e>"
480 "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
481
482 def test_xmlgen_encoding(self):
483 encodings = ('iso-8859-15', 'utf-8', 'utf-8-sig',
484 'utf-16', 'utf-16be', 'utf-16le',
485 'utf-32', 'utf-32be', 'utf-32le')
486 for encoding in encodings:
487 result = self.ioclass()
488 gen = XMLGenerator(result, encoding=encoding)
489
490 gen.startDocument()
491 gen.startElement("doc", {"a": '\u20ac'})
492 gen.characters("\u20ac")
493 gen.endElement("doc")
494 gen.endDocument()
495
496 self.assertEqual(result.getvalue(),
497 self.xml('<doc a="\u20ac">\u20ac</doc>', encoding=encoding))
498
499 def test_xmlgen_unencodable(self):
500 result = self.ioclass()
501 gen = XMLGenerator(result, encoding='ascii')
502
503 gen.startDocument()
504 gen.startElement("doc", {"a": '\u20ac'})
505 gen.characters("\u20ac")
506 gen.endElement("doc")
507 gen.endDocument()
508
509 self.assertEqual(result.getvalue(),
510 self.xml('<doc a="&#8364;">&#8364;</doc>', encoding='ascii'))
Fred Drakec9fadf92001-08-07 19:17:06 +0000511
Guido van Rossumd8faa362007-04-27 19:54:29 +0000512 def test_xmlgen_ignorable(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200513 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000514 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000515
Guido van Rossumd8faa362007-04-27 19:54:29 +0000516 gen.startDocument()
517 gen.startElement("doc", {})
518 gen.ignorableWhitespace(" ")
519 gen.endElement("doc")
520 gen.endDocument()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000521
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200522 self.assertEqual(result.getvalue(), self.xml("<doc> </doc>"))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000523
R. David Murraya90032a2010-10-17 22:46:45 +0000524 def test_xmlgen_ignorable_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200525 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000526 gen = XMLGenerator(result, short_empty_elements=True)
527
528 gen.startDocument()
529 gen.startElement("doc", {})
530 gen.ignorableWhitespace(" ")
531 gen.endElement("doc")
532 gen.endDocument()
533
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200534 self.assertEqual(result.getvalue(), self.xml("<doc> </doc>"))
R. David Murraya90032a2010-10-17 22:46:45 +0000535
Serhiy Storchaka3eab6b32013-05-12 17:31:16 +0300536 def test_xmlgen_encoding_bytes(self):
537 encodings = ('iso-8859-15', 'utf-8', 'utf-8-sig',
538 'utf-16', 'utf-16be', 'utf-16le',
539 'utf-32', 'utf-32be', 'utf-32le')
540 for encoding in encodings:
541 result = self.ioclass()
542 gen = XMLGenerator(result, encoding=encoding)
543
544 gen.startDocument()
545 gen.startElement("doc", {"a": '\u20ac'})
546 gen.characters("\u20ac".encode(encoding))
547 gen.ignorableWhitespace(" ".encode(encoding))
548 gen.endElement("doc")
549 gen.endDocument()
550
551 self.assertEqual(result.getvalue(),
552 self.xml('<doc a="\u20ac">\u20ac </doc>', encoding=encoding))
553
Guido van Rossumd8faa362007-04-27 19:54:29 +0000554 def test_xmlgen_ns(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200555 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000556 gen = XMLGenerator(result)
Lars Gustäbel96753b32000-09-24 12:24:24 +0000557
Guido van Rossumd8faa362007-04-27 19:54:29 +0000558 gen.startDocument()
559 gen.startPrefixMapping("ns1", ns_uri)
560 gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
561 # add an unqualified name
562 gen.startElementNS((None, "udoc"), None, {})
563 gen.endElementNS((None, "udoc"), None)
564 gen.endElementNS((ns_uri, "doc"), "ns1:doc")
565 gen.endPrefixMapping("ns1")
566 gen.endDocument()
Fred Drake004d5e62000-10-23 17:22:08 +0000567
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200568 self.assertEqual(result.getvalue(), self.xml(
569 '<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
Guido van Rossumd8faa362007-04-27 19:54:29 +0000570 ns_uri))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000571
R. David Murraya90032a2010-10-17 22:46:45 +0000572 def test_xmlgen_ns_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200573 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000574 gen = XMLGenerator(result, short_empty_elements=True)
575
576 gen.startDocument()
577 gen.startPrefixMapping("ns1", ns_uri)
578 gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
579 # add an unqualified name
580 gen.startElementNS((None, "udoc"), None, {})
581 gen.endElementNS((None, "udoc"), None)
582 gen.endElementNS((ns_uri, "doc"), "ns1:doc")
583 gen.endPrefixMapping("ns1")
584 gen.endDocument()
585
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200586 self.assertEqual(result.getvalue(), self.xml(
587 '<ns1:doc xmlns:ns1="%s"><udoc/></ns1:doc>' %
R. David Murraya90032a2010-10-17 22:46:45 +0000588 ns_uri))
589
Guido van Rossumd8faa362007-04-27 19:54:29 +0000590 def test_1463026_1(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200591 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000592 gen = XMLGenerator(result)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000593
Guido van Rossumd8faa362007-04-27 19:54:29 +0000594 gen.startDocument()
595 gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
596 gen.endElementNS((None, 'a'), 'a')
597 gen.endDocument()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000598
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200599 self.assertEqual(result.getvalue(), self.xml('<a b="c"></a>'))
Thomas Wouterscf297e42007-02-23 15:07:44 +0000600
R. David Murraya90032a2010-10-17 22:46:45 +0000601 def test_1463026_1_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200602 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000603 gen = XMLGenerator(result, short_empty_elements=True)
604
605 gen.startDocument()
606 gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
607 gen.endElementNS((None, 'a'), 'a')
608 gen.endDocument()
609
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200610 self.assertEqual(result.getvalue(), self.xml('<a b="c"/>'))
R. David Murraya90032a2010-10-17 22:46:45 +0000611
Guido van Rossumd8faa362007-04-27 19:54:29 +0000612 def test_1463026_2(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200613 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000614 gen = XMLGenerator(result)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000615
Guido van Rossumd8faa362007-04-27 19:54:29 +0000616 gen.startDocument()
617 gen.startPrefixMapping(None, 'qux')
618 gen.startElementNS(('qux', 'a'), 'a', {})
619 gen.endElementNS(('qux', 'a'), 'a')
620 gen.endPrefixMapping(None)
621 gen.endDocument()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000622
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200623 self.assertEqual(result.getvalue(), self.xml('<a xmlns="qux"></a>'))
Thomas Wouterscf297e42007-02-23 15:07:44 +0000624
R. David Murraya90032a2010-10-17 22:46:45 +0000625 def test_1463026_2_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200626 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000627 gen = XMLGenerator(result, short_empty_elements=True)
628
629 gen.startDocument()
630 gen.startPrefixMapping(None, 'qux')
631 gen.startElementNS(('qux', 'a'), 'a', {})
632 gen.endElementNS(('qux', 'a'), 'a')
633 gen.endPrefixMapping(None)
634 gen.endDocument()
635
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200636 self.assertEqual(result.getvalue(), self.xml('<a xmlns="qux"/>'))
R. David Murraya90032a2010-10-17 22:46:45 +0000637
Guido van Rossumd8faa362007-04-27 19:54:29 +0000638 def test_1463026_3(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200639 result = self.ioclass()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000640 gen = XMLGenerator(result)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000641
Guido van Rossumd8faa362007-04-27 19:54:29 +0000642 gen.startDocument()
643 gen.startPrefixMapping('my', 'qux')
644 gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
645 gen.endElementNS(('qux', 'a'), 'a')
646 gen.endPrefixMapping('my')
647 gen.endDocument()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000648
Ezio Melottib3aedd42010-11-20 19:04:17 +0000649 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200650 self.xml('<my:a xmlns:my="qux" b="c"></my:a>'))
Lars Gustäbel96753b32000-09-24 12:24:24 +0000651
R. David Murraya90032a2010-10-17 22:46:45 +0000652 def test_1463026_3_empty(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200653 result = self.ioclass()
R. David Murraya90032a2010-10-17 22:46:45 +0000654 gen = XMLGenerator(result, short_empty_elements=True)
655
656 gen.startDocument()
657 gen.startPrefixMapping('my', 'qux')
658 gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
659 gen.endElementNS(('qux', 'a'), 'a')
660 gen.endPrefixMapping('my')
661 gen.endDocument()
662
Ezio Melottib3aedd42010-11-20 19:04:17 +0000663 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200664 self.xml('<my:a xmlns:my="qux" b="c"/>'))
R. David Murraya90032a2010-10-17 22:46:45 +0000665
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000666 def test_5027_1(self):
667 # The xml prefix (as in xml:lang below) is reserved and bound by
668 # definition to http://www.w3.org/XML/1998/namespace. XMLGenerator had
Andrew Svetlov737fb892012-12-18 21:14:22 +0200669 # a bug whereby a KeyError is raised because this namespace is missing
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000670 # from a dictionary.
671 #
672 # This test demonstrates the bug by parsing a document.
673 test_xml = StringIO(
674 '<?xml version="1.0"?>'
675 '<a:g1 xmlns:a="http://example.com/ns">'
676 '<a:g2 xml:lang="en">Hello</a:g2>'
677 '</a:g1>')
678
679 parser = make_parser()
680 parser.setFeature(feature_namespaces, True)
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200681 result = self.ioclass()
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000682 gen = XMLGenerator(result)
683 parser.setContentHandler(gen)
684 parser.parse(test_xml)
685
Ezio Melottib3aedd42010-11-20 19:04:17 +0000686 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200687 self.xml(
Ezio Melottib3aedd42010-11-20 19:04:17 +0000688 '<a:g1 xmlns:a="http://example.com/ns">'
689 '<a:g2 xml:lang="en">Hello</a:g2>'
690 '</a:g1>'))
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000691
692 def test_5027_2(self):
693 # The xml prefix (as in xml:lang below) is reserved and bound by
694 # definition to http://www.w3.org/XML/1998/namespace. XMLGenerator had
Andrew Svetlov737fb892012-12-18 21:14:22 +0200695 # a bug whereby a KeyError is raised because this namespace is missing
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000696 # from a dictionary.
697 #
698 # This test demonstrates the bug by direct manipulation of the
699 # XMLGenerator.
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200700 result = self.ioclass()
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000701 gen = XMLGenerator(result)
702
703 gen.startDocument()
704 gen.startPrefixMapping('a', 'http://example.com/ns')
705 gen.startElementNS(('http://example.com/ns', 'g1'), 'g1', {})
706 lang_attr = {('http://www.w3.org/XML/1998/namespace', 'lang'): 'en'}
707 gen.startElementNS(('http://example.com/ns', 'g2'), 'g2', lang_attr)
708 gen.characters('Hello')
709 gen.endElementNS(('http://example.com/ns', 'g2'), 'g2')
710 gen.endElementNS(('http://example.com/ns', 'g1'), 'g1')
711 gen.endPrefixMapping('a')
712 gen.endDocument()
713
Ezio Melottib3aedd42010-11-20 19:04:17 +0000714 self.assertEqual(result.getvalue(),
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200715 self.xml(
Ezio Melottib3aedd42010-11-20 19:04:17 +0000716 '<a:g1 xmlns:a="http://example.com/ns">'
717 '<a:g2 xml:lang="en">Hello</a:g2>'
718 '</a:g1>'))
Antoine Pitrou6b03ee62010-10-27 18:33:30 +0000719
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200720 def test_no_close_file(self):
721 result = self.ioclass()
722 def func(out):
723 gen = XMLGenerator(out)
724 gen.startDocument()
725 gen.startElement("doc", {})
726 func(result)
727 self.assertFalse(result.closed)
728
Serhiy Storchakaa5f13d22013-02-25 13:46:10 +0200729 def test_xmlgen_fragment(self):
730 result = self.ioclass()
731 gen = XMLGenerator(result)
732
733 # Don't call gen.startDocument()
734 gen.startElement("foo", {"a": "1.0"})
735 gen.characters("Hello")
736 gen.endElement("foo")
737 gen.startElement("bar", {"b": "2.0"})
738 gen.endElement("bar")
739 # Don't call gen.endDocument()
740
741 self.assertEqual(result.getvalue(),
742 self.xml('<foo a="1.0">Hello</foo><bar b="2.0"></bar>')[len(self.xml('')):])
743
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200744class StringXmlgenTest(XmlgenTest, unittest.TestCase):
745 ioclass = StringIO
746
747 def xml(self, doc, encoding='iso-8859-1'):
748 return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, doc)
749
750 test_xmlgen_unencodable = None
751
752class BytesXmlgenTest(XmlgenTest, unittest.TestCase):
753 ioclass = BytesIO
754
755 def xml(self, doc, encoding='iso-8859-1'):
756 return ('<?xml version="1.0" encoding="%s"?>\n%s' %
757 (encoding, doc)).encode(encoding, 'xmlcharrefreplace')
758
759class WriterXmlgenTest(BytesXmlgenTest):
760 class ioclass(list):
761 write = list.append
762 closed = False
763
764 def seekable(self):
765 return True
766
767 def tell(self):
768 # return 0 at start and not 0 after start
769 return len(self)
770
771 def getvalue(self):
772 return b''.join(self)
773
Georg Brandlc502df42013-05-12 11:41:12 +0200774class StreamWriterXmlgenTest(XmlgenTest, unittest.TestCase):
775 def ioclass(self):
776 raw = BytesIO()
777 writer = codecs.getwriter('ascii')(raw, 'xmlcharrefreplace')
778 writer.getvalue = raw.getvalue
779 return writer
780
781 def xml(self, doc, encoding='iso-8859-1'):
782 return ('<?xml version="1.0" encoding="%s"?>\n%s' %
783 (encoding, doc)).encode('ascii', 'xmlcharrefreplace')
784
785class StreamReaderWriterXmlgenTest(XmlgenTest, unittest.TestCase):
786 fname = support.TESTFN + '-codecs'
787
788 def ioclass(self):
789 writer = codecs.open(self.fname, 'w', encoding='ascii',
790 errors='xmlcharrefreplace', buffering=0)
Antoine Pitrou2adb6fe2013-05-13 22:34:21 +0200791 def cleanup():
792 writer.close()
793 support.unlink(self.fname)
794 self.addCleanup(cleanup)
Richard Oudkerk90a24272013-05-18 18:11:30 +0100795 def getvalue():
796 # Windows will not let use reopen without first closing
797 writer.close()
798 with open(writer.name, 'rb') as f:
799 return f.read()
800 writer.getvalue = getvalue
Georg Brandlc502df42013-05-12 11:41:12 +0200801 return writer
802
Georg Brandlc502df42013-05-12 11:41:12 +0200803 def xml(self, doc, encoding='iso-8859-1'):
804 return ('<?xml version="1.0" encoding="%s"?>\n%s' %
805 (encoding, doc)).encode('ascii', 'xmlcharrefreplace')
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200806
807start = b'<?xml version="1.0" encoding="iso-8859-1"?>\n'
808
Fred Drake004d5e62000-10-23 17:22:08 +0000809
Guido van Rossumd8faa362007-04-27 19:54:29 +0000810class XMLFilterBaseTest(unittest.TestCase):
811 def test_filter_basic(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200812 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000813 gen = XMLGenerator(result)
814 filter = XMLFilterBase()
815 filter.setContentHandler(gen)
Lars Gustäbel96753b32000-09-24 12:24:24 +0000816
Guido van Rossumd8faa362007-04-27 19:54:29 +0000817 filter.startDocument()
818 filter.startElement("doc", {})
819 filter.characters("content")
820 filter.ignorableWhitespace(" ")
821 filter.endElement("doc")
822 filter.endDocument()
823
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200824 self.assertEqual(result.getvalue(), start + b"<doc>content </doc>")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000825
826# ===========================================================================
827#
828# expatreader tests
829#
830# ===========================================================================
831
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200832with open(TEST_XMLFILE_OUT, 'rb') as f:
Benjamin Petersond5df36d2010-10-31 18:23:23 +0000833 xml_test_out = f.read()
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000834
Guido van Rossumd8faa362007-04-27 19:54:29 +0000835class ExpatReaderTest(XmlTestBase):
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000836
Guido van Rossumd8faa362007-04-27 19:54:29 +0000837 # ===== XMLReader support
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000838
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300839 def test_expat_binary_file(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000840 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200841 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000842 xmlgen = XMLGenerator(result)
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000843
Guido van Rossumd8faa362007-04-27 19:54:29 +0000844 parser.setContentHandler(xmlgen)
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200845 with open(TEST_XMLFILE, 'rb') as f:
Benjamin Petersond5df36d2010-10-31 18:23:23 +0000846 parser.parse(f)
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000847
Ezio Melottib3aedd42010-11-20 19:04:17 +0000848 self.assertEqual(result.getvalue(), xml_test_out)
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000849
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300850 def test_expat_text_file(self):
851 parser = create_parser()
852 result = BytesIO()
853 xmlgen = XMLGenerator(result)
854
855 parser.setContentHandler(xmlgen)
856 with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f:
857 parser.parse(f)
858
859 self.assertEqual(result.getvalue(), xml_test_out)
860
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +0200861 @requires_nonascii_filenames
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300862 def test_expat_binary_file_nonascii(self):
Serhiy Storchakad5202392013-02-02 10:31:17 +0200863 fname = support.TESTFN_UNICODE
864 shutil.copyfile(TEST_XMLFILE, fname)
865 self.addCleanup(support.unlink, fname)
866
867 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200868 result = BytesIO()
Serhiy Storchakad5202392013-02-02 10:31:17 +0200869 xmlgen = XMLGenerator(result)
870
871 parser.setContentHandler(xmlgen)
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +0300872 parser.parse(open(fname, 'rb'))
Serhiy Storchakad5202392013-02-02 10:31:17 +0200873
874 self.assertEqual(result.getvalue(), xml_test_out)
875
Serhiy Storchakafc8e9b02014-11-27 22:13:16 +0200876 def test_expat_binary_file_bytes_name(self):
877 fname = os.fsencode(TEST_XMLFILE)
878 parser = create_parser()
879 result = BytesIO()
880 xmlgen = XMLGenerator(result)
881
882 parser.setContentHandler(xmlgen)
883 with open(fname, 'rb') as f:
884 parser.parse(f)
885
886 self.assertEqual(result.getvalue(), xml_test_out)
887
888 def test_expat_binary_file_int_name(self):
889 parser = create_parser()
890 result = BytesIO()
891 xmlgen = XMLGenerator(result)
892
893 parser.setContentHandler(xmlgen)
894 with open(TEST_XMLFILE, 'rb') as f:
895 with open(f.fileno(), 'rb', closefd=False) as f2:
896 parser.parse(f2)
897
898 self.assertEqual(result.getvalue(), xml_test_out)
899
Guido van Rossumd8faa362007-04-27 19:54:29 +0000900 # ===== DTDHandler support
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000901
Guido van Rossumd8faa362007-04-27 19:54:29 +0000902 class TestDTDHandler:
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000903
Guido van Rossumd8faa362007-04-27 19:54:29 +0000904 def __init__(self):
905 self._notations = []
906 self._entities = []
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000907
Guido van Rossumd8faa362007-04-27 19:54:29 +0000908 def notationDecl(self, name, publicId, systemId):
909 self._notations.append((name, publicId, systemId))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000910
Guido van Rossumd8faa362007-04-27 19:54:29 +0000911 def unparsedEntityDecl(self, name, publicId, systemId, ndata):
912 self._entities.append((name, publicId, systemId, ndata))
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000913
Guido van Rossumd8faa362007-04-27 19:54:29 +0000914 def test_expat_dtdhandler(self):
915 parser = create_parser()
916 handler = self.TestDTDHandler()
917 parser.setDTDHandler(handler)
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000918
Guido van Rossumd8faa362007-04-27 19:54:29 +0000919 parser.feed('<!DOCTYPE doc [\n')
920 parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
921 parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
922 parser.feed(']>\n')
923 parser.feed('<doc></doc>')
924 parser.close()
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000925
Ezio Melottib3aedd42010-11-20 19:04:17 +0000926 self.assertEqual(handler._notations,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927 [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
Ezio Melottib3aedd42010-11-20 19:04:17 +0000928 self.assertEqual(handler._entities, [("img", None, "expat.gif", "GIF")])
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000929
Guido van Rossumd8faa362007-04-27 19:54:29 +0000930 # ===== EntityResolver support
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000931
Guido van Rossumd8faa362007-04-27 19:54:29 +0000932 class TestEntityResolver:
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000933
Guido van Rossumd8faa362007-04-27 19:54:29 +0000934 def resolveEntity(self, publicId, systemId):
935 inpsrc = InputSource()
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200936 inpsrc.setByteStream(BytesIO(b"<entity/>"))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000937 return inpsrc
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000938
Guido van Rossumd8faa362007-04-27 19:54:29 +0000939 def test_expat_entityresolver(self):
940 parser = create_parser()
941 parser.setEntityResolver(self.TestEntityResolver())
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200942 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000943 parser.setContentHandler(XMLGenerator(result))
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000944
Guido van Rossumd8faa362007-04-27 19:54:29 +0000945 parser.feed('<!DOCTYPE doc [\n')
946 parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
947 parser.feed(']>\n')
948 parser.feed('<doc>&test;</doc>')
949 parser.close()
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000950
Ezio Melottib3aedd42010-11-20 19:04:17 +0000951 self.assertEqual(result.getvalue(), start +
Serhiy Storchaka88efc522013-02-10 14:29:52 +0200952 b"<doc><entity></entity></doc>")
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000953
Guido van Rossumd8faa362007-04-27 19:54:29 +0000954 # ===== Attributes support
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000955
Guido van Rossumd8faa362007-04-27 19:54:29 +0000956 class AttrGatherer(ContentHandler):
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000957
Guido van Rossumd8faa362007-04-27 19:54:29 +0000958 def startElement(self, name, attrs):
959 self._attrs = attrs
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000960
Guido van Rossumd8faa362007-04-27 19:54:29 +0000961 def startElementNS(self, name, qname, attrs):
962 self._attrs = attrs
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000963
Guido van Rossumd8faa362007-04-27 19:54:29 +0000964 def test_expat_attrs_empty(self):
965 parser = create_parser()
966 gather = self.AttrGatherer()
967 parser.setContentHandler(gather)
968
969 parser.feed("<doc/>")
970 parser.close()
971
972 self.verify_empty_attrs(gather._attrs)
973
974 def test_expat_attrs_wattr(self):
975 parser = create_parser()
976 gather = self.AttrGatherer()
977 parser.setContentHandler(gather)
978
979 parser.feed("<doc attr='val'/>")
980 parser.close()
981
982 self.verify_attrs_wattr(gather._attrs)
983
984 def test_expat_nsattrs_empty(self):
985 parser = create_parser(1)
986 gather = self.AttrGatherer()
987 parser.setContentHandler(gather)
988
989 parser.feed("<doc/>")
990 parser.close()
991
992 self.verify_empty_nsattrs(gather._attrs)
993
994 def test_expat_nsattrs_wattr(self):
995 parser = create_parser(1)
996 gather = self.AttrGatherer()
997 parser.setContentHandler(gather)
998
999 parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
1000 parser.close()
1001
1002 attrs = gather._attrs
1003
Ezio Melottib3aedd42010-11-20 19:04:17 +00001004 self.assertEqual(attrs.getLength(), 1)
1005 self.assertEqual(attrs.getNames(), [(ns_uri, "attr")])
Guido van Rossumd8faa362007-04-27 19:54:29 +00001006 self.assertTrue((attrs.getQNames() == [] or
1007 attrs.getQNames() == ["ns:attr"]))
Ezio Melottib3aedd42010-11-20 19:04:17 +00001008 self.assertEqual(len(attrs), 1)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001009 self.assertIn((ns_uri, "attr"), attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001010 self.assertEqual(attrs.get((ns_uri, "attr")), "val")
1011 self.assertEqual(attrs.get((ns_uri, "attr"), 25), "val")
1012 self.assertEqual(list(attrs.items()), [((ns_uri, "attr"), "val")])
1013 self.assertEqual(list(attrs.values()), ["val"])
1014 self.assertEqual(attrs.getValue((ns_uri, "attr")), "val")
1015 self.assertEqual(attrs[(ns_uri, "attr")], "val")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001016
1017 # ===== InputSource support
1018
Benjamin Petersona7f4f5a2008-09-04 02:22:52 +00001019 def test_expat_inpsource_filename(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001020 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001021 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001022 xmlgen = XMLGenerator(result)
1023
1024 parser.setContentHandler(xmlgen)
Florent Xiclunaf15351d2010-03-13 23:24:31 +00001025 parser.parse(TEST_XMLFILE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001026
Ezio Melottib3aedd42010-11-20 19:04:17 +00001027 self.assertEqual(result.getvalue(), xml_test_out)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001028
Benjamin Petersona7f4f5a2008-09-04 02:22:52 +00001029 def test_expat_inpsource_sysid(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001030 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001031 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001032 xmlgen = XMLGenerator(result)
1033
1034 parser.setContentHandler(xmlgen)
Florent Xiclunaf15351d2010-03-13 23:24:31 +00001035 parser.parse(InputSource(TEST_XMLFILE))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001036
Ezio Melottib3aedd42010-11-20 19:04:17 +00001037 self.assertEqual(result.getvalue(), xml_test_out)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001038
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +02001039 @requires_nonascii_filenames
Serhiy Storchakad5202392013-02-02 10:31:17 +02001040 def test_expat_inpsource_sysid_nonascii(self):
1041 fname = support.TESTFN_UNICODE
1042 shutil.copyfile(TEST_XMLFILE, fname)
1043 self.addCleanup(support.unlink, fname)
1044
1045 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001046 result = BytesIO()
Serhiy Storchakad5202392013-02-02 10:31:17 +02001047 xmlgen = XMLGenerator(result)
1048
1049 parser.setContentHandler(xmlgen)
1050 parser.parse(InputSource(fname))
1051
1052 self.assertEqual(result.getvalue(), xml_test_out)
1053
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +03001054 def test_expat_inpsource_byte_stream(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001055 parser = create_parser()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001056 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001057 xmlgen = XMLGenerator(result)
1058
1059 parser.setContentHandler(xmlgen)
1060 inpsrc = InputSource()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001061 with open(TEST_XMLFILE, 'rb') as f:
Benjamin Petersond5df36d2010-10-31 18:23:23 +00001062 inpsrc.setByteStream(f)
1063 parser.parse(inpsrc)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001064
Ezio Melottib3aedd42010-11-20 19:04:17 +00001065 self.assertEqual(result.getvalue(), xml_test_out)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001066
Serhiy Storchaka61de0872015-04-02 21:00:13 +03001067 def test_expat_inpsource_character_stream(self):
1068 parser = create_parser()
1069 result = BytesIO()
1070 xmlgen = XMLGenerator(result)
1071
1072 parser.setContentHandler(xmlgen)
1073 inpsrc = InputSource()
1074 with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f:
1075 inpsrc.setCharacterStream(f)
1076 parser.parse(inpsrc)
1077
1078 self.assertEqual(result.getvalue(), xml_test_out)
1079
Guido van Rossumd8faa362007-04-27 19:54:29 +00001080 # ===== IncrementalParser support
1081
1082 def test_expat_incremental(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("</doc>")
1090 parser.close()
1091
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001092 self.assertEqual(result.getvalue(), start + b"<doc></doc>")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001093
1094 def test_expat_incremental_reset(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001095 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001096 xmlgen = XMLGenerator(result)
1097 parser = create_parser()
1098 parser.setContentHandler(xmlgen)
1099
1100 parser.feed("<doc>")
1101 parser.feed("text")
1102
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001103 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001104 xmlgen = XMLGenerator(result)
1105 parser.setContentHandler(xmlgen)
1106 parser.reset()
1107
1108 parser.feed("<doc>")
1109 parser.feed("text")
1110 parser.feed("</doc>")
1111 parser.close()
1112
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001113 self.assertEqual(result.getvalue(), start + b"<doc>text</doc>")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001114
1115 # ===== Locator support
1116
1117 def test_expat_locator_noinfo(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001118 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001119 xmlgen = XMLGenerator(result)
1120 parser = create_parser()
1121 parser.setContentHandler(xmlgen)
1122
1123 parser.feed("<doc>")
1124 parser.feed("</doc>")
1125 parser.close()
1126
Ezio Melottib3aedd42010-11-20 19:04:17 +00001127 self.assertEqual(parser.getSystemId(), None)
1128 self.assertEqual(parser.getPublicId(), None)
1129 self.assertEqual(parser.getLineNumber(), 1)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001130
Benjamin Petersona7f4f5a2008-09-04 02:22:52 +00001131 def test_expat_locator_withinfo(self):
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001132 result = BytesIO()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001133 xmlgen = XMLGenerator(result)
1134 parser = create_parser()
1135 parser.setContentHandler(xmlgen)
Florent Xiclunaf15351d2010-03-13 23:24:31 +00001136 parser.parse(TEST_XMLFILE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001137
Ezio Melottib3aedd42010-11-20 19:04:17 +00001138 self.assertEqual(parser.getSystemId(), TEST_XMLFILE)
1139 self.assertEqual(parser.getPublicId(), None)
Lars Gustäbel2fc52942000-10-24 15:35:07 +00001140
Serhiy Storchaka1a4ed4c2013-02-02 12:17:05 +02001141 @requires_nonascii_filenames
Serhiy Storchakad5202392013-02-02 10:31:17 +02001142 def test_expat_locator_withinfo_nonascii(self):
1143 fname = support.TESTFN_UNICODE
1144 shutil.copyfile(TEST_XMLFILE, fname)
1145 self.addCleanup(support.unlink, fname)
1146
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001147 result = BytesIO()
Serhiy Storchakad5202392013-02-02 10:31:17 +02001148 xmlgen = XMLGenerator(result)
1149 parser = create_parser()
1150 parser.setContentHandler(xmlgen)
1151 parser.parse(fname)
1152
1153 self.assertEqual(parser.getSystemId(), fname)
1154 self.assertEqual(parser.getPublicId(), None)
1155
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001156
1157# ===========================================================================
1158#
1159# error reporting
1160#
1161# ===========================================================================
1162
Guido van Rossumd8faa362007-04-27 19:54:29 +00001163class ErrorReportingTest(unittest.TestCase):
1164 def test_expat_inpsource_location(self):
1165 parser = create_parser()
1166 parser.setContentHandler(ContentHandler()) # do nothing
1167 source = InputSource()
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001168 source.setByteStream(BytesIO(b"<foo bar foobar>")) #ill-formed
Guido van Rossumd8faa362007-04-27 19:54:29 +00001169 name = "a file name"
1170 source.setSystemId(name)
1171 try:
1172 parser.parse(source)
1173 self.fail()
1174 except SAXException as e:
Ezio Melottib3aedd42010-11-20 19:04:17 +00001175 self.assertEqual(e.getSystemId(), name)
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001176
Guido van Rossumd8faa362007-04-27 19:54:29 +00001177 def test_expat_incomplete(self):
1178 parser = create_parser()
1179 parser.setContentHandler(ContentHandler()) # do nothing
1180 self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
Serhiy Storchakaab914782015-05-06 09:36:06 +03001181 self.assertEqual(parser.getColumnNumber(), 5)
1182 self.assertEqual(parser.getLineNumber(), 1)
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001183
Guido van Rossumd8faa362007-04-27 19:54:29 +00001184 def test_sax_parse_exception_str(self):
1185 # pass various values from a locator to the SAXParseException to
1186 # make sure that the __str__() doesn't fall apart when None is
1187 # passed instead of an integer line and column number
1188 #
1189 # use "normal" values for the locator:
1190 str(SAXParseException("message", None,
1191 self.DummyLocator(1, 1)))
1192 # use None for the line number:
1193 str(SAXParseException("message", None,
1194 self.DummyLocator(None, 1)))
1195 # use None for the column number:
1196 str(SAXParseException("message", None,
1197 self.DummyLocator(1, None)))
1198 # use None for both:
1199 str(SAXParseException("message", None,
1200 self.DummyLocator(None, None)))
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001201
Guido van Rossumd8faa362007-04-27 19:54:29 +00001202 class DummyLocator:
1203 def __init__(self, lineno, colno):
1204 self._lineno = lineno
1205 self._colno = colno
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001206
Guido van Rossumd8faa362007-04-27 19:54:29 +00001207 def getPublicId(self):
1208 return "pubid"
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001209
Guido van Rossumd8faa362007-04-27 19:54:29 +00001210 def getSystemId(self):
1211 return "sysid"
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001212
Guido van Rossumd8faa362007-04-27 19:54:29 +00001213 def getLineNumber(self):
1214 return self._lineno
Fred Drake6fd0b0d2004-03-20 08:15:30 +00001215
Guido van Rossumd8faa362007-04-27 19:54:29 +00001216 def getColumnNumber(self):
1217 return self._colno
Martin v. Löwis80670bc2000-10-06 21:13:23 +00001218
Lars Gustäbelab647872000-09-24 18:40:52 +00001219# ===========================================================================
1220#
1221# xmlreader tests
1222#
1223# ===========================================================================
1224
Guido van Rossumd8faa362007-04-27 19:54:29 +00001225class XmlReaderTest(XmlTestBase):
Lars Gustäbelab647872000-09-24 18:40:52 +00001226
Guido van Rossumd8faa362007-04-27 19:54:29 +00001227 # ===== AttributesImpl
1228 def test_attrs_empty(self):
1229 self.verify_empty_attrs(AttributesImpl({}))
Lars Gustäbelab647872000-09-24 18:40:52 +00001230
Guido van Rossumd8faa362007-04-27 19:54:29 +00001231 def test_attrs_wattr(self):
1232 self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
Lars Gustäbelab647872000-09-24 18:40:52 +00001233
Guido van Rossumd8faa362007-04-27 19:54:29 +00001234 def test_nsattrs_empty(self):
1235 self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
Lars Gustäbelab647872000-09-24 18:40:52 +00001236
Guido van Rossumd8faa362007-04-27 19:54:29 +00001237 def test_nsattrs_wattr(self):
1238 attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
1239 {(ns_uri, "attr") : "ns:attr"})
Fred Drake004d5e62000-10-23 17:22:08 +00001240
Ezio Melottib3aedd42010-11-20 19:04:17 +00001241 self.assertEqual(attrs.getLength(), 1)
1242 self.assertEqual(attrs.getNames(), [(ns_uri, "attr")])
1243 self.assertEqual(attrs.getQNames(), ["ns:attr"])
1244 self.assertEqual(len(attrs), 1)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001245 self.assertIn((ns_uri, "attr"), attrs)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001246 self.assertEqual(list(attrs.keys()), [(ns_uri, "attr")])
1247 self.assertEqual(attrs.get((ns_uri, "attr")), "val")
1248 self.assertEqual(attrs.get((ns_uri, "attr"), 25), "val")
1249 self.assertEqual(list(attrs.items()), [((ns_uri, "attr"), "val")])
1250 self.assertEqual(list(attrs.values()), ["val"])
1251 self.assertEqual(attrs.getValue((ns_uri, "attr")), "val")
1252 self.assertEqual(attrs.getValueByQName("ns:attr"), "val")
1253 self.assertEqual(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
1254 self.assertEqual(attrs[(ns_uri, "attr")], "val")
1255 self.assertEqual(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
Fred Drake004d5e62000-10-23 17:22:08 +00001256
Lars Gustäbelab647872000-09-24 18:40:52 +00001257
Christian Heimesbbe741d2008-03-28 10:53:29 +00001258def test_main():
Guido van Rossumd8faa362007-04-27 19:54:29 +00001259 run_unittest(MakeParserTest,
Serhiy Storchaka13e41c52015-04-02 23:05:57 +03001260 ParseTest,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001261 SaxutilsTest,
Serhiy Storchakaaa9563c2015-04-02 20:55:59 +03001262 PrepareInputSourceTest,
Serhiy Storchaka88efc522013-02-10 14:29:52 +02001263 StringXmlgenTest,
1264 BytesXmlgenTest,
1265 WriterXmlgenTest,
Georg Brandlc502df42013-05-12 11:41:12 +02001266 StreamWriterXmlgenTest,
1267 StreamReaderWriterXmlgenTest,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001268 ExpatReaderTest,
1269 ErrorReportingTest,
1270 XmlReaderTest)
Lars Gustäbelb7536d52000-09-24 18:53:56 +00001271
Guido van Rossumd8faa362007-04-27 19:54:29 +00001272if __name__ == "__main__":
Christian Heimesbbe741d2008-03-28 10:53:29 +00001273 test_main()