move sections
[python/dscho.git] / Lib / test / test_sax.py
blobdf7daf1955b3fa13e4df7d4c633e7fa11ed6dc71
1 # regression test for SAX 2.0 -*- coding: iso-8859-1 -*-
2 # $Id$
4 from xml.sax import make_parser, ContentHandler, \
5 SAXException, SAXReaderNotAvailable, SAXParseException
6 try:
7 make_parser()
8 except SAXReaderNotAvailable:
9 # don't try to test this module if we cannot create a parser
10 raise ImportError("no XML parsers available")
11 from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
12 XMLFilterBase
13 from xml.sax.expatreader import create_parser
14 from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
15 from cStringIO import StringIO
16 from test.test_support import findfile, run_unittest
17 import unittest
19 TEST_XMLFILE = findfile("test.xml", subdir="xmltestdata")
20 TEST_XMLFILE_OUT = findfile("test.xml.out", subdir="xmltestdata")
22 ns_uri = "http://www.python.org/xml-ns/saxtest/"
24 class XmlTestBase(unittest.TestCase):
25 def verify_empty_attrs(self, attrs):
26 self.assertRaises(KeyError, attrs.getValue, "attr")
27 self.assertRaises(KeyError, attrs.getValueByQName, "attr")
28 self.assertRaises(KeyError, attrs.getNameByQName, "attr")
29 self.assertRaises(KeyError, attrs.getQNameByName, "attr")
30 self.assertRaises(KeyError, attrs.__getitem__, "attr")
31 self.assertEquals(attrs.getLength(), 0)
32 self.assertEquals(attrs.getNames(), [])
33 self.assertEquals(attrs.getQNames(), [])
34 self.assertEquals(len(attrs), 0)
35 self.assertFalse(attrs.has_key("attr"))
36 self.assertEquals(attrs.keys(), [])
37 self.assertEquals(attrs.get("attrs"), None)
38 self.assertEquals(attrs.get("attrs", 25), 25)
39 self.assertEquals(attrs.items(), [])
40 self.assertEquals(attrs.values(), [])
42 def verify_empty_nsattrs(self, attrs):
43 self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
44 self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
45 self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
46 self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
47 self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
48 self.assertEquals(attrs.getLength(), 0)
49 self.assertEquals(attrs.getNames(), [])
50 self.assertEquals(attrs.getQNames(), [])
51 self.assertEquals(len(attrs), 0)
52 self.assertFalse(attrs.has_key((ns_uri, "attr")))
53 self.assertEquals(attrs.keys(), [])
54 self.assertEquals(attrs.get((ns_uri, "attr")), None)
55 self.assertEquals(attrs.get((ns_uri, "attr"), 25), 25)
56 self.assertEquals(attrs.items(), [])
57 self.assertEquals(attrs.values(), [])
59 def verify_attrs_wattr(self, attrs):
60 self.assertEquals(attrs.getLength(), 1)
61 self.assertEquals(attrs.getNames(), ["attr"])
62 self.assertEquals(attrs.getQNames(), ["attr"])
63 self.assertEquals(len(attrs), 1)
64 self.assertTrue(attrs.has_key("attr"))
65 self.assertEquals(attrs.keys(), ["attr"])
66 self.assertEquals(attrs.get("attr"), "val")
67 self.assertEquals(attrs.get("attr", 25), "val")
68 self.assertEquals(attrs.items(), [("attr", "val")])
69 self.assertEquals(attrs.values(), ["val"])
70 self.assertEquals(attrs.getValue("attr"), "val")
71 self.assertEquals(attrs.getValueByQName("attr"), "val")
72 self.assertEquals(attrs.getNameByQName("attr"), "attr")
73 self.assertEquals(attrs["attr"], "val")
74 self.assertEquals(attrs.getQNameByName("attr"), "attr")
76 class MakeParserTest(unittest.TestCase):
77 def test_make_parser2(self):
78 # Creating parsers several times in a row should succeed.
79 # Testing this because there have been failures of this kind
80 # before.
81 from xml.sax import make_parser
82 p = make_parser()
83 from xml.sax import make_parser
84 p = make_parser()
85 from xml.sax import make_parser
86 p = make_parser()
87 from xml.sax import make_parser
88 p = make_parser()
89 from xml.sax import make_parser
90 p = make_parser()
91 from xml.sax import make_parser
92 p = make_parser()
95 # ===========================================================================
97 # saxutils tests
99 # ===========================================================================
101 class SaxutilsTest(unittest.TestCase):
102 # ===== escape
103 def test_escape_basic(self):
104 self.assertEquals(escape("Donald Duck & Co"), "Donald Duck & Co")
106 def test_escape_all(self):
107 self.assertEquals(escape("<Donald Duck & Co>"),
108 "&lt;Donald Duck &amp; Co&gt;")
110 def test_escape_extra(self):
111 self.assertEquals(escape("Hei på deg", {"å" : "&aring;"}),
112 "Hei p&aring; deg")
114 # ===== unescape
115 def test_unescape_basic(self):
116 self.assertEquals(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
118 def test_unescape_all(self):
119 self.assertEquals(unescape("&lt;Donald Duck &amp; Co&gt;"),
120 "<Donald Duck & Co>")
122 def test_unescape_extra(self):
123 self.assertEquals(unescape("Hei på deg", {"å" : "&aring;"}),
124 "Hei p&aring; deg")
126 def test_unescape_amp_extra(self):
127 self.assertEquals(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
129 # ===== quoteattr
130 def test_quoteattr_basic(self):
131 self.assertEquals(quoteattr("Donald Duck & Co"),
132 '"Donald Duck &amp; Co"')
134 def test_single_quoteattr(self):
135 self.assertEquals(quoteattr('Includes "double" quotes'),
136 '\'Includes "double" quotes\'')
138 def test_double_quoteattr(self):
139 self.assertEquals(quoteattr("Includes 'single' quotes"),
140 "\"Includes 'single' quotes\"")
142 def test_single_double_quoteattr(self):
143 self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"),
144 "\"Includes 'single' and &quot;double&quot; quotes\"")
146 # ===== make_parser
147 def test_make_parser(self):
148 # Creating a parser should succeed - it should fall back
149 # to the expatreader
150 p = make_parser(['xml.parsers.no_such_parser'])
153 # ===== XMLGenerator
155 start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
157 class XmlgenTest(unittest.TestCase):
158 def test_xmlgen_basic(self):
159 result = StringIO()
160 gen = XMLGenerator(result)
161 gen.startDocument()
162 gen.startElement("doc", {})
163 gen.endElement("doc")
164 gen.endDocument()
166 self.assertEquals(result.getvalue(), start + "<doc></doc>")
168 def test_xmlgen_content(self):
169 result = StringIO()
170 gen = XMLGenerator(result)
172 gen.startDocument()
173 gen.startElement("doc", {})
174 gen.characters("huhei")
175 gen.endElement("doc")
176 gen.endDocument()
178 self.assertEquals(result.getvalue(), start + "<doc>huhei</doc>")
180 def test_xmlgen_pi(self):
181 result = StringIO()
182 gen = XMLGenerator(result)
184 gen.startDocument()
185 gen.processingInstruction("test", "data")
186 gen.startElement("doc", {})
187 gen.endElement("doc")
188 gen.endDocument()
190 self.assertEquals(result.getvalue(), start + "<?test data?><doc></doc>")
192 def test_xmlgen_content_escape(self):
193 result = StringIO()
194 gen = XMLGenerator(result)
196 gen.startDocument()
197 gen.startElement("doc", {})
198 gen.characters("<huhei&")
199 gen.endElement("doc")
200 gen.endDocument()
202 self.assertEquals(result.getvalue(),
203 start + "<doc>&lt;huhei&amp;</doc>")
205 def test_xmlgen_attr_escape(self):
206 result = StringIO()
207 gen = XMLGenerator(result)
209 gen.startDocument()
210 gen.startElement("doc", {"a": '"'})
211 gen.startElement("e", {"a": "'"})
212 gen.endElement("e")
213 gen.startElement("e", {"a": "'\""})
214 gen.endElement("e")
215 gen.startElement("e", {"a": "\n\r\t"})
216 gen.endElement("e")
217 gen.endElement("doc")
218 gen.endDocument()
220 self.assertEquals(result.getvalue(), start +
221 ("<doc a='\"'><e a=\"'\"></e>"
222 "<e a=\"'&quot;\"></e>"
223 "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
225 def test_xmlgen_ignorable(self):
226 result = StringIO()
227 gen = XMLGenerator(result)
229 gen.startDocument()
230 gen.startElement("doc", {})
231 gen.ignorableWhitespace(" ")
232 gen.endElement("doc")
233 gen.endDocument()
235 self.assertEquals(result.getvalue(), start + "<doc> </doc>")
237 def test_xmlgen_ns(self):
238 result = StringIO()
239 gen = XMLGenerator(result)
241 gen.startDocument()
242 gen.startPrefixMapping("ns1", ns_uri)
243 gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
244 # add an unqualified name
245 gen.startElementNS((None, "udoc"), None, {})
246 gen.endElementNS((None, "udoc"), None)
247 gen.endElementNS((ns_uri, "doc"), "ns1:doc")
248 gen.endPrefixMapping("ns1")
249 gen.endDocument()
251 self.assertEquals(result.getvalue(), start + \
252 ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
253 ns_uri))
255 def test_1463026_1(self):
256 result = StringIO()
257 gen = XMLGenerator(result)
259 gen.startDocument()
260 gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
261 gen.endElementNS((None, 'a'), 'a')
262 gen.endDocument()
264 self.assertEquals(result.getvalue(), start+'<a b="c"></a>')
266 def test_1463026_2(self):
267 result = StringIO()
268 gen = XMLGenerator(result)
270 gen.startDocument()
271 gen.startPrefixMapping(None, 'qux')
272 gen.startElementNS(('qux', 'a'), 'a', {})
273 gen.endElementNS(('qux', 'a'), 'a')
274 gen.endPrefixMapping(None)
275 gen.endDocument()
277 self.assertEquals(result.getvalue(), start+'<a xmlns="qux"></a>')
279 def test_1463026_3(self):
280 result = StringIO()
281 gen = XMLGenerator(result)
283 gen.startDocument()
284 gen.startPrefixMapping('my', 'qux')
285 gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
286 gen.endElementNS(('qux', 'a'), 'a')
287 gen.endPrefixMapping('my')
288 gen.endDocument()
290 self.assertEquals(result.getvalue(),
291 start+'<my:a xmlns:my="qux" b="c"></my:a>')
294 class XMLFilterBaseTest(unittest.TestCase):
295 def test_filter_basic(self):
296 result = StringIO()
297 gen = XMLGenerator(result)
298 filter = XMLFilterBase()
299 filter.setContentHandler(gen)
301 filter.startDocument()
302 filter.startElement("doc", {})
303 filter.characters("content")
304 filter.ignorableWhitespace(" ")
305 filter.endElement("doc")
306 filter.endDocument()
308 self.assertEquals(result.getvalue(), start + "<doc>content </doc>")
310 # ===========================================================================
312 # expatreader tests
314 # ===========================================================================
316 xml_test_out = open(TEST_XMLFILE_OUT).read()
318 class ExpatReaderTest(XmlTestBase):
320 # ===== XMLReader support
322 def test_expat_file(self):
323 parser = create_parser()
324 result = StringIO()
325 xmlgen = XMLGenerator(result)
327 parser.setContentHandler(xmlgen)
328 parser.parse(open(TEST_XMLFILE))
330 self.assertEquals(result.getvalue(), xml_test_out)
332 # ===== DTDHandler support
334 class TestDTDHandler:
336 def __init__(self):
337 self._notations = []
338 self._entities = []
340 def notationDecl(self, name, publicId, systemId):
341 self._notations.append((name, publicId, systemId))
343 def unparsedEntityDecl(self, name, publicId, systemId, ndata):
344 self._entities.append((name, publicId, systemId, ndata))
346 def test_expat_dtdhandler(self):
347 parser = create_parser()
348 handler = self.TestDTDHandler()
349 parser.setDTDHandler(handler)
351 parser.feed('<!DOCTYPE doc [\n')
352 parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
353 parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
354 parser.feed(']>\n')
355 parser.feed('<doc></doc>')
356 parser.close()
358 self.assertEquals(handler._notations,
359 [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
360 self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")])
362 # ===== EntityResolver support
364 class TestEntityResolver:
366 def resolveEntity(self, publicId, systemId):
367 inpsrc = InputSource()
368 inpsrc.setByteStream(StringIO("<entity/>"))
369 return inpsrc
371 def test_expat_entityresolver(self):
372 parser = create_parser()
373 parser.setEntityResolver(self.TestEntityResolver())
374 result = StringIO()
375 parser.setContentHandler(XMLGenerator(result))
377 parser.feed('<!DOCTYPE doc [\n')
378 parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
379 parser.feed(']>\n')
380 parser.feed('<doc>&test;</doc>')
381 parser.close()
383 self.assertEquals(result.getvalue(), start +
384 "<doc><entity></entity></doc>")
386 # ===== Attributes support
388 class AttrGatherer(ContentHandler):
390 def startElement(self, name, attrs):
391 self._attrs = attrs
393 def startElementNS(self, name, qname, attrs):
394 self._attrs = attrs
396 def test_expat_attrs_empty(self):
397 parser = create_parser()
398 gather = self.AttrGatherer()
399 parser.setContentHandler(gather)
401 parser.feed("<doc/>")
402 parser.close()
404 self.verify_empty_attrs(gather._attrs)
406 def test_expat_attrs_wattr(self):
407 parser = create_parser()
408 gather = self.AttrGatherer()
409 parser.setContentHandler(gather)
411 parser.feed("<doc attr='val'/>")
412 parser.close()
414 self.verify_attrs_wattr(gather._attrs)
416 def test_expat_nsattrs_empty(self):
417 parser = create_parser(1)
418 gather = self.AttrGatherer()
419 parser.setContentHandler(gather)
421 parser.feed("<doc/>")
422 parser.close()
424 self.verify_empty_nsattrs(gather._attrs)
426 def test_expat_nsattrs_wattr(self):
427 parser = create_parser(1)
428 gather = self.AttrGatherer()
429 parser.setContentHandler(gather)
431 parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
432 parser.close()
434 attrs = gather._attrs
436 self.assertEquals(attrs.getLength(), 1)
437 self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
438 self.assertTrue((attrs.getQNames() == [] or
439 attrs.getQNames() == ["ns:attr"]))
440 self.assertEquals(len(attrs), 1)
441 self.assertTrue(attrs.has_key((ns_uri, "attr")))
442 self.assertEquals(attrs.get((ns_uri, "attr")), "val")
443 self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
444 self.assertEquals(attrs.items(), [((ns_uri, "attr"), "val")])
445 self.assertEquals(attrs.values(), ["val"])
446 self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
447 self.assertEquals(attrs[(ns_uri, "attr")], "val")
449 # ===== InputSource support
451 def test_expat_inpsource_filename(self):
452 parser = create_parser()
453 result = StringIO()
454 xmlgen = XMLGenerator(result)
456 parser.setContentHandler(xmlgen)
457 parser.parse(TEST_XMLFILE)
459 self.assertEquals(result.getvalue(), xml_test_out)
461 def test_expat_inpsource_sysid(self):
462 parser = create_parser()
463 result = StringIO()
464 xmlgen = XMLGenerator(result)
466 parser.setContentHandler(xmlgen)
467 parser.parse(InputSource(TEST_XMLFILE))
469 self.assertEquals(result.getvalue(), xml_test_out)
471 def test_expat_inpsource_stream(self):
472 parser = create_parser()
473 result = StringIO()
474 xmlgen = XMLGenerator(result)
476 parser.setContentHandler(xmlgen)
477 inpsrc = InputSource()
478 inpsrc.setByteStream(open(TEST_XMLFILE))
479 parser.parse(inpsrc)
481 self.assertEquals(result.getvalue(), xml_test_out)
483 # ===== IncrementalParser support
485 def test_expat_incremental(self):
486 result = StringIO()
487 xmlgen = XMLGenerator(result)
488 parser = create_parser()
489 parser.setContentHandler(xmlgen)
491 parser.feed("<doc>")
492 parser.feed("</doc>")
493 parser.close()
495 self.assertEquals(result.getvalue(), start + "<doc></doc>")
497 def test_expat_incremental_reset(self):
498 result = StringIO()
499 xmlgen = XMLGenerator(result)
500 parser = create_parser()
501 parser.setContentHandler(xmlgen)
503 parser.feed("<doc>")
504 parser.feed("text")
506 result = StringIO()
507 xmlgen = XMLGenerator(result)
508 parser.setContentHandler(xmlgen)
509 parser.reset()
511 parser.feed("<doc>")
512 parser.feed("text")
513 parser.feed("</doc>")
514 parser.close()
516 self.assertEquals(result.getvalue(), start + "<doc>text</doc>")
518 # ===== Locator support
520 def test_expat_locator_noinfo(self):
521 result = StringIO()
522 xmlgen = XMLGenerator(result)
523 parser = create_parser()
524 parser.setContentHandler(xmlgen)
526 parser.feed("<doc>")
527 parser.feed("</doc>")
528 parser.close()
530 self.assertEquals(parser.getSystemId(), None)
531 self.assertEquals(parser.getPublicId(), None)
532 self.assertEquals(parser.getLineNumber(), 1)
534 def test_expat_locator_withinfo(self):
535 result = StringIO()
536 xmlgen = XMLGenerator(result)
537 parser = create_parser()
538 parser.setContentHandler(xmlgen)
539 parser.parse(TEST_XMLFILE)
541 self.assertEquals(parser.getSystemId(), TEST_XMLFILE)
542 self.assertEquals(parser.getPublicId(), None)
545 # ===========================================================================
547 # error reporting
549 # ===========================================================================
551 class ErrorReportingTest(unittest.TestCase):
552 def test_expat_inpsource_location(self):
553 parser = create_parser()
554 parser.setContentHandler(ContentHandler()) # do nothing
555 source = InputSource()
556 source.setByteStream(StringIO("<foo bar foobar>")) #ill-formed
557 name = "a file name"
558 source.setSystemId(name)
559 try:
560 parser.parse(source)
561 self.fail()
562 except SAXException, e:
563 self.assertEquals(e.getSystemId(), name)
565 def test_expat_incomplete(self):
566 parser = create_parser()
567 parser.setContentHandler(ContentHandler()) # do nothing
568 self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
570 def test_sax_parse_exception_str(self):
571 # pass various values from a locator to the SAXParseException to
572 # make sure that the __str__() doesn't fall apart when None is
573 # passed instead of an integer line and column number
575 # use "normal" values for the locator:
576 str(SAXParseException("message", None,
577 self.DummyLocator(1, 1)))
578 # use None for the line number:
579 str(SAXParseException("message", None,
580 self.DummyLocator(None, 1)))
581 # use None for the column number:
582 str(SAXParseException("message", None,
583 self.DummyLocator(1, None)))
584 # use None for both:
585 str(SAXParseException("message", None,
586 self.DummyLocator(None, None)))
588 class DummyLocator:
589 def __init__(self, lineno, colno):
590 self._lineno = lineno
591 self._colno = colno
593 def getPublicId(self):
594 return "pubid"
596 def getSystemId(self):
597 return "sysid"
599 def getLineNumber(self):
600 return self._lineno
602 def getColumnNumber(self):
603 return self._colno
605 # ===========================================================================
607 # xmlreader tests
609 # ===========================================================================
611 class XmlReaderTest(XmlTestBase):
613 # ===== AttributesImpl
614 def test_attrs_empty(self):
615 self.verify_empty_attrs(AttributesImpl({}))
617 def test_attrs_wattr(self):
618 self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
620 def test_nsattrs_empty(self):
621 self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
623 def test_nsattrs_wattr(self):
624 attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
625 {(ns_uri, "attr") : "ns:attr"})
627 self.assertEquals(attrs.getLength(), 1)
628 self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
629 self.assertEquals(attrs.getQNames(), ["ns:attr"])
630 self.assertEquals(len(attrs), 1)
631 self.assertTrue(attrs.has_key((ns_uri, "attr")))
632 self.assertEquals(attrs.keys(), [(ns_uri, "attr")])
633 self.assertEquals(attrs.get((ns_uri, "attr")), "val")
634 self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
635 self.assertEquals(attrs.items(), [((ns_uri, "attr"), "val")])
636 self.assertEquals(attrs.values(), ["val"])
637 self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
638 self.assertEquals(attrs.getValueByQName("ns:attr"), "val")
639 self.assertEquals(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
640 self.assertEquals(attrs[(ns_uri, "attr")], "val")
641 self.assertEquals(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
644 # During the development of Python 2.5, an attempt to move the "xml"
645 # package implementation to a new package ("xmlcore") proved painful.
646 # The goal of this change was to allow applications to be able to
647 # obtain and rely on behavior in the standard library implementation
648 # of the XML support without needing to be concerned about the
649 # availability of the PyXML implementation.
651 # While the existing import hackery in Lib/xml/__init__.py can cause
652 # PyXML's _xmlpus package to supplant the "xml" package, that only
653 # works because either implementation uses the "xml" package name for
654 # imports.
656 # The move resulted in a number of problems related to the fact that
657 # the import machinery's "package context" is based on the name that's
658 # being imported rather than the __name__ of the actual package
659 # containment; it wasn't possible for the "xml" package to be replaced
660 # by a simple module that indirected imports to the "xmlcore" package.
662 # The following two tests exercised bugs that were introduced in that
663 # attempt. Keeping these tests around will help detect problems with
664 # other attempts to provide reliable access to the standard library's
665 # implementation of the XML support.
667 def test_sf_1511497(self):
668 # Bug report: http://www.python.org/sf/1511497
669 import sys
670 old_modules = sys.modules.copy()
671 for modname in sys.modules.keys():
672 if modname.startswith("xml."):
673 del sys.modules[modname]
674 try:
675 import xml.sax.expatreader
676 module = xml.sax.expatreader
677 self.assertEquals(module.__name__, "xml.sax.expatreader")
678 finally:
679 sys.modules.update(old_modules)
681 def test_sf_1513611(self):
682 # Bug report: http://www.python.org/sf/1513611
683 sio = StringIO("invalid")
684 parser = make_parser()
685 from xml.sax import SAXParseException
686 self.assertRaises(SAXParseException, parser.parse, sio)
689 def test_main():
690 run_unittest(MakeParserTest,
691 SaxutilsTest,
692 XmlgenTest,
693 ExpatReaderTest,
694 ErrorReportingTest,
695 XmlReaderTest)
697 if __name__ == "__main__":
698 test_main()