2 # regression test for SAX 2.0
5 from xml
.sax
import make_parser
, ContentHandler
, \
6 SAXException
, SAXReaderNotAvailable
, SAXParseException
9 except SAXReaderNotAvailable
:
10 # don't try to test this module if we cannot create a parser
11 raise ImportError("no XML parsers available")
12 from xml
.sax
.saxutils
import XMLGenerator
, escape
, 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_support
import verbose
, TestFailed
, findfile
23 def confirm(outcome
, name
):
33 # ===========================================================================
37 # ===========================================================================
41 def test_escape_basic():
42 return escape("Donald Duck & Co") == "Donald Duck & Co"
44 def test_escape_all():
45 return escape("<Donald Duck & Co>") == "<Donald Duck & Co>"
47 def test_escape_extra():
48 return escape("Hei på deg", {"å" : "å"}) == "Hei på deg"
50 def test_make_parser():
52 # Creating a parser should succeed - it should fall back
54 p
= make_parser(['xml.parsers.no_such_parser'])
63 start
= '<?xml version="1.0" encoding="iso-8859-1"?>\n'
65 def test_xmlgen_basic():
67 gen
= XMLGenerator(result
)
69 gen
.startElement("doc", {})
73 return result
.getvalue() == start
+ "<doc></doc>"
75 def test_xmlgen_content():
77 gen
= XMLGenerator(result
)
80 gen
.startElement("doc", {})
81 gen
.characters("huhei")
85 return result
.getvalue() == start
+ "<doc>huhei</doc>"
89 gen
= XMLGenerator(result
)
92 gen
.processingInstruction("test", "data")
93 gen
.startElement("doc", {})
97 return result
.getvalue() == start
+ "<?test data?><doc></doc>"
99 def test_xmlgen_content_escape():
101 gen
= XMLGenerator(result
)
104 gen
.startElement("doc", {})
105 gen
.characters("<huhei&")
106 gen
.endElement("doc")
109 return result
.getvalue() == start
+ "<doc><huhei&</doc>"
111 def test_xmlgen_ignorable():
113 gen
= XMLGenerator(result
)
116 gen
.startElement("doc", {})
117 gen
.ignorableWhitespace(" ")
118 gen
.endElement("doc")
121 return result
.getvalue() == start
+ "<doc> </doc>"
123 ns_uri
= "http://www.python.org/xml-ns/saxtest/"
125 def test_xmlgen_ns():
127 gen
= XMLGenerator(result
)
130 gen
.startPrefixMapping("ns1", ns_uri
)
131 gen
.startElementNS((ns_uri
, "doc"), "ns1:doc", {})
132 # add an unqualified name
133 gen
.startElementNS((None, "udoc"), None, {})
134 gen
.endElementNS((None, "udoc"), None)
135 gen
.endElementNS((ns_uri
, "doc"), "ns1:doc")
136 gen
.endPrefixMapping("ns1")
139 return result
.getvalue() == start
+ \
140 ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
143 # ===== XMLFilterBase
145 def test_filter_basic():
147 gen
= XMLGenerator(result
)
148 filter = XMLFilterBase()
149 filter.setContentHandler(gen
)
151 filter.startDocument()
152 filter.startElement("doc", {})
153 filter.characters("content")
154 filter.ignorableWhitespace(" ")
155 filter.endElement("doc")
158 return result
.getvalue() == start
+ "<doc>content </doc>"
160 # ===========================================================================
164 # ===========================================================================
166 # ===== DTDHandler support
168 class TestDTDHandler
:
174 def notationDecl(self
, name
, publicId
, systemId
):
175 self
._notations
.append((name
, publicId
, systemId
))
177 def unparsedEntityDecl(self
, name
, publicId
, systemId
, ndata
):
178 self
._entities
.append((name
, publicId
, systemId
, ndata
))
180 def test_expat_dtdhandler():
181 parser
= create_parser()
182 handler
= TestDTDHandler()
183 parser
.setDTDHandler(handler
)
185 parser
.feed('<!DOCTYPE doc [\n')
186 parser
.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
187 parser
.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
189 parser
.feed('<doc></doc>')
192 return handler
._notations
== [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
193 handler
._entities
== [("img", None, "expat.gif", "GIF")]
195 # ===== EntityResolver support
197 class TestEntityResolver
:
199 def resolveEntity(self
, publicId
, systemId
):
200 inpsrc
= InputSource()
201 inpsrc
.setByteStream(StringIO("<entity/>"))
204 def test_expat_entityresolver():
205 parser
= create_parser()
206 parser
.setEntityResolver(TestEntityResolver())
208 parser
.setContentHandler(XMLGenerator(result
))
210 parser
.feed('<!DOCTYPE doc [\n')
211 parser
.feed(' <!ENTITY test SYSTEM "whatever">\n')
213 parser
.feed('<doc>&test;</doc>')
216 return result
.getvalue() == start
+ "<doc><entity></entity></doc>"
218 # ===== Attributes support
220 class AttrGatherer(ContentHandler
):
222 def startElement(self
, name
, attrs
):
225 def startElementNS(self
, name
, qname
, attrs
):
228 def test_expat_attrs_empty():
229 parser
= create_parser()
230 gather
= AttrGatherer()
231 parser
.setContentHandler(gather
)
233 parser
.feed("<doc/>")
236 return verify_empty_attrs(gather
._attrs
)
238 def test_expat_attrs_wattr():
239 parser
= create_parser()
240 gather
= AttrGatherer()
241 parser
.setContentHandler(gather
)
243 parser
.feed("<doc attr='val'/>")
246 return verify_attrs_wattr(gather
._attrs
)
248 def test_expat_nsattrs_empty():
249 parser
= create_parser(1)
250 gather
= AttrGatherer()
251 parser
.setContentHandler(gather
)
253 parser
.feed("<doc/>")
256 return verify_empty_nsattrs(gather
._attrs
)
258 def test_expat_nsattrs_wattr():
259 parser
= create_parser(1)
260 gather
= AttrGatherer()
261 parser
.setContentHandler(gather
)
263 parser
.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri
)
266 attrs
= gather
._attrs
268 return attrs
.getLength() == 1 and \
269 attrs
.getNames() == [(ns_uri
, "attr")] and \
270 attrs
.getQNames() == [] and \
271 len(attrs
) == 1 and \
272 attrs
.has_key((ns_uri
, "attr")) and \
273 attrs
.keys() == [(ns_uri
, "attr")] and \
274 attrs
.get((ns_uri
, "attr")) == "val" and \
275 attrs
.get((ns_uri
, "attr"), 25) == "val" and \
276 attrs
.items() == [((ns_uri
, "attr"), "val")] and \
277 attrs
.values() == ["val"] and \
278 attrs
.getValue((ns_uri
, "attr")) == "val" and \
279 attrs
[(ns_uri
, "attr")] == "val"
281 # ===== InputSource support
283 xml_test_out
= open(findfile("test.xml.out")).read()
285 def test_expat_inpsource_filename():
286 parser
= create_parser()
288 xmlgen
= XMLGenerator(result
)
290 parser
.setContentHandler(xmlgen
)
291 parser
.parse(findfile("test.xml"))
293 return result
.getvalue() == xml_test_out
295 def test_expat_inpsource_sysid():
296 parser
= create_parser()
298 xmlgen
= XMLGenerator(result
)
300 parser
.setContentHandler(xmlgen
)
301 parser
.parse(InputSource(findfile("test.xml")))
303 return result
.getvalue() == xml_test_out
305 def test_expat_inpsource_stream():
306 parser
= create_parser()
308 xmlgen
= XMLGenerator(result
)
310 parser
.setContentHandler(xmlgen
)
311 inpsrc
= InputSource()
312 inpsrc
.setByteStream(open(findfile("test.xml")))
315 return result
.getvalue() == xml_test_out
318 # ===========================================================================
322 # ===========================================================================
324 def test_expat_inpsource_location():
325 parser
= create_parser()
326 parser
.setContentHandler(ContentHandler()) # do nothing
327 source
= InputSource()
328 source
.setByteStream(StringIO("<foo bar foobar>")) #ill-formed
330 source
.setSystemId(name
)
333 except SAXException
, e
:
334 return e
.getSystemId() == name
336 def test_expat_incomplete():
337 parser
= create_parser()
338 parser
.setContentHandler(ContentHandler()) # do nothing
340 parser
.parse(StringIO("<foo>"))
341 except SAXParseException
:
342 return 1 # ok, error found
347 # ===========================================================================
351 # ===========================================================================
353 # ===== AttributesImpl
355 def verify_empty_attrs(attrs
):
357 attrs
.getValue("attr")
363 attrs
.getValueByQName("attr")
369 attrs
.getNameByQName("attr")
375 attrs
.getQNameByName("attr")
386 return attrs
.getLength() == 0 and \
387 attrs
.getNames() == [] and \
388 attrs
.getQNames() == [] and \
389 len(attrs
) == 0 and \
390 not attrs
.has_key("attr") and \
391 attrs
.keys() == [] and \
392 attrs
.get("attrs") == None and \
393 attrs
.get("attrs", 25) == 25 and \
394 attrs
.items() == [] and \
395 attrs
.values() == [] and \
396 gvk
and gvqk
and gnqk
and gik
and gqnk
398 def verify_attrs_wattr(attrs
):
399 return attrs
.getLength() == 1 and \
400 attrs
.getNames() == ["attr"] and \
401 attrs
.getQNames() == ["attr"] and \
402 len(attrs
) == 1 and \
403 attrs
.has_key("attr") and \
404 attrs
.keys() == ["attr"] and \
405 attrs
.get("attr") == "val" and \
406 attrs
.get("attr", 25) == "val" and \
407 attrs
.items() == [("attr", "val")] and \
408 attrs
.values() == ["val"] and \
409 attrs
.getValue("attr") == "val" and \
410 attrs
.getValueByQName("attr") == "val" and \
411 attrs
.getNameByQName("attr") == "attr" and \
412 attrs
["attr"] == "val" and \
413 attrs
.getQNameByName("attr") == "attr"
415 def test_attrs_empty():
416 return verify_empty_attrs(AttributesImpl({}))
418 def test_attrs_wattr():
419 return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
421 # ===== AttributesImpl
423 def verify_empty_nsattrs(attrs
):
425 attrs
.getValue((ns_uri
, "attr"))
431 attrs
.getValueByQName("ns:attr")
437 attrs
.getNameByQName("ns:attr")
443 attrs
.getQNameByName((ns_uri
, "attr"))
449 attrs
[(ns_uri
, "attr")]
454 return attrs
.getLength() == 0 and \
455 attrs
.getNames() == [] and \
456 attrs
.getQNames() == [] and \
457 len(attrs
) == 0 and \
458 not attrs
.has_key((ns_uri
, "attr")) and \
459 attrs
.keys() == [] and \
460 attrs
.get((ns_uri
, "attr")) == None and \
461 attrs
.get((ns_uri
, "attr"), 25) == 25 and \
462 attrs
.items() == [] and \
463 attrs
.values() == [] and \
464 gvk
and gvqk
and gnqk
and gik
and gqnk
466 def test_nsattrs_empty():
467 return verify_empty_nsattrs(AttributesNSImpl({}, {}))
469 def test_nsattrs_wattr():
470 attrs
= AttributesNSImpl({(ns_uri
, "attr") : "val"},
471 {(ns_uri
, "attr") : "ns:attr"})
473 return attrs
.getLength() == 1 and \
474 attrs
.getNames() == [(ns_uri
, "attr")] and \
475 attrs
.getQNames() == ["ns:attr"] and \
476 len(attrs
) == 1 and \
477 attrs
.has_key((ns_uri
, "attr")) and \
478 attrs
.keys() == [(ns_uri
, "attr")] and \
479 attrs
.get((ns_uri
, "attr")) == "val" and \
480 attrs
.get((ns_uri
, "attr"), 25) == "val" and \
481 attrs
.items() == [((ns_uri
, "attr"), "val")] and \
482 attrs
.values() == ["val"] and \
483 attrs
.getValue((ns_uri
, "attr")) == "val" and \
484 attrs
.getValueByQName("ns:attr") == "val" and \
485 attrs
.getNameByQName("ns:attr") == (ns_uri
, "attr") and \
486 attrs
[(ns_uri
, "attr")] == "val" and \
487 attrs
.getQNameByName((ns_uri
, "attr")) == "ns:attr"
492 def make_test_output():
493 parser
= create_parser()
495 xmlgen
= XMLGenerator(result
)
497 parser
.setContentHandler(xmlgen
)
498 parser
.parse(findfile("test.xml"))
500 outf
= open(findfile("test.xml.out"), "w")
501 outf
.write(result
.getvalue())
504 items
= locals().items()
506 for (name
, value
) in items
:
507 if name
[ : 5] == "test_":
508 confirm(value(), name
)
510 print "%d tests, %d failures" % (tests
, fails
)
512 raise TestFailed
, "%d of %d tests failed" % (fails
, tests
)