1 # regression test for SAX 2.0
4 from xml
.sax
import make_parser
, ContentHandler
, \
5 SAXException
, SAXReaderNotAvailable
, SAXParseException
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
, XMLFilterBase
12 from xml
.sax
.expatreader
import create_parser
13 from xml
.sax
.xmlreader
import InputSource
, AttributesImpl
, AttributesNSImpl
14 from cStringIO
import StringIO
15 from test_support
import verify
, verbose
, TestFailed
, findfile
22 def confirm(outcome
, name
):
32 def test_make_parser2():
34 # Creating parsers several times in a row should succeed.
35 # Testing this because there have been failures of this kind
37 from xml
.sax
import make_parser
39 from xml
.sax
import make_parser
41 from xml
.sax
import make_parser
43 from xml
.sax
import make_parser
45 from xml
.sax
import make_parser
47 from xml
.sax
import make_parser
55 # ===========================================================================
59 # ===========================================================================
63 def test_escape_basic():
64 return escape("Donald Duck & Co") == "Donald Duck & Co"
66 def test_escape_all():
67 return escape("<Donald Duck & Co>") == "<Donald Duck & Co>"
69 def test_escape_extra():
70 return escape("Hei på deg", {"å" : "å"}) == "Hei på deg"
72 def test_make_parser():
74 # Creating a parser should succeed - it should fall back
76 p
= make_parser(['xml.parsers.no_such_parser'])
85 start
= '<?xml version="1.0" encoding="iso-8859-1"?>\n'
87 def test_xmlgen_basic():
89 gen
= XMLGenerator(result
)
91 gen
.startElement("doc", {})
95 return result
.getvalue() == start
+ "<doc></doc>"
97 def test_xmlgen_content():
99 gen
= XMLGenerator(result
)
102 gen
.startElement("doc", {})
103 gen
.characters("huhei")
104 gen
.endElement("doc")
107 return result
.getvalue() == start
+ "<doc>huhei</doc>"
109 def test_xmlgen_pi():
111 gen
= XMLGenerator(result
)
114 gen
.processingInstruction("test", "data")
115 gen
.startElement("doc", {})
116 gen
.endElement("doc")
119 return result
.getvalue() == start
+ "<?test data?><doc></doc>"
121 def test_xmlgen_content_escape():
123 gen
= XMLGenerator(result
)
126 gen
.startElement("doc", {})
127 gen
.characters("<huhei&")
128 gen
.endElement("doc")
131 return result
.getvalue() == start
+ "<doc><huhei&</doc>"
133 def test_xmlgen_ignorable():
135 gen
= XMLGenerator(result
)
138 gen
.startElement("doc", {})
139 gen
.ignorableWhitespace(" ")
140 gen
.endElement("doc")
143 return result
.getvalue() == start
+ "<doc> </doc>"
145 ns_uri
= "http://www.python.org/xml-ns/saxtest/"
147 def test_xmlgen_ns():
149 gen
= XMLGenerator(result
)
152 gen
.startPrefixMapping("ns1", ns_uri
)
153 gen
.startElementNS((ns_uri
, "doc"), "ns1:doc", {})
154 # add an unqualified name
155 gen
.startElementNS((None, "udoc"), None, {})
156 gen
.endElementNS((None, "udoc"), None)
157 gen
.endElementNS((ns_uri
, "doc"), "ns1:doc")
158 gen
.endPrefixMapping("ns1")
161 return result
.getvalue() == start
+ \
162 ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
165 # ===== XMLFilterBase
167 def test_filter_basic():
169 gen
= XMLGenerator(result
)
170 filter = XMLFilterBase()
171 filter.setContentHandler(gen
)
173 filter.startDocument()
174 filter.startElement("doc", {})
175 filter.characters("content")
176 filter.ignorableWhitespace(" ")
177 filter.endElement("doc")
180 return result
.getvalue() == start
+ "<doc>content </doc>"
182 # ===========================================================================
186 # ===========================================================================
188 # ===== XMLReader support
190 def test_expat_file():
191 parser
= create_parser()
193 xmlgen
= XMLGenerator(result
)
195 parser
.setContentHandler(xmlgen
)
196 parser
.parse(open(findfile("test.xml")))
198 return result
.getvalue() == xml_test_out
200 # ===== DTDHandler support
202 class TestDTDHandler
:
208 def notationDecl(self
, name
, publicId
, systemId
):
209 self
._notations
.append((name
, publicId
, systemId
))
211 def unparsedEntityDecl(self
, name
, publicId
, systemId
, ndata
):
212 self
._entities
.append((name
, publicId
, systemId
, ndata
))
214 def test_expat_dtdhandler():
215 parser
= create_parser()
216 handler
= TestDTDHandler()
217 parser
.setDTDHandler(handler
)
219 parser
.feed('<!DOCTYPE doc [\n')
220 parser
.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
221 parser
.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
223 parser
.feed('<doc></doc>')
226 return handler
._notations
== [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
227 handler
._entities
== [("img", None, "expat.gif", "GIF")]
229 # ===== EntityResolver support
231 class TestEntityResolver
:
233 def resolveEntity(self
, publicId
, systemId
):
234 inpsrc
= InputSource()
235 inpsrc
.setByteStream(StringIO("<entity/>"))
238 def test_expat_entityresolver():
239 parser
= create_parser()
240 parser
.setEntityResolver(TestEntityResolver())
242 parser
.setContentHandler(XMLGenerator(result
))
244 parser
.feed('<!DOCTYPE doc [\n')
245 parser
.feed(' <!ENTITY test SYSTEM "whatever">\n')
247 parser
.feed('<doc>&test;</doc>')
250 return result
.getvalue() == start
+ "<doc><entity></entity></doc>"
252 # ===== Attributes support
254 class AttrGatherer(ContentHandler
):
256 def startElement(self
, name
, attrs
):
259 def startElementNS(self
, name
, qname
, attrs
):
262 def test_expat_attrs_empty():
263 parser
= create_parser()
264 gather
= AttrGatherer()
265 parser
.setContentHandler(gather
)
267 parser
.feed("<doc/>")
270 return verify_empty_attrs(gather
._attrs
)
272 def test_expat_attrs_wattr():
273 parser
= create_parser()
274 gather
= AttrGatherer()
275 parser
.setContentHandler(gather
)
277 parser
.feed("<doc attr='val'/>")
280 return verify_attrs_wattr(gather
._attrs
)
282 def test_expat_nsattrs_empty():
283 parser
= create_parser(1)
284 gather
= AttrGatherer()
285 parser
.setContentHandler(gather
)
287 parser
.feed("<doc/>")
290 return verify_empty_nsattrs(gather
._attrs
)
292 def test_expat_nsattrs_wattr():
293 parser
= create_parser(1)
294 gather
= AttrGatherer()
295 parser
.setContentHandler(gather
)
297 parser
.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri
)
300 attrs
= gather
._attrs
302 return attrs
.getLength() == 1 and \
303 attrs
.getNames() == [(ns_uri
, "attr")] and \
304 attrs
.getQNames() == [] and \
305 len(attrs
) == 1 and \
306 attrs
.has_key((ns_uri
, "attr")) and \
307 attrs
.keys() == [(ns_uri
, "attr")] and \
308 attrs
.get((ns_uri
, "attr")) == "val" and \
309 attrs
.get((ns_uri
, "attr"), 25) == "val" and \
310 attrs
.items() == [((ns_uri
, "attr"), "val")] and \
311 attrs
.values() == ["val"] and \
312 attrs
.getValue((ns_uri
, "attr")) == "val" and \
313 attrs
[(ns_uri
, "attr")] == "val"
315 # ===== InputSource support
317 xml_test_out
= open(findfile("test.xml.out")).read()
319 def test_expat_inpsource_filename():
320 parser
= create_parser()
322 xmlgen
= XMLGenerator(result
)
324 parser
.setContentHandler(xmlgen
)
325 parser
.parse(findfile("test.xml"))
327 return result
.getvalue() == xml_test_out
329 def test_expat_inpsource_sysid():
330 parser
= create_parser()
332 xmlgen
= XMLGenerator(result
)
334 parser
.setContentHandler(xmlgen
)
335 parser
.parse(InputSource(findfile("test.xml")))
337 return result
.getvalue() == xml_test_out
339 def test_expat_inpsource_stream():
340 parser
= create_parser()
342 xmlgen
= XMLGenerator(result
)
344 parser
.setContentHandler(xmlgen
)
345 inpsrc
= InputSource()
346 inpsrc
.setByteStream(open(findfile("test.xml")))
349 return result
.getvalue() == xml_test_out
351 # ===== IncrementalParser support
353 def test_expat_incremental():
355 xmlgen
= XMLGenerator(result
)
356 parser
= create_parser()
357 parser
.setContentHandler(xmlgen
)
360 parser
.feed("</doc>")
363 return result
.getvalue() == start
+ "<doc></doc>"
365 def test_expat_incremental_reset():
367 xmlgen
= XMLGenerator(result
)
368 parser
= create_parser()
369 parser
.setContentHandler(xmlgen
)
375 xmlgen
= XMLGenerator(result
)
376 parser
.setContentHandler(xmlgen
)
381 parser
.feed("</doc>")
384 return result
.getvalue() == start
+ "<doc>text</doc>"
386 # ===== Locator support
388 def test_expat_locator_noinfo():
390 xmlgen
= XMLGenerator(result
)
391 parser
= create_parser()
392 parser
.setContentHandler(xmlgen
)
395 parser
.feed("</doc>")
398 return parser
.getSystemId() is None and \
399 parser
.getPublicId() is None and \
400 parser
.getLineNumber() == 1
402 def test_expat_locator_withinfo():
404 xmlgen
= XMLGenerator(result
)
405 parser
= create_parser()
406 parser
.setContentHandler(xmlgen
)
407 parser
.parse(findfile("test.xml"))
409 return parser
.getSystemId() == findfile("test.xml") and \
410 parser
.getPublicId() is None
413 # ===========================================================================
417 # ===========================================================================
419 def test_expat_inpsource_location():
420 parser
= create_parser()
421 parser
.setContentHandler(ContentHandler()) # do nothing
422 source
= InputSource()
423 source
.setByteStream(StringIO("<foo bar foobar>")) #ill-formed
425 source
.setSystemId(name
)
428 except SAXException
, e
:
429 return e
.getSystemId() == name
431 def test_expat_incomplete():
432 parser
= create_parser()
433 parser
.setContentHandler(ContentHandler()) # do nothing
435 parser
.parse(StringIO("<foo>"))
436 except SAXParseException
:
437 return 1 # ok, error found
442 # ===========================================================================
446 # ===========================================================================
448 # ===== AttributesImpl
450 def verify_empty_attrs(attrs
):
452 attrs
.getValue("attr")
458 attrs
.getValueByQName("attr")
464 attrs
.getNameByQName("attr")
470 attrs
.getQNameByName("attr")
481 return attrs
.getLength() == 0 and \
482 attrs
.getNames() == [] and \
483 attrs
.getQNames() == [] and \
484 len(attrs
) == 0 and \
485 not attrs
.has_key("attr") and \
486 attrs
.keys() == [] and \
487 attrs
.get("attrs") is None and \
488 attrs
.get("attrs", 25) == 25 and \
489 attrs
.items() == [] and \
490 attrs
.values() == [] and \
491 gvk
and gvqk
and gnqk
and gik
and gqnk
493 def verify_attrs_wattr(attrs
):
494 return attrs
.getLength() == 1 and \
495 attrs
.getNames() == ["attr"] and \
496 attrs
.getQNames() == ["attr"] and \
497 len(attrs
) == 1 and \
498 attrs
.has_key("attr") and \
499 attrs
.keys() == ["attr"] and \
500 attrs
.get("attr") == "val" and \
501 attrs
.get("attr", 25) == "val" and \
502 attrs
.items() == [("attr", "val")] and \
503 attrs
.values() == ["val"] and \
504 attrs
.getValue("attr") == "val" and \
505 attrs
.getValueByQName("attr") == "val" and \
506 attrs
.getNameByQName("attr") == "attr" and \
507 attrs
["attr"] == "val" and \
508 attrs
.getQNameByName("attr") == "attr"
510 def test_attrs_empty():
511 return verify_empty_attrs(AttributesImpl({}))
513 def test_attrs_wattr():
514 return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
516 # ===== AttributesImpl
518 def verify_empty_nsattrs(attrs
):
520 attrs
.getValue((ns_uri
, "attr"))
526 attrs
.getValueByQName("ns:attr")
532 attrs
.getNameByQName("ns:attr")
538 attrs
.getQNameByName((ns_uri
, "attr"))
544 attrs
[(ns_uri
, "attr")]
549 return attrs
.getLength() == 0 and \
550 attrs
.getNames() == [] and \
551 attrs
.getQNames() == [] and \
552 len(attrs
) == 0 and \
553 not attrs
.has_key((ns_uri
, "attr")) and \
554 attrs
.keys() == [] and \
555 attrs
.get((ns_uri
, "attr")) is None and \
556 attrs
.get((ns_uri
, "attr"), 25) == 25 and \
557 attrs
.items() == [] and \
558 attrs
.values() == [] and \
559 gvk
and gvqk
and gnqk
and gik
and gqnk
561 def test_nsattrs_empty():
562 return verify_empty_nsattrs(AttributesNSImpl({}, {}))
564 def test_nsattrs_wattr():
565 attrs
= AttributesNSImpl({(ns_uri
, "attr") : "val"},
566 {(ns_uri
, "attr") : "ns:attr"})
568 return attrs
.getLength() == 1 and \
569 attrs
.getNames() == [(ns_uri
, "attr")] and \
570 attrs
.getQNames() == ["ns:attr"] and \
571 len(attrs
) == 1 and \
572 attrs
.has_key((ns_uri
, "attr")) and \
573 attrs
.keys() == [(ns_uri
, "attr")] and \
574 attrs
.get((ns_uri
, "attr")) == "val" and \
575 attrs
.get((ns_uri
, "attr"), 25) == "val" and \
576 attrs
.items() == [((ns_uri
, "attr"), "val")] and \
577 attrs
.values() == ["val"] and \
578 attrs
.getValue((ns_uri
, "attr")) == "val" and \
579 attrs
.getValueByQName("ns:attr") == "val" and \
580 attrs
.getNameByQName("ns:attr") == (ns_uri
, "attr") and \
581 attrs
[(ns_uri
, "attr")] == "val" and \
582 attrs
.getQNameByName((ns_uri
, "attr")) == "ns:attr"
587 def make_test_output():
588 parser
= create_parser()
590 xmlgen
= XMLGenerator(result
)
592 parser
.setContentHandler(xmlgen
)
593 parser
.parse(findfile("test.xml"))
595 outf
= open(findfile("test.xml.out"), "w")
596 outf
.write(result
.getvalue())
599 items
= locals().items()
601 for (name
, value
) in items
:
602 if name
[ : 5] == "test_":
603 confirm(value(), name
)
605 print "%d tests, %d failures" % (tests
, fails
)
607 raise TestFailed
, "%d of %d tests failed" % (fails
, tests
)