Package lxml :: Package tests :: Module test_etree
[hide private]
[frames] | no frames]

Source Code for Module lxml.tests.test_etree

   1  # -*- coding: utf-8 -*- 
   2   
   3  """ 
   4  Tests specific to the extended etree API 
   5   
   6  Tests that apply to the general ElementTree API should go into 
   7  test_elementtree 
   8  """ 
   9   
  10  from __future__ import absolute_import 
  11   
  12  from collections import OrderedDict 
  13  import os.path 
  14  import unittest 
  15  import copy 
  16  import sys 
  17  import re 
  18  import gc 
  19  import operator 
  20  import textwrap 
  21  import zlib 
  22  import gzip 
  23   
  24  from .common_imports import etree, StringIO, BytesIO, HelperTestCase 
  25  from .common_imports import fileInTestDir, fileUrlInTestDir, read_file, path2url, tmpfile 
  26  from .common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest 
  27  from .common_imports import canonicalize, _str, _bytes 
  28   
  29  print(""" 
  30  TESTED VERSION: %s""" % etree.__version__ + """ 
  31      Python:           %r""" % (sys.version_info,) + """ 
  32      lxml.etree:       %r""" % (etree.LXML_VERSION,) + """ 
  33      libxml used:      %r""" % (etree.LIBXML_VERSION,) + """ 
  34      libxml compiled:  %r""" % (etree.LIBXML_COMPILED_VERSION,) + """ 
  35      libxslt used:     %r""" % (etree.LIBXSLT_VERSION,) + """ 
  36      libxslt compiled: %r""" % (etree.LIBXSLT_COMPILED_VERSION,) + """ 
  37      FS encoding:      %s""" % (sys.getfilesystemencoding(),) + """ 
  38      Default encoding: %s""" % (sys.getdefaultencoding(),) + """ 
  39      Max Unicode:      %s""" % (sys.maxunicode,) + """ 
  40  """) 
  41   
  42  try: 
  43      _unicode = unicode 
  44  except NameError: 
  45      # Python 3 
  46      _unicode = str 
  47   
  48   
49 -class ETreeOnlyTestCase(HelperTestCase):
50 """Tests only for etree, not ElementTree""" 51 etree = etree 52
53 - def test_version(self):
54 self.assertTrue(isinstance(etree.__version__, _unicode)) 55 self.assertTrue(isinstance(etree.LXML_VERSION, tuple)) 56 self.assertEqual(len(etree.LXML_VERSION), 4) 57 self.assertTrue(isinstance(etree.LXML_VERSION[0], int)) 58 self.assertTrue(isinstance(etree.LXML_VERSION[1], int)) 59 self.assertTrue(isinstance(etree.LXML_VERSION[2], int)) 60 self.assertTrue(isinstance(etree.LXML_VERSION[3], int)) 61 self.assertTrue(etree.__version__.startswith( 62 str(etree.LXML_VERSION[0])))
63
64 - def test_c_api(self):
65 if hasattr(self.etree, '__pyx_capi__'): 66 # newer Pyrex compatible C-API 67 self.assertTrue(isinstance(self.etree.__pyx_capi__, dict)) 68 self.assertTrue(len(self.etree.__pyx_capi__) > 0) 69 else: 70 # older C-API mechanism 71 self.assertTrue(hasattr(self.etree, '_import_c_api'))
72
73 - def test_include_paths(self):
74 import lxml 75 includes = lxml.get_include() 76 self.assertTrue(includes) 77 self.assertTrue(len(includes) >= 2) 78 self.assertTrue(os.path.join(os.path.dirname(lxml.__file__), 'includes') in includes, 79 includes)
80
81 - def test_element_names(self):
82 Element = self.etree.Element 83 el = Element('name') 84 self.assertEqual(el.tag, 'name') 85 el = Element('{}name') 86 self.assertEqual(el.tag, 'name')
87
88 - def test_element_name_empty(self):
89 Element = self.etree.Element 90 el = Element('name') 91 self.assertRaises(ValueError, Element, '{}') 92 self.assertRaises(ValueError, setattr, el, 'tag', '{}') 93 94 self.assertRaises(ValueError, Element, '{test}') 95 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
96
97 - def test_element_name_colon(self):
98 Element = self.etree.Element 99 self.assertRaises(ValueError, Element, 'p:name') 100 self.assertRaises(ValueError, Element, '{test}p:name') 101 102 el = Element('name') 103 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
104
105 - def test_element_name_quote(self):
106 Element = self.etree.Element 107 self.assertRaises(ValueError, Element, "p'name") 108 self.assertRaises(ValueError, Element, 'p"name') 109 110 self.assertRaises(ValueError, Element, "{test}p'name") 111 self.assertRaises(ValueError, Element, '{test}p"name') 112 113 el = Element('name') 114 self.assertRaises(ValueError, setattr, el, 'tag', "p'name") 115 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
116
117 - def test_element_name_space(self):
118 Element = self.etree.Element 119 self.assertRaises(ValueError, Element, ' name ') 120 self.assertRaises(ValueError, Element, 'na me') 121 self.assertRaises(ValueError, Element, '{test} name') 122 123 el = Element('name') 124 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
125
126 - def test_subelement_name_empty(self):
127 Element = self.etree.Element 128 SubElement = self.etree.SubElement 129 130 el = Element('name') 131 self.assertRaises(ValueError, SubElement, el, '{}') 132 self.assertRaises(ValueError, SubElement, el, '{test}')
133
134 - def test_subelement_name_colon(self):
135 Element = self.etree.Element 136 SubElement = self.etree.SubElement 137 138 el = Element('name') 139 self.assertRaises(ValueError, SubElement, el, 'p:name') 140 self.assertRaises(ValueError, SubElement, el, '{test}p:name')
141
142 - def test_subelement_name_quote(self):
143 Element = self.etree.Element 144 SubElement = self.etree.SubElement 145 146 el = Element('name') 147 self.assertRaises(ValueError, SubElement, el, "p'name") 148 self.assertRaises(ValueError, SubElement, el, "{test}p'name") 149 150 self.assertRaises(ValueError, SubElement, el, 'p"name') 151 self.assertRaises(ValueError, SubElement, el, '{test}p"name')
152
153 - def test_subelement_name_space(self):
154 Element = self.etree.Element 155 SubElement = self.etree.SubElement 156 157 el = Element('name') 158 self.assertRaises(ValueError, SubElement, el, ' name ') 159 self.assertRaises(ValueError, SubElement, el, 'na me') 160 self.assertRaises(ValueError, SubElement, el, '{test} name')
161
163 Element = self.etree.Element 164 SubElement = self.etree.SubElement 165 166 el = Element('name') 167 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'}) 168 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'}) 169 self.assertEqual(0, len(el))
170
171 - def test_qname_empty(self):
172 QName = self.etree.QName 173 self.assertRaises(ValueError, QName, '') 174 self.assertRaises(ValueError, QName, None) 175 self.assertRaises(ValueError, QName, None, None) 176 self.assertRaises(ValueError, QName, 'test', '')
177
178 - def test_qname_none(self):
179 QName = self.etree.QName 180 q = QName(None, 'TAG') 181 self.assertEqual('TAG', q) 182 self.assertEqual('TAG', q.localname) 183 self.assertEqual(None, q.namespace)
184
185 - def test_qname_colon(self):
186 QName = self.etree.QName 187 self.assertRaises(ValueError, QName, 'p:name') 188 self.assertRaises(ValueError, QName, 'test', 'p:name')
189
190 - def test_qname_space(self):
191 QName = self.etree.QName 192 self.assertRaises(ValueError, QName, ' name ') 193 self.assertRaises(ValueError, QName, 'na me') 194 self.assertRaises(ValueError, QName, 'test', ' name')
195
197 # ET doesn't have namespace/localname properties on QNames 198 QName = self.etree.QName 199 namespace, localname = 'http://myns', 'a' 200 qname = QName(namespace, localname) 201 self.assertEqual(namespace, qname.namespace) 202 self.assertEqual(localname, qname.localname)
203
204 - def test_qname_element(self):
205 # ET doesn't have namespace/localname properties on QNames 206 QName = self.etree.QName 207 qname1 = QName('http://myns', 'a') 208 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'}) 209 210 qname2 = QName(a) 211 self.assertEqual(a.tag, qname1.text) 212 self.assertEqual(a.tag, qname1) 213 self.assertEqual(qname1.text, qname2.text) 214 self.assertEqual(qname1, qname2.text) 215 self.assertEqual(qname1.text, qname2) 216 self.assertEqual(qname1, qname2)
217
218 - def test_qname_text_resolve(self):
219 # ET doesn't resove QNames as text values 220 etree = self.etree 221 qname = etree.QName('http://myns', 'a') 222 a = etree.Element(qname, nsmap={'p' : 'http://myns'}) 223 a.text = qname 224 225 self.assertEqual("p:a", a.text)
226
227 - def test_nsmap_prefix_invalid(self):
228 etree = self.etree 229 self.assertRaises(ValueError, 230 etree.Element, "root", nsmap={'"' : 'testns'}) 231 self.assertRaises(ValueError, 232 etree.Element, "root", nsmap={'&' : 'testns'}) 233 self.assertRaises(ValueError, 234 etree.Element, "root", nsmap={'a:b' : 'testns'})
235
236 - def test_clear_keep_tail(self):
237 XML = self.etree.XML 238 tostring = self.etree.tostring 239 a = XML('<a aa="A"><b ba="B">B1</b>B2<c ca="C">C1</c>C2</a>') 240 a[0].clear(keep_tail=True) 241 self.assertEqual(_bytes('<a aa="A"><b/>B2<c ca="C">C1</c>C2</a>'), tostring(a))
242
243 - def test_attribute_has_key(self):
244 # ET in Py 3.x has no "attrib.has_key()" method 245 XML = self.etree.XML 246 247 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />')) 248 self.assertEqual( 249 True, root.attrib.has_key('bar')) 250 self.assertEqual( 251 False, root.attrib.has_key('baz')) 252 self.assertEqual( 253 False, root.attrib.has_key('hah')) 254 self.assertEqual( 255 True, 256 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
257
258 - def test_attribute_set(self):
259 Element = self.etree.Element 260 root = Element("root") 261 root.set("attr", "TEST") 262 self.assertEqual("TEST", root.get("attr"))
263
265 # ElementTree accepts arbitrary attribute values 266 # lxml.etree allows only strings 267 Element = self.etree.Element 268 269 root = Element("root") 270 root.set("attr", "TEST") 271 self.assertEqual("TEST", root.get("attr")) 272 self.assertRaises(TypeError, root.set, "newattr", 5)
273
274 - def test_attrib_and_keywords(self):
275 Element = self.etree.Element 276 277 root = Element("root") 278 root.set("attr", "TEST") 279 self.assertEqual("TEST", root.attrib["attr"]) 280 281 root2 = Element("root2", root.attrib, attr2='TOAST') 282 self.assertEqual("TEST", root2.attrib["attr"]) 283 self.assertEqual("TOAST", root2.attrib["attr2"]) 284 self.assertEqual(None, root.attrib.get("attr2"))
285
286 - def test_attrib_order(self):
287 Element = self.etree.Element 288 289 keys = ["attr%d" % i for i in range(12, 4, -1)] 290 values = ["TEST-%d" % i for i in range(12, 4, -1)] 291 items = list(zip(keys, values)) 292 293 root = Element("root") 294 for key, value in items: 295 root.set(key, value) 296 self.assertEqual(keys, root.attrib.keys()) 297 self.assertEqual(values, root.attrib.values()) 298 299 attr_order = [ 300 ('attr_99', 'TOAST-1'), 301 ('attr_98', 'TOAST-2'), 302 ] 303 ordered_dict_types = [OrderedDict, lambda x:x] 304 if sys.version_info >= (3, 6): 305 ordered_dict_types.append(dict) 306 else: 307 # Keyword arguments are not ordered in Py<3.6, and thus get sorted. 308 attr_order.sort() 309 attr_order += items 310 expected_keys = [attr[0] for attr in attr_order] 311 expected_values = [attr[1] for attr in attr_order] 312 expected_items = list(zip(expected_keys, expected_values)) 313 314 for dict_type in ordered_dict_types: 315 root2 = Element("root2", dict_type(root.attrib), 316 attr_99='TOAST-1', attr_98='TOAST-2') 317 318 try: 319 self.assertSequenceEqual(expected_keys, root2.attrib.keys()) 320 self.assertSequenceEqual(expected_values, root2.attrib.values()) 321 self.assertSequenceEqual(expected_items, root2.attrib.items()) 322 except AssertionError as exc: 323 exc.args = ("Order of '%s': %s" % (dict_type.__name__, exc.args[0]),) + exc.args[1:] 324 raise 325 326 self.assertEqual(keys, root.attrib.keys()) 327 self.assertEqual(values, root.attrib.values())
328
329 - def test_attribute_set_invalid(self):
330 # ElementTree accepts arbitrary attribute values 331 # lxml.etree allows only strings, or None for (html5) boolean attributes 332 Element = self.etree.Element 333 root = Element("root") 334 self.assertRaises(TypeError, root.set, "newattr", 5) 335 self.assertRaises(TypeError, root.set, "newattr", object) 336 self.assertRaises(TypeError, root.set, "newattr", None) 337 self.assertRaises(TypeError, root.set, "newattr")
338
339 - def test_strip_attributes(self):
340 XML = self.etree.XML 341 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>') 342 343 root = XML(xml) 344 self.etree.strip_attributes(root, 'a') 345 self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'), 346 self._writeElement(root)) 347 348 root = XML(xml) 349 self.etree.strip_attributes(root, 'b', 'c') 350 self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'), 351 self._writeElement(root))
352
353 - def test_strip_attributes_ns(self):
354 XML = self.etree.XML 355 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>') 356 357 root = XML(xml) 358 self.etree.strip_attributes(root, 'a') 359 self.assertEqual( 360 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'), 361 self._writeElement(root)) 362 363 root = XML(xml) 364 self.etree.strip_attributes(root, '{http://test/ns}a', 'c') 365 self.assertEqual( 366 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'), 367 self._writeElement(root)) 368 369 root = XML(xml) 370 self.etree.strip_attributes(root, '{http://test/ns}*') 371 self.assertEqual( 372 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'), 373 self._writeElement(root))
374
375 - def test_strip_elements(self):
376 XML = self.etree.XML 377 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>') 378 379 root = XML(xml) 380 self.etree.strip_elements(root, 'a') 381 self.assertEqual(_bytes('<test><x></x></test>'), 382 self._writeElement(root)) 383 384 root = XML(xml) 385 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z') 386 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'), 387 self._writeElement(root)) 388 389 root = XML(xml) 390 self.etree.strip_elements(root, 'c') 391 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'), 392 self._writeElement(root))
393
394 - def test_strip_elements_ns(self):
395 XML = self.etree.XML 396 xml = _bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"/>C</b>BT</n:a>AT<x>X<a>A<b xmlns="urn:a"/>BT<c xmlns="urn:x"/>CT</a>AT</x>XT</test>') 397 398 root = XML(xml) 399 self.etree.strip_elements(root, 'a') 400 self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>C</b>BT</n:a>AT<x>X</x>XT</test>'), 401 self._writeElement(root)) 402 403 root = XML(xml) 404 self.etree.strip_elements(root, '{urn:a}b', 'c') 405 self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>C</b>BT</n:a>AT<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 406 self._writeElement(root)) 407 408 root = XML(xml) 409 self.etree.strip_elements(root, '{urn:a}*', 'c') 410 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 411 self._writeElement(root)) 412 413 root = XML(xml) 414 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False) 415 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 416 self._writeElement(root))
417
418 - def test_strip_tags(self):
419 XML = self.etree.XML 420 xml = _bytes('<test>TEST<a>A<b>B<c/>CT</b>BT</a>AT<x>X<a>A<b/>BT<c/>CT</a>AT</x>XT</test>') 421 422 root = XML(xml) 423 self.etree.strip_tags(root, 'a') 424 self.assertEqual(_bytes('<test>TESTA<b>B<c></c>CT</b>BTAT<x>XA<b></b>BT<c></c>CTAT</x>XT</test>'), 425 self._writeElement(root)) 426 427 root = XML(xml) 428 self.etree.strip_tags(root, 'b', 'c', 'X', 'Y', 'Z') 429 self.assertEqual(_bytes('<test>TEST<a>ABCTBT</a>AT<x>X<a>ABTCT</a>AT</x>XT</test>'), 430 self._writeElement(root)) 431 432 root = XML(xml) 433 self.etree.strip_tags(root, 'c') 434 self.assertEqual(_bytes('<test>TEST<a>A<b>BCT</b>BT</a>AT<x>X<a>A<b></b>BTCT</a>AT</x>XT</test>'), 435 self._writeElement(root))
436
437 - def test_strip_tags_pi_comment(self):
438 XML = self.etree.XML 439 PI = self.etree.ProcessingInstruction 440 Comment = self.etree.Comment 441 xml = _bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT<?PI2?></test>\n<!--comment3-->\n<?PI1?>') 442 443 root = XML(xml) 444 self.etree.strip_tags(root, PI) 445 self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT</test>\n<!--comment3-->\n<?PI1?>'), 446 self._writeElement(root)) 447 448 root = XML(xml) 449 self.etree.strip_tags(root, Comment) 450 self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT<?PI2?></test>\n<!--comment3-->\n<?PI1?>'), 451 self._writeElement(root)) 452 453 root = XML(xml) 454 self.etree.strip_tags(root, PI, Comment) 455 self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT</test>\n<!--comment3-->\n<?PI1?>'), 456 self._writeElement(root)) 457 458 root = XML(xml) 459 self.etree.strip_tags(root, Comment, PI) 460 self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT</test>\n<!--comment3-->\n<?PI1?>'), 461 self._writeElement(root))
462
464 XML = self.etree.XML 465 ElementTree = self.etree.ElementTree 466 PI = self.etree.ProcessingInstruction 467 Comment = self.etree.Comment 468 xml = _bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT<?PI2?></test>\n<!--comment3-->\n<?PI1?>') 469 470 root = XML(xml) 471 self.etree.strip_tags(ElementTree(root), PI) 472 self.assertEqual(_bytes('<!--comment1-->\n<test>TEST<!--comment2-->XT</test>\n<!--comment3-->'), 473 self._writeElement(root)) 474 475 root = XML(xml) 476 self.etree.strip_tags(ElementTree(root), Comment) 477 self.assertEqual(_bytes('<?PI1?>\n<test>TESTXT<?PI2?></test>\n<?PI1?>'), 478 self._writeElement(root)) 479 480 root = XML(xml) 481 self.etree.strip_tags(ElementTree(root), PI, Comment) 482 self.assertEqual(_bytes('<test>TESTXT</test>'), 483 self._writeElement(root)) 484 485 root = XML(xml) 486 self.etree.strip_tags(ElementTree(root), Comment, PI) 487 self.assertEqual(_bytes('<test>TESTXT</test>'), 488 self._writeElement(root))
489
490 - def test_strip_tags_doc_style(self):
491 XML = self.etree.XML 492 xml = _bytes(''' 493 <div> 494 <div> 495 I like <strong>sheep</strong>. 496 <br/> 497 I like lots of <strong>sheep</strong>. 498 <br/> 499 Click <a href="http://www.sheep.com">here</a> 500 for <a href="http://www.sheep.com">those</a> sheep. 501 <br/> 502 </div> 503 </div> 504 '''.strip()) 505 506 root = XML(xml) 507 self.etree.strip_tags(root, 'a') 508 self.assertEqual(re.sub(_bytes('</?a[^>]*>'), _bytes(''), xml).replace(_bytes('<br/>'), _bytes('<br></br>')), 509 self._writeElement(root)) 510 511 root = XML(xml) 512 self.etree.strip_tags(root, 'a', 'br') 513 self.assertEqual(re.sub(_bytes('</?a[^>]*>'), _bytes(''), 514 re.sub(_bytes('<br[^>]*>'), _bytes(''), xml)), 515 self._writeElement(root))
516
517 - def test_strip_tags_ns(self):
518 XML = self.etree.XML 519 xml = _bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"/>CT</b>BT</n:a>AT<x>X<a>A<b xmlns="urn:a"/>BT<c xmlns="urn:x"/>CT</a>AT</x>XT</test>') 520 521 root = XML(xml) 522 self.etree.strip_tags(root, 'a') 523 self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>CT</b>BT</n:a>AT<x>XA<b xmlns="urn:a"></b>BT<c xmlns="urn:x"></c>CTAT</x>XT</test>'), 524 self._writeElement(root)) 525 526 root = XML(xml) 527 self.etree.strip_tags(root, '{urn:a}b', 'c') 528 self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>CT</b>BT</n:a>AT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 529 self._writeElement(root)) 530 531 root = XML(xml) 532 self.etree.strip_tags(root, '{urn:a}*', 'c') 533 self.assertEqual(_bytes('<test>TESTA<b>B<c xmlns="urn:c"></c>CT</b>BTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 534 self._writeElement(root))
535
536 - def test_strip_tags_and_remove(self):
537 # previously crashed 538 HTML = self.etree.HTML 539 root = HTML(_bytes('<div><h1>title</h1> <b>foo</b> <p>boo</p></div>'))[0][0] 540 self.assertEqual(_bytes('<div><h1>title</h1> <b>foo</b> <p>boo</p></div>'), 541 self.etree.tostring(root)) 542 self.etree.strip_tags(root, 'b') 543 self.assertEqual(_bytes('<div><h1>title</h1> foo <p>boo</p></div>'), 544 self.etree.tostring(root)) 545 root.remove(root[0]) 546 self.assertEqual(_bytes('<div><p>boo</p></div>'), 547 self.etree.tostring(root))
548
549 - def test_pi(self):
550 # lxml.etree separates target and text 551 Element = self.etree.Element 552 SubElement = self.etree.SubElement 553 ProcessingInstruction = self.etree.ProcessingInstruction 554 555 a = Element('a') 556 a.append(ProcessingInstruction('foo', 'some more text')) 557 self.assertEqual(a[0].target, 'foo') 558 self.assertEqual(a[0].text, 'some more text')
559
560 - def test_pi_parse(self):
561 XML = self.etree.XML 562 root = XML(_bytes("<test><?mypi my test ?></test>")) 563 self.assertEqual(root[0].target, "mypi") 564 self.assertEqual(root[0].text, "my test ")
565
567 XML = self.etree.XML 568 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 569 self.assertEqual(root[0].target, "mypi") 570 self.assertEqual(root[0].get('my'), "1") 571 self.assertEqual(root[0].get('test'), " abc ") 572 self.assertEqual(root[0].get('quotes'), "' '") 573 self.assertEqual(root[0].get('only'), None) 574 self.assertEqual(root[0].get('names'), None) 575 self.assertEqual(root[0].get('nope'), None)
576
578 XML = self.etree.XML 579 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 580 self.assertEqual(root[0].target, "mypi") 581 self.assertEqual(root[0].attrib['my'], "1") 582 self.assertEqual(root[0].attrib['test'], " abc ") 583 self.assertEqual(root[0].attrib['quotes'], "' '") 584 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only') 585 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names') 586 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
587
588 - def test_deepcopy_pi(self):
589 # previously caused a crash 590 ProcessingInstruction = self.etree.ProcessingInstruction 591 592 a = ProcessingInstruction("PI", "ONE") 593 b = copy.deepcopy(a) 594 b.text = "ANOTHER" 595 596 self.assertEqual('ONE', a.text) 597 self.assertEqual('ANOTHER', b.text)
598
600 XML = self.etree.XML 601 tostring = self.etree.tostring 602 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->")) 603 tree1 = self.etree.ElementTree(root) 604 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 605 tostring(tree1)) 606 607 tree2 = copy.deepcopy(tree1) 608 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 609 tostring(tree2)) 610 611 root2 = copy.deepcopy(tree1.getroot()) 612 self.assertEqual(_bytes("<test/>"), 613 tostring(root2))
614
616 XML = self.etree.XML 617 tostring = self.etree.tostring 618 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>') 619 root = XML(xml) 620 tree1 = self.etree.ElementTree(root) 621 self.assertEqual(xml, tostring(tree1)) 622 623 tree2 = copy.deepcopy(tree1) 624 self.assertEqual(xml, tostring(tree2)) 625 626 root2 = copy.deepcopy(tree1.getroot()) 627 self.assertEqual(_bytes("<test/>"), 628 tostring(root2))
629
630 - def test_deepcopy_pi_dtd(self):
631 XML = self.etree.XML 632 tostring = self.etree.tostring 633 xml = _bytes('<!-- comment --><!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>') 634 root = XML(xml) 635 tree1 = self.etree.ElementTree(root) 636 self.assertEqual(xml, tostring(tree1)) 637 638 tree2 = copy.deepcopy(tree1) 639 self.assertEqual(xml, tostring(tree2))
640
641 - def test_parse_remove_comments(self):
642 fromstring = self.etree.fromstring 643 tostring = self.etree.tostring 644 XMLParser = self.etree.XMLParser 645 646 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 647 parser = XMLParser(remove_comments=True) 648 root = fromstring(xml, parser) 649 self.assertEqual( 650 _bytes('<a><b><c/></b></a>'), 651 tostring(root))
652
653 - def test_parse_remove_pis(self):
654 parse = self.etree.parse 655 tostring = self.etree.tostring 656 XMLParser = self.etree.XMLParser 657 658 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>') 659 660 f = BytesIO(xml) 661 tree = parse(f) 662 self.assertEqual( 663 xml, 664 tostring(tree)) 665 666 parser = XMLParser(remove_pis=True) 667 tree = parse(f, parser) 668 self.assertEqual( 669 _bytes('<a><b><c/></b></a>'), 670 tostring(tree))
671
673 # ET raises IOError only 674 parse = self.etree.parse 675 self.assertRaises(TypeError, parse, 'notthere.xml', object())
676
678 # ET removes comments 679 iterparse = self.etree.iterparse 680 tostring = self.etree.tostring 681 682 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 683 events = list(iterparse(f)) 684 root = events[-1][1] 685 self.assertEqual(3, len(events)) 686 self.assertEqual( 687 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 688 tostring(root))
689
690 - def test_iterparse_comments(self):
691 # ET removes comments 692 iterparse = self.etree.iterparse 693 tostring = self.etree.tostring 694 695 def name(event, el): 696 if event == 'comment': 697 return el.text 698 else: 699 return el.tag
700 701 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 702 events = list(iterparse(f, events=('end', 'comment'))) 703 root = events[-1][1] 704 self.assertEqual(6, len(events)) 705 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'], 706 [ name(*item) for item in events ]) 707 self.assertEqual( 708 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 709 tostring(root))
710
711 - def test_iterparse_pis(self):
712 # ET removes pis 713 iterparse = self.etree.iterparse 714 tostring = self.etree.tostring 715 ElementTree = self.etree.ElementTree 716 717 def name(event, el): 718 if event == 'pi': 719 return el.target, el.text 720 else: 721 return el.tag
722 723 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>') 724 events = list(iterparse(f, events=('end', 'pi'))) 725 root = events[-2][1] 726 self.assertEqual(8, len(events)) 727 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b', 728 ('pid','d'), 'a', ('pie','e')], 729 [ name(*item) for item in events ]) 730 self.assertEqual( 731 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'), 732 tostring(ElementTree(root))) 733
734 - def test_iterparse_remove_comments(self):
735 iterparse = self.etree.iterparse 736 tostring = self.etree.tostring 737 738 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 739 events = list(iterparse(f, remove_comments=True, 740 events=('end', 'comment'))) 741 root = events[-1][1] 742 self.assertEqual(3, len(events)) 743 self.assertEqual(['c', 'b', 'a'], 744 [ el.tag for (event, el) in events ]) 745 self.assertEqual( 746 _bytes('<a><b><c/></b></a>'), 747 tostring(root))
748
749 - def test_iterparse_broken(self):
750 iterparse = self.etree.iterparse 751 f = BytesIO('<a><b><c/></a>') 752 # ET raises ExpatError, lxml raises XMLSyntaxError 753 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
754
755 - def test_iterparse_broken_recover(self):
756 iterparse = self.etree.iterparse 757 f = BytesIO('<a><b><c/></a>') 758 it = iterparse(f, events=('start', 'end'), recover=True) 759 events = [(ev, el.tag) for ev, el in it] 760 root = it.root 761 self.assertTrue(root is not None) 762 763 self.assertEqual(1, events.count(('start', 'a'))) 764 self.assertEqual(1, events.count(('end', 'a'))) 765 766 self.assertEqual(1, events.count(('start', 'b'))) 767 self.assertEqual(1, events.count(('end', 'b'))) 768 769 self.assertEqual(1, events.count(('start', 'c'))) 770 self.assertEqual(1, events.count(('end', 'c')))
771
772 - def test_iterparse_broken_multi_recover(self):
773 iterparse = self.etree.iterparse 774 f = BytesIO('<a><b><c/></d><b><c/></a></b>') 775 it = iterparse(f, events=('start', 'end'), recover=True) 776 events = [(ev, el.tag) for ev, el in it] 777 root = it.root 778 self.assertTrue(root is not None) 779 780 self.assertEqual(1, events.count(('start', 'a'))) 781 self.assertEqual(1, events.count(('end', 'a'))) 782 783 self.assertEqual(2, events.count(('start', 'b'))) 784 self.assertEqual(2, events.count(('end', 'b'))) 785 786 self.assertEqual(2, events.count(('start', 'c'))) 787 self.assertEqual(2, events.count(('end', 'c')))
788
789 - def test_iterparse_strip(self):
790 iterparse = self.etree.iterparse 791 f = BytesIO(""" 792 <a> \n \n <b> b test </b> \n 793 794 \n\t <c> \n </c> </a> \n """) 795 iterator = iterparse(f, remove_blank_text=True) 796 text = [ (element.text, element.tail) 797 for event, element in iterator ] 798 self.assertEqual( 799 [(" b test ", None), (" \n ", None), (None, None)], 800 text)
801
802 - def test_iterparse_tag(self):
803 iterparse = self.etree.iterparse 804 f = BytesIO('<a><b><d/></b><c/></a>') 805 806 iterator = iterparse(f, tag="b", events=('start', 'end')) 807 events = list(iterator) 808 root = iterator.root 809 self.assertEqual( 810 [('start', root[0]), ('end', root[0])], 811 events)
812
813 - def test_iterparse_tag_all(self):
814 iterparse = self.etree.iterparse 815 f = BytesIO('<a><b><d/></b><c/></a>') 816 817 iterator = iterparse(f, tag="*", events=('start', 'end')) 818 events = list(iterator) 819 self.assertEqual( 820 8, 821 len(events))
822
823 - def test_iterparse_tag_ns(self):
824 iterparse = self.etree.iterparse 825 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 826 827 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end')) 828 events = list(iterator) 829 root = iterator.root 830 self.assertEqual( 831 [('start', root[0]), ('end', root[0])], 832 events)
833
834 - def test_iterparse_tag_ns_empty(self):
835 iterparse = self.etree.iterparse 836 f = BytesIO('<a><b><d/></b><c/></a>') 837 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 838 events = list(iterator) 839 root = iterator.root 840 self.assertEqual( 841 [('start', root[0]), ('end', root[0])], 842 events) 843 844 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 845 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 846 events = list(iterator) 847 root = iterator.root 848 self.assertEqual([], events)
849
850 - def test_iterparse_tag_ns_all(self):
851 iterparse = self.etree.iterparse 852 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 853 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end')) 854 events = list(iterator) 855 self.assertEqual(8, len(events))
856
857 - def test_iterparse_tag_ns_empty_all(self):
858 iterparse = self.etree.iterparse 859 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 860 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 861 events = list(iterator) 862 self.assertEqual([], events) 863 864 f = BytesIO('<a><b><d/></b><c/></a>') 865 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 866 events = list(iterator) 867 self.assertEqual(8, len(events))
868
869 - def test_iterparse_encoding_error(self):
870 text = _str('Søk på nettet') 871 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 872 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 873 ).encode('iso-8859-1') 874 875 self.assertRaises(self.etree.ParseError, 876 list, self.etree.iterparse(BytesIO(xml_latin1)))
877
878 - def test_iterparse_encoding_8bit_override(self):
879 text = _str('Søk på nettet', encoding="UTF-8") 880 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 881 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 882 ).encode('iso-8859-1') 883 884 iterator = self.etree.iterparse(BytesIO(xml_latin1), 885 encoding="iso-8859-1") 886 self.assertEqual(1, len(list(iterator))) 887 888 a = iterator.root 889 self.assertEqual(a.text, text)
890
891 - def test_iterparse_keep_cdata(self):
892 tostring = self.etree.tostring 893 f = BytesIO('<root><![CDATA[test]]></root>') 894 context = self.etree.iterparse(f, strip_cdata=False) 895 content = [ el.text for event,el in context ] 896 897 self.assertEqual(['test'], content) 898 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 899 tostring(context.root))
900
901 - def test_parser_encoding_unknown(self):
902 self.assertRaises( 903 LookupError, self.etree.XMLParser, encoding="hopefully unknown")
904
905 - def test_parser_encoding(self):
906 self.etree.XMLParser(encoding="ascii") 907 self.etree.XMLParser(encoding="utf-8") 908 self.etree.XMLParser(encoding="iso-8859-1")
909
910 - def test_feed_parser_recover(self):
911 parser = self.etree.XMLParser(recover=True) 912 913 parser.feed('<?xml version=') 914 parser.feed('"1.0"?><ro') 915 parser.feed('ot><') 916 parser.feed('a test="works"') 917 parser.feed('><othertag/></root') # <a> not closed! 918 parser.feed('>') 919 920 root = parser.close() 921 922 self.assertEqual(root.tag, "root") 923 self.assertEqual(len(root), 1) 924 self.assertEqual(root[0].tag, "a") 925 self.assertEqual(root[0].get("test"), "works") 926 self.assertEqual(len(root[0]), 1) 927 self.assertEqual(root[0][0].tag, "othertag")
928 # FIXME: would be nice to get some errors logged ... 929 #self.assertTrue(len(parser.error_log) > 0, "error log is empty") 930
931 - def test_feed_parser_recover_no_id_dict(self):
932 # test that recover mode plays nicely with the no-id-dict setup 933 parser = self.etree.XMLParser(recover=True, collect_ids=False) 934 935 parser.feed('<?xml version=') 936 parser.feed('"1.0"?><ro') 937 parser.feed('ot xml:id="123"><') 938 parser.feed('a test="works" xml:id=') 939 parser.feed('"321"><othertag/></root') # <a> not closed! 940 parser.feed('>') 941 942 root = parser.close() 943 944 self.assertEqual(root.tag, "root") 945 self.assertEqual(len(root), 1) 946 self.assertEqual(root[0].tag, "a") 947 self.assertEqual(root[0].get("test"), "works") 948 self.assertEqual(root[0].attrib, { 949 'test': 'works', 950 '{http://www.w3.org/XML/1998/namespace}id': '321'}) 951 self.assertEqual(len(root[0]), 1) 952 self.assertEqual(root[0][0].tag, "othertag")
953 # FIXME: would be nice to get some errors logged ... 954 #self.assertTrue(len(parser.error_log) > 0, "error log is empty") 955
956 - def test_elementtree_parser_target_type_error(self):
957 assertEqual = self.assertEqual 958 assertFalse = self.assertFalse 959 960 events = [] 961 class Target(object): 962 def start(self, tag, attrib): 963 events.append("start") 964 assertFalse(attrib) 965 assertEqual("TAG", tag)
966 def end(self, tag): 967 events.append("end") 968 assertEqual("TAG", tag) 969 def close(self): 970 return "DONE" # no Element! 971 972 parser = self.etree.XMLParser(target=Target()) 973 tree = self.etree.ElementTree() 974 975 self.assertRaises(TypeError, 976 tree.parse, BytesIO("<TAG/>"), parser=parser) 977 self.assertEqual(["start", "end"], events) 978
979 - def test_parser_target_feed_exception(self):
980 # ET doesn't call .close() on errors 981 events = [] 982 class Target(object): 983 def start(self, tag, attrib): 984 events.append("start-" + tag)
985 def end(self, tag): 986 events.append("end-" + tag) 987 if tag == 'a': 988 raise ValueError("dead and gone") 989 def data(self, data): 990 events.append("data-" + data) 991 def close(self): 992 events.append("close") 993 return "DONE" 994 995 parser = self.etree.XMLParser(target=Target()) 996 997 try: 998 parser.feed(_bytes('<root>A<a>ca</a>B</root>')) 999 done = parser.close() 1000 self.fail("error expected, but parsing succeeded") 1001 except ValueError: 1002 done = 'value error received as expected' 1003 1004 self.assertEqual(["start-root", "data-A", "start-a", 1005 "data-ca", "end-a", "close"], 1006 events) 1007
1008 - def test_parser_target_fromstring_exception(self):
1009 # ET doesn't call .close() on errors 1010 events = [] 1011 class Target(object): 1012 def start(self, tag, attrib): 1013 events.append("start-" + tag)
1014 def end(self, tag): 1015 events.append("end-" + tag) 1016 if tag == 'a': 1017 raise ValueError("dead and gone") 1018 def data(self, data): 1019 events.append("data-" + data) 1020 def close(self): 1021 events.append("close") 1022 return "DONE" 1023 1024 parser = self.etree.XMLParser(target=Target()) 1025 1026 try: 1027 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'), 1028 parser=parser) 1029 self.fail("error expected, but parsing succeeded") 1030 except ValueError: 1031 done = 'value error received as expected' 1032 1033 self.assertEqual(["start-root", "data-A", "start-a", 1034 "data-ca", "end-a", "close"], 1035 events) 1036
1037 - def test_parser_target_feed_no_id_dict(self):
1038 # test that target parsing works nicely with the no-id-hash setup 1039 events = [] 1040 class Target(object): 1041 def start(self, tag, attrib): 1042 events.append("start-" + tag)
1043 def end(self, tag): 1044 events.append("end-" + tag) 1045 def data(self, data): 1046 events.append("data-" + data) 1047 def comment(self, text): 1048 events.append("comment-" + text) 1049 def close(self): 1050 return "DONE" 1051 1052 parser = self.etree.XMLParser(target=Target(), collect_ids=False) 1053 1054 parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->')) 1055 parser.feed(_bytes('<sub xml:id="321"/>B</root>')) 1056 done = parser.close() 1057 1058 self.assertEqual("DONE", done) 1059 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b", 1060 "start-sub", "end-sub", "data-B", "end-root"], 1061 events) 1062
1063 - def test_parser_target_comment(self):
1064 events = [] 1065 class Target(object): 1066 def start(self, tag, attrib): 1067 events.append("start-" + tag)
1068 def end(self, tag): 1069 events.append("end-" + tag) 1070 def data(self, data): 1071 events.append("data-" + data) 1072 def comment(self, text): 1073 events.append("comment-" + text) 1074 def close(self): 1075 return "DONE" 1076 1077 parser = self.etree.XMLParser(target=Target()) 1078 1079 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->')) 1080 done = parser.close() 1081 1082 self.assertEqual("DONE", done) 1083 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b", 1084 "start-sub", "end-sub", "comment-c", "data-B", 1085 "end-root", "comment-d"], 1086 events) 1087
1088 - def test_parser_target_pi(self):
1089 events = [] 1090 class Target(object): 1091 def start(self, tag, attrib): 1092 events.append("start-" + tag)
1093 def end(self, tag): 1094 events.append("end-" + tag) 1095 def data(self, data): 1096 events.append("data-" + data) 1097 def pi(self, target, data): 1098 events.append("pi-" + target + "-" + data) 1099 def close(self): 1100 return "DONE" 1101 1102 parser = self.etree.XMLParser(target=Target()) 1103 1104 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>')) 1105 done = parser.close() 1106 1107 self.assertEqual("DONE", done) 1108 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b", 1109 "data-B", "end-root", "pi-test-c"], 1110 events) 1111
1112 - def test_parser_target_cdata(self):
1113 events = [] 1114 class Target(object): 1115 def start(self, tag, attrib): 1116 events.append("start-" + tag)
1117 def end(self, tag): 1118 events.append("end-" + tag) 1119 def data(self, data): 1120 events.append("data-" + data) 1121 def close(self): 1122 return "DONE" 1123 1124 parser = self.etree.XMLParser(target=Target(), 1125 strip_cdata=False) 1126 1127 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>')) 1128 done = parser.close() 1129 1130 self.assertEqual("DONE", done) 1131 self.assertEqual(["start-root", "data-A", "start-a", 1132 "data-ca", "end-a", "data-B", "end-root"], 1133 events) 1134
1135 - def test_parser_target_recover(self):
1136 events = [] 1137 class Target(object): 1138 def start(self, tag, attrib): 1139 events.append("start-" + tag)
1140 def end(self, tag): 1141 events.append("end-" + tag) 1142 def data(self, data): 1143 events.append("data-" + data) 1144 def close(self): 1145 events.append("close") 1146 return "DONE" 1147 1148 parser = self.etree.XMLParser(target=Target(), 1149 recover=True) 1150 1151 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>')) 1152 done = parser.close() 1153 1154 self.assertEqual("DONE", done) 1155 self.assertEqual(["start-root", "data-A", "start-a", 1156 "data-ca", "end-a", "data-B", 1157 "end-root", "close"], 1158 events) 1159
1160 - def test_iterwalk_tag(self):
1161 iterwalk = self.etree.iterwalk 1162 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1163 1164 iterator = iterwalk(root, tag="b", events=('start', 'end')) 1165 events = list(iterator) 1166 self.assertEqual( 1167 [('start', root[0]), ('end', root[0])], 1168 events)
1169
1170 - def test_iterwalk_tag_all(self):
1171 iterwalk = self.etree.iterwalk 1172 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1173 1174 iterator = iterwalk(root, tag="*", events=('start', 'end')) 1175 events = list(iterator) 1176 self.assertEqual( 1177 8, 1178 len(events))
1179
1180 - def test_iterwalk(self):
1181 iterwalk = self.etree.iterwalk 1182 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1183 1184 events = list(iterwalk(root)) 1185 self.assertEqual( 1186 [('end', root[0]), ('end', root[1]), ('end', root)], 1187 events)
1188
1189 - def test_iterwalk_comments_root_element(self):
1190 iterwalk = self.etree.iterwalk 1191 root = self.etree.XML( 1192 b'<!--C0--><a><!--Ca--><b><!--Cb--></b><!--Cc--><c/></a><!--C99-->') 1193 1194 iterator = iterwalk(root, events=('start', 'end', 'comment')) 1195 events = list(iterator) 1196 self.assertEqual( 1197 [('start', root), ('comment', root[0]), 1198 ('start', root[1]), ('comment', root[1][0]), ('end', root[1]), 1199 ('comment', root[2]), ('start', root[3]), ('end', root[3]), 1200 ('end', root), 1201 ], 1202 events)
1203
1204 - def test_iterwalk_comments_tree(self):
1205 iterwalk = self.etree.iterwalk 1206 root = self.etree.XML( 1207 b'<!--C0--><a><!--Ca--><b><!--Cb--></b><!--Cc--><c/></a><!--C99-->') 1208 1209 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'comment')) 1210 events = list(iterator) 1211 self.assertEqual( 1212 [('comment', root.getprevious()), 1213 ('start', root), ('comment', root[0]), # <a> 1214 ('start', root[1]), ('comment', root[1][0]), ('end', root[1]), # <b> 1215 ('comment', root[2]), ('start', root[3]), ('end', root[3]), # <c> 1216 ('end', root), ('comment', root.getnext()), 1217 ], 1218 events)
1219
1220 - def test_iterwalk_pis_root_element(self):
1221 iterwalk = self.etree.iterwalk 1222 root = self.etree.XML( 1223 b'<?C0?><a><?Ca?><b><?Cb?></b><?Cc?><c/></a><?C99?>') 1224 1225 iterator = iterwalk(root, events=('start', 'end', 'pi')) 1226 events = list(iterator) 1227 self.assertEqual( 1228 [('start', root), ('pi', root[0]), 1229 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]), 1230 ('pi', root[2]), ('start', root[3]), ('end', root[3]), 1231 ('end', root), 1232 ], 1233 events)
1234
1235 - def test_iterwalk_pis_tree(self):
1236 iterwalk = self.etree.iterwalk 1237 root = self.etree.XML( 1238 b'<?C0?><a><?Ca?><b><?Cb?></b><?Cc?><c/></a><?C99?>') 1239 1240 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'pi')) 1241 events = list(iterator) 1242 self.assertEqual( 1243 [('pi', root.getprevious()), 1244 ('start', root), ('pi', root[0]), # <a> 1245 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]), # <b> 1246 ('pi', root[2]), ('start', root[3]), ('end', root[3]), # <c> 1247 ('end', root), ('pi', root.getnext()), 1248 ], 1249 events)
1250
1251 - def test_iterwalk_pis_comments_tree(self):
1252 iterwalk = self.etree.iterwalk 1253 root = self.etree.XML( 1254 b'<!--C0--><?C0?><!--C1--><a><?Ca?><b><!--Cb--></b><?Cc?><c/></a><!--C99--><?C99?>') 1255 1256 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'pi', 'comment')) 1257 events = list(iterator) 1258 self.assertEqual( 1259 [('comment', root.getprevious().getprevious().getprevious()), 1260 ('pi', root.getprevious().getprevious()), 1261 ('comment', root.getprevious()), 1262 ('start', root), ('pi', root[0]), # <a> 1263 ('start', root[1]), ('comment', root[1][0]), ('end', root[1]), # <b> 1264 ('pi', root[2]), ('start', root[3]), ('end', root[3]), # <c> 1265 ('end', root), ('comment', root.getnext()), ('pi', root.getnext().getnext()), 1266 ], 1267 events)
1268
1269 - def test_iterwalk_pis_comments_tree_no_events(self):
1270 iterwalk = self.etree.iterwalk 1271 root = self.etree.XML( 1272 b'<!--C0--><?C0?><!--C1--><a><?Ca?><b><!--Cb--></b><?Cc?><c/></a><!--C99--><?C99?>') 1273 1274 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end')) 1275 events = list(iterator) 1276 self.assertEqual( 1277 [('start', root), # <a> 1278 ('start', root[1]), ('end', root[1]), # <b> 1279 ('start', root[3]), ('end', root[3]), # <c> 1280 ('end', root), 1281 ], 1282 events)
1283
1284 - def test_iterwalk_start(self):
1285 iterwalk = self.etree.iterwalk 1286 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1287 1288 iterator = iterwalk(root, events=('start',)) 1289 events = list(iterator) 1290 self.assertEqual( 1291 [('start', root), ('start', root[0]), ('start', root[1])], 1292 events)
1293
1294 - def test_iterwalk_start_end(self):
1295 iterwalk = self.etree.iterwalk 1296 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1297 1298 iterator = iterwalk(root, events=('start','end')) 1299 events = list(iterator) 1300 self.assertEqual( 1301 [('start', root), ('start', root[0]), ('end', root[0]), 1302 ('start', root[1]), ('end', root[1]), ('end', root)], 1303 events)
1304
1305 - def test_iterwalk_start_tags(self):
1306 iterwalk = self.etree.iterwalk 1307 root = self.etree.XML(_bytes('<a><b></b><c/><b><d/></b></a>')) 1308 1309 iterator = iterwalk(root, events=('start',), tag='b') 1310 events = list(iterator) 1311 self.assertEqual( 1312 [('start', root[0]), ('start', root[2])], 1313 events)
1314
1315 - def test_iterwalk_start_end_tags(self):
1316 iterwalk = self.etree.iterwalk 1317 root = self.etree.XML(_bytes('<a><b></b><c/><b><d/></b></a>')) 1318 1319 iterator = iterwalk(root, events=('start', 'end'), tag='b') 1320 events = list(iterator) 1321 self.assertEqual( 1322 [('start', root[0]), ('end', root[0]), ('start', root[2]), ('end', root[2])], 1323 events)
1324
1325 - def test_iterwalk_start_end_tags_with_root(self):
1326 iterwalk = self.etree.iterwalk 1327 root = self.etree.XML(_bytes('<a><b></b><c/><b><d/></b></a>')) 1328 1329 iterator = iterwalk(root, events=('start', 'end'), tag=('b', 'a')) 1330 events = list(iterator) 1331 self.assertEqual( 1332 [('start', root), 1333 ('start', root[0]), ('end', root[0]), 1334 ('start', root[2]), ('end', root[2]), 1335 ('end', root), 1336 ], 1337 events)
1338
1339 - def test_iterwalk_clear(self):
1340 iterwalk = self.etree.iterwalk 1341 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1342 1343 iterator = iterwalk(root) 1344 for event, elem in iterator: 1345 elem.clear() 1346 1347 self.assertEqual(0, 1348 len(root))
1349
1350 - def test_iterwalk_attrib_ns(self):
1351 iterwalk = self.etree.iterwalk 1352 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>')) 1353 1354 attr_name = '{testns}bla' 1355 events = [] 1356 iterator = iterwalk(root, events=('start','end','start-ns','end-ns')) 1357 for event, elem in iterator: 1358 events.append(event) 1359 if event == 'start': 1360 if elem.tag != '{ns1}a': 1361 elem.set(attr_name, 'value') 1362 1363 self.assertEqual( 1364 ['start-ns', 'start', 'start', 'start-ns', 'start', 1365 'end', 'end-ns', 'end', 'end', 'end-ns'], 1366 events) 1367 1368 self.assertEqual( 1369 None, 1370 root.get(attr_name)) 1371 self.assertEqual( 1372 'value', 1373 root[0].get(attr_name))
1374
1375 - def test_iterwalk_end_skip(self):
1376 iterwalk = self.etree.iterwalk 1377 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>')) 1378 1379 iterator = iterwalk(root) 1380 tags = [] 1381 for event, elem in iterator: 1382 tags.append(elem.tag) 1383 # requesting a skip after an 'end' event should never have an effect 1384 iterator.skip_subtree() 1385 1386 self.assertEqual(['c', 'b', 'e', 'd', 'a'], tags)
1387
1388 - def test_iterwalk_start_end_skip(self):
1389 iterwalk = self.etree.iterwalk 1390 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>')) 1391 1392 iterator = iterwalk(root, events=('start', 'end')) 1393 tags = [] 1394 for event, elem in iterator: 1395 tags.append((event, elem.tag)) 1396 if elem.tag in ('b', 'e'): 1397 # skipping should only have an effect on 'start', not on 'end' 1398 iterator.skip_subtree() 1399 1400 self.assertEqual( 1401 [('start', 'a'), 1402 ('start', 'b'), ('end', 'b'), # ignored child 'c' 1403 ('start', 'd'), 1404 ('start', 'e'), ('end', 'e'), 1405 ('end', 'd'), 1406 ('end', 'a')], 1407 tags)
1408
1409 - def test_iterwalk_ns_skip(self):
1410 iterwalk = self.etree.iterwalk 1411 root = self.etree.XML(_bytes( 1412 '<a xmlns="ns1"><b xmlns="nsb"><c xmlns="ns2"/></b><d xmlns="ns2"><e/></d></a>')) 1413 1414 events = [] 1415 iterator = iterwalk(root, events=('start','start-ns','end-ns')) 1416 for event, elem in iterator: 1417 if event in ('start-ns', 'end-ns'): 1418 events.append((event, elem)) 1419 if event == 'start-ns' and elem == ('', 'nsb'): 1420 events.append('skip') 1421 iterator.skip_subtree() 1422 else: 1423 events.append((event, elem.tag)) 1424 1425 self.assertEqual( 1426 [('start-ns', ('', 'ns1')), 1427 ('start', '{ns1}a'), 1428 ('start-ns', ('', 'nsb')), 1429 'skip', 1430 ('start', '{nsb}b'), 1431 ('end-ns', None), 1432 ('start-ns', ('', 'ns2')), 1433 ('start', '{ns2}d'), 1434 ('start', '{ns2}e'), 1435 ('end-ns', None), 1436 ('end-ns', None) 1437 ], 1438 events)
1439
1440 - def test_iterwalk_getiterator(self):
1441 iterwalk = self.etree.iterwalk 1442 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1443 1444 counts = [] 1445 for event, elem in iterwalk(root): 1446 counts.append(len(list(elem.getiterator()))) 1447 self.assertEqual( 1448 [1,2,1,4], 1449 counts)
1450
1451 - def test_resolve_string_dtd(self):
1452 parse = self.etree.parse 1453 parser = self.etree.XMLParser(dtd_validation=True) 1454 assertEqual = self.assertEqual 1455 test_url = _str("__nosuch.dtd") 1456 1457 class MyResolver(self.etree.Resolver): 1458 def resolve(self, url, id, context): 1459 assertEqual(url, test_url) 1460 return self.resolve_string( 1461 _str('''<!ENTITY myentity "%s"> 1462 <!ELEMENT doc ANY>''') % url, context)
1463 1464 parser.resolvers.add(MyResolver()) 1465 1466 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1467 tree = parse(StringIO(xml), parser) 1468 root = tree.getroot() 1469 self.assertEqual(root.text, test_url) 1470
1471 - def test_resolve_bytes_dtd(self):
1472 parse = self.etree.parse 1473 parser = self.etree.XMLParser(dtd_validation=True) 1474 assertEqual = self.assertEqual 1475 test_url = _str("__nosuch.dtd") 1476 1477 class MyResolver(self.etree.Resolver): 1478 def resolve(self, url, id, context): 1479 assertEqual(url, test_url) 1480 return self.resolve_string( 1481 (_str('''<!ENTITY myentity "%s"> 1482 <!ELEMENT doc ANY>''') % url).encode('utf-8'), 1483 context)
1484 1485 parser.resolvers.add(MyResolver()) 1486 1487 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1488 tree = parse(StringIO(xml), parser) 1489 root = tree.getroot() 1490 self.assertEqual(root.text, test_url) 1491
1492 - def test_resolve_filelike_dtd(self):
1493 parse = self.etree.parse 1494 parser = self.etree.XMLParser(dtd_validation=True) 1495 assertEqual = self.assertEqual 1496 test_url = _str("__nosuch.dtd") 1497 1498 class MyResolver(self.etree.Resolver): 1499 def resolve(self, url, id, context): 1500 assertEqual(url, test_url) 1501 return self.resolve_file( 1502 SillyFileLike( 1503 _str('''<!ENTITY myentity "%s"> 1504 <!ELEMENT doc ANY>''') % url), context)
1505 1506 parser.resolvers.add(MyResolver()) 1507 1508 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1509 tree = parse(StringIO(xml), parser) 1510 root = tree.getroot() 1511 self.assertEqual(root.text, test_url) 1512
1513 - def test_resolve_filename_dtd(self):
1514 parse = self.etree.parse 1515 parser = self.etree.XMLParser(attribute_defaults=True) 1516 assertEqual = self.assertEqual 1517 test_url = _str("__nosuch.dtd") 1518 1519 class MyResolver(self.etree.Resolver): 1520 def resolve(self, url, id, context): 1521 assertEqual(url, test_url) 1522 return self.resolve_filename( 1523 fileInTestDir('test.dtd'), context)
1524 1525 parser.resolvers.add(MyResolver()) 1526 1527 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1528 tree = parse(StringIO(xml), parser) 1529 root = tree.getroot() 1530 self.assertEqual( 1531 root.attrib, {'default': 'valueA'}) 1532 self.assertEqual( 1533 root[0].attrib, {'default': 'valueB'}) 1534
1535 - def test_resolve_filename_dtd_relative(self):
1536 parse = self.etree.parse 1537 parser = self.etree.XMLParser(attribute_defaults=True) 1538 assertEqual = self.assertEqual 1539 test_url = _str("__nosuch.dtd") 1540 1541 class MyResolver(self.etree.Resolver): 1542 def resolve(self, url, id, context): 1543 expected = fileUrlInTestDir(test_url) 1544 url = url.replace('file://', 'file:') # depends on libxml2 version 1545 expected = expected.replace('file://', 'file:') 1546 assertEqual(url, expected) 1547 return self.resolve_filename( 1548 fileUrlInTestDir('test.dtd'), context)
1549 1550 parser.resolvers.add(MyResolver()) 1551 1552 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1553 tree = parse(StringIO(xml), parser, 1554 base_url=fileUrlInTestDir('__test.xml')) 1555 root = tree.getroot() 1556 self.assertEqual( 1557 root.attrib, {'default': 'valueA'}) 1558 self.assertEqual( 1559 root[0].attrib, {'default': 'valueB'}) 1560
1561 - def test_resolve_file_dtd(self):
1562 parse = self.etree.parse 1563 parser = self.etree.XMLParser(attribute_defaults=True) 1564 assertEqual = self.assertEqual 1565 test_url = _str("__nosuch.dtd") 1566 1567 class MyResolver(self.etree.Resolver): 1568 def resolve(self, url, id, context): 1569 assertEqual(url, test_url) 1570 return self.resolve_file( 1571 open(fileInTestDir('test.dtd'), 'rb'), context)
1572 1573 parser.resolvers.add(MyResolver()) 1574 1575 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1576 tree = parse(StringIO(xml), parser) 1577 root = tree.getroot() 1578 self.assertEqual( 1579 root.attrib, {'default': 'valueA'}) 1580 self.assertEqual( 1581 root[0].attrib, {'default': 'valueB'}) 1582
1583 - def test_resolve_empty(self):
1584 parse = self.etree.parse 1585 parser = self.etree.XMLParser(load_dtd=True) 1586 assertEqual = self.assertEqual 1587 test_url = _str("__nosuch.dtd") 1588 1589 class check(object): 1590 resolved = False
1591 1592 class MyResolver(self.etree.Resolver): 1593 def resolve(self, url, id, context): 1594 assertEqual(url, test_url) 1595 check.resolved = True 1596 return self.resolve_empty(context) 1597 1598 parser.resolvers.add(MyResolver()) 1599 1600 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1601 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser) 1602 self.assertTrue(check.resolved) 1603
1604 - def test_resolve_error(self):
1605 parse = self.etree.parse 1606 parser = self.etree.XMLParser(dtd_validation=True) 1607 1608 class _LocalException(Exception): 1609 pass
1610 1611 class MyResolver(self.etree.Resolver): 1612 def resolve(self, url, id, context): 1613 raise _LocalException 1614 1615 parser.resolvers.add(MyResolver()) 1616 1617 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>' 1618 self.assertRaises(_LocalException, parse, BytesIO(xml), parser) 1619
1620 - def test_entity_parse(self):
1621 parse = self.etree.parse 1622 tostring = self.etree.tostring 1623 parser = self.etree.XMLParser(resolve_entities=False) 1624 Entity = self.etree.Entity 1625 1626 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>') 1627 tree = parse(BytesIO(xml), parser) 1628 root = tree.getroot() 1629 self.assertEqual(root[0].tag, Entity) 1630 self.assertEqual(root[0].text, "&myentity;") 1631 self.assertEqual(root[0].tail, None) 1632 self.assertEqual(root[0].name, "myentity") 1633 1634 self.assertEqual(_bytes('<doc>&myentity;</doc>'), 1635 tostring(root))
1636
1637 - def test_entity_restructure(self):
1638 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp "&#160;"> ]> 1639 <root> 1640 <child1/> 1641 <child2/> 1642 <child3>&nbsp;</child3> 1643 </root>''') 1644 1645 parser = self.etree.XMLParser(resolve_entities=False) 1646 root = etree.fromstring(xml, parser) 1647 self.assertEqual([ el.tag for el in root ], 1648 ['child1', 'child2', 'child3']) 1649 1650 root[0] = root[-1] 1651 self.assertEqual([ el.tag for el in root ], 1652 ['child3', 'child2']) 1653 self.assertEqual(root[0][0].text, '&nbsp;') 1654 self.assertEqual(root[0][0].name, 'nbsp')
1655
1656 - def test_entity_append(self):
1657 Entity = self.etree.Entity 1658 Element = self.etree.Element 1659 tostring = self.etree.tostring 1660 1661 root = Element("root") 1662 root.append( Entity("test") ) 1663 1664 self.assertEqual(root[0].tag, Entity) 1665 self.assertEqual(root[0].text, "&test;") 1666 self.assertEqual(root[0].tail, None) 1667 self.assertEqual(root[0].name, "test") 1668 1669 self.assertEqual(_bytes('<root>&test;</root>'), 1670 tostring(root))
1671
1672 - def test_entity_append_parsed(self):
1673 Entity = self.etree.Entity 1674 Element = self.etree.Element 1675 parser = self.etree.XMLParser(resolve_entities=False) 1676 entity = self.etree.XML('''<!DOCTYPE data [ 1677 <!ENTITY a "a"> 1678 <!ENTITY b "&a;"> 1679 ]> 1680 <data>&b;</data> 1681 ''', parser) 1682 1683 el = Element('test') 1684 el.append(entity) 1685 self.assertEqual(el.tag, 'test') 1686 self.assertEqual(el[0].tag, 'data') 1687 self.assertEqual(el[0][0].tag, Entity) 1688 self.assertEqual(el[0][0].name, 'b')
1689
1690 - def test_entity_values(self):
1691 Entity = self.etree.Entity 1692 self.assertEqual(Entity("test").text, '&test;') 1693 self.assertEqual(Entity("#17683").text, '&#17683;') 1694 self.assertEqual(Entity("#x1768").text, '&#x1768;') 1695 self.assertEqual(Entity("#x98AF").text, '&#x98AF;')
1696
1697 - def test_entity_error(self):
1698 Entity = self.etree.Entity 1699 self.assertRaises(ValueError, Entity, 'a b c') 1700 self.assertRaises(ValueError, Entity, 'a,b') 1701 self.assertRaises(ValueError, Entity, 'a\0b') 1702 self.assertRaises(ValueError, Entity, '#abc') 1703 self.assertRaises(ValueError, Entity, '#xxyz')
1704
1705 - def test_cdata(self):
1706 CDATA = self.etree.CDATA 1707 Element = self.etree.Element 1708 tostring = self.etree.tostring 1709 1710 root = Element("root") 1711 root.text = CDATA('test') 1712 1713 self.assertEqual('test', 1714 root.text) 1715 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1716 tostring(root))
1717
1718 - def test_cdata_tail(self):
1719 CDATA = self.etree.CDATA 1720 Element = self.etree.Element 1721 SubElement = self.etree.SubElement 1722 tostring = self.etree.tostring 1723 1724 root = Element("root") 1725 child = SubElement(root, 'child') 1726 child.tail = CDATA('test') 1727 1728 self.assertEqual('test', child.tail) 1729 self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'), 1730 tostring(root)) 1731 1732 root = Element("root") 1733 root.tail = CDATA('test') 1734 1735 self.assertEqual('test', root.tail) 1736 self.assertEqual(_bytes('<root/><![CDATA[test]]>'), 1737 tostring(root))
1738
1739 - def test_cdata_type(self):
1740 CDATA = self.etree.CDATA 1741 Element = self.etree.Element 1742 root = Element("root") 1743 1744 root.text = CDATA("test") 1745 self.assertEqual('test', root.text) 1746 1747 root.text = CDATA(_str("test")) 1748 self.assertEqual('test', root.text) 1749 1750 self.assertRaises(TypeError, CDATA, 1)
1751
1752 - def test_cdata_errors(self):
1753 CDATA = self.etree.CDATA 1754 Element = self.etree.Element 1755 1756 root = Element("root") 1757 cdata = CDATA('test') 1758 1759 self.assertRaises(TypeError, 1760 root.set, 'attr', cdata) 1761 self.assertRaises(TypeError, 1762 operator.setitem, root.attrib, 'attr', cdata)
1763
1764 - def test_cdata_parser(self):
1765 tostring = self.etree.tostring 1766 parser = self.etree.XMLParser(strip_cdata=False) 1767 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1768 1769 self.assertEqual('test', root.text) 1770 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1771 tostring(root))
1772
1773 - def test_cdata_xpath(self):
1774 tostring = self.etree.tostring 1775 parser = self.etree.XMLParser(strip_cdata=False) 1776 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1777 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1778 tostring(root)) 1779 1780 self.assertEqual(['test'], root.xpath('//text()'))
1781 1782 # TypeError in etree, AssertionError in ElementTree;
1783 - def test_setitem_assert(self):
1784 Element = self.etree.Element 1785 SubElement = self.etree.SubElement 1786 1787 a = Element('a') 1788 b = SubElement(a, 'b') 1789 1790 self.assertRaises(TypeError, 1791 a.__setitem__, 0, 'foo')
1792
1793 - def test_append_error(self):
1794 Element = self.etree.Element 1795 root = Element('root') 1796 # raises AssertionError in ElementTree 1797 self.assertRaises(TypeError, root.append, None) 1798 self.assertRaises(TypeError, root.extend, [None]) 1799 self.assertRaises(TypeError, root.extend, [Element('one'), None]) 1800 self.assertEqual('one', root[0].tag)
1801
1802 - def test_append_recursive_error(self):
1803 Element = self.etree.Element 1804 SubElement = self.etree.SubElement 1805 root = Element('root') 1806 self.assertRaises(ValueError, root.append, root) 1807 child = SubElement(root, 'child') 1808 self.assertRaises(ValueError, child.append, root) 1809 child2 = SubElement(child, 'child2') 1810 self.assertRaises(ValueError, child2.append, root) 1811 self.assertRaises(ValueError, child2.append, child) 1812 self.assertEqual('child2', root[0][0].tag)
1813
1814 - def test_addnext(self):
1815 Element = self.etree.Element 1816 SubElement = self.etree.SubElement 1817 root = Element('root') 1818 SubElement(root, 'a') 1819 SubElement(root, 'b') 1820 1821 self.assertEqual(['a', 'b'], 1822 [c.tag for c in root]) 1823 root[1].addnext(root[0]) 1824 self.assertEqual(['b', 'a'], 1825 [c.tag for c in root])
1826
1827 - def test_addprevious(self):
1828 Element = self.etree.Element 1829 SubElement = self.etree.SubElement 1830 root = Element('root') 1831 SubElement(root, 'a') 1832 SubElement(root, 'b') 1833 1834 self.assertEqual(['a', 'b'], 1835 [c.tag for c in root]) 1836 root[0].addprevious(root[1]) 1837 self.assertEqual(['b', 'a'], 1838 [c.tag for c in root])
1839
1840 - def test_addnext_cycle(self):
1841 Element = self.etree.Element 1842 SubElement = self.etree.SubElement 1843 root = Element('root') 1844 a = SubElement(root, 'a') 1845 b = SubElement(a, 'b') 1846 # appending parent as sibling is forbidden 1847 self.assertRaises(ValueError, b.addnext, a) 1848 self.assertEqual(['a'], [c.tag for c in root]) 1849 self.assertEqual(['b'], [c.tag for c in a])
1850
1851 - def test_addprevious_cycle(self):
1852 Element = self.etree.Element 1853 SubElement = self.etree.SubElement 1854 root = Element('root') 1855 a = SubElement(root, 'a') 1856 b = SubElement(a, 'b') 1857 # appending parent as sibling is forbidden 1858 self.assertRaises(ValueError, b.addprevious, a) 1859 self.assertEqual(['a'], [c.tag for c in root]) 1860 self.assertEqual(['b'], [c.tag for c in a])
1861
1862 - def test_addnext_cycle_long(self):
1863 Element = self.etree.Element 1864 SubElement = self.etree.SubElement 1865 root = Element('root') 1866 a = SubElement(root, 'a') 1867 b = SubElement(a, 'b') 1868 c = SubElement(b, 'c') 1869 # appending parent as sibling is forbidden 1870 self.assertRaises(ValueError, c.addnext, a)
1871
1872 - def test_addprevious_cycle_long(self):
1873 Element = self.etree.Element 1874 SubElement = self.etree.SubElement 1875 root = Element('root') 1876 a = SubElement(root, 'a') 1877 b = SubElement(a, 'b') 1878 c = SubElement(b, 'c') 1879 # appending parent as sibling is forbidden 1880 self.assertRaises(ValueError, c.addprevious, a)
1881
1882 - def test_addprevious_noops(self):
1883 Element = self.etree.Element 1884 SubElement = self.etree.SubElement 1885 root = Element('root') 1886 a = SubElement(root, 'a') 1887 b = SubElement(root, 'b') 1888 a.addprevious(a) 1889 self.assertEqual('a', root[0].tag) 1890 self.assertEqual('b', root[1].tag) 1891 b.addprevious(b) 1892 self.assertEqual('a', root[0].tag) 1893 self.assertEqual('b', root[1].tag) 1894 b.addprevious(a) 1895 self.assertEqual('a', root[0].tag) 1896 self.assertEqual('b', root[1].tag)
1897
1898 - def test_addnext_noops(self):
1899 Element = self.etree.Element 1900 SubElement = self.etree.SubElement 1901 root = Element('root') 1902 a = SubElement(root, 'a') 1903 b = SubElement(root, 'b') 1904 a.addnext(a) 1905 self.assertEqual('a', root[0].tag) 1906 self.assertEqual('b', root[1].tag) 1907 b.addnext(b) 1908 self.assertEqual('a', root[0].tag) 1909 self.assertEqual('b', root[1].tag) 1910 a.addnext(b) 1911 self.assertEqual('a', root[0].tag) 1912 self.assertEqual('b', root[1].tag)
1913
1914 - def test_addnext_root(self):
1915 Element = self.etree.Element 1916 a = Element('a') 1917 b = Element('b') 1918 self.assertRaises(TypeError, a.addnext, b)
1919
1920 - def test_addprevious_pi(self):
1921 Element = self.etree.Element 1922 SubElement = self.etree.SubElement 1923 PI = self.etree.PI 1924 root = Element('root') 1925 SubElement(root, 'a') 1926 pi = PI('TARGET', 'TEXT') 1927 pi.tail = "TAIL" 1928 1929 self.assertEqual(_bytes('<root><a></a></root>'), 1930 self._writeElement(root)) 1931 root[0].addprevious(pi) 1932 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'), 1933 self._writeElement(root))
1934
1935 - def test_addprevious_root_pi(self):
1936 Element = self.etree.Element 1937 PI = self.etree.PI 1938 root = Element('root') 1939 pi = PI('TARGET', 'TEXT') 1940 pi.tail = "TAIL" 1941 1942 self.assertEqual(_bytes('<root></root>'), 1943 self._writeElement(root)) 1944 root.addprevious(pi) 1945 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'), 1946 self._writeElement(root))
1947
1948 - def test_addnext_pi(self):
1949 Element = self.etree.Element 1950 SubElement = self.etree.SubElement 1951 PI = self.etree.PI 1952 root = Element('root') 1953 SubElement(root, 'a') 1954 pi = PI('TARGET', 'TEXT') 1955 pi.tail = "TAIL" 1956 1957 self.assertEqual(_bytes('<root><a></a></root>'), 1958 self._writeElement(root)) 1959 root[0].addnext(pi) 1960 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'), 1961 self._writeElement(root))
1962
1963 - def test_addnext_root_pi(self):
1964 Element = self.etree.Element 1965 PI = self.etree.PI 1966 root = Element('root') 1967 pi = PI('TARGET', 'TEXT') 1968 pi.tail = "TAIL" 1969 1970 self.assertEqual(_bytes('<root></root>'), 1971 self._writeElement(root)) 1972 root.addnext(pi) 1973 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'), 1974 self._writeElement(root))
1975
1976 - def test_addnext_comment(self):
1977 Element = self.etree.Element 1978 SubElement = self.etree.SubElement 1979 Comment = self.etree.Comment 1980 root = Element('root') 1981 SubElement(root, 'a') 1982 comment = Comment('TEXT ') 1983 comment.tail = "TAIL" 1984 1985 self.assertEqual(_bytes('<root><a></a></root>'), 1986 self._writeElement(root)) 1987 root[0].addnext(comment) 1988 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'), 1989 self._writeElement(root))
1990
1991 - def test_addnext_root_comment(self):
1992 Element = self.etree.Element 1993 Comment = self.etree.Comment 1994 root = Element('root') 1995 comment = Comment('TEXT ') 1996 comment.tail = "TAIL" 1997 1998 self.assertEqual(_bytes('<root></root>'), 1999 self._writeElement(root)) 2000 root.addnext(comment) 2001 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'), 2002 self._writeElement(root))
2003
2004 - def test_addprevious_comment(self):
2005 Element = self.etree.Element 2006 SubElement = self.etree.SubElement 2007 Comment = self.etree.Comment 2008 root = Element('root') 2009 SubElement(root, 'a') 2010 comment = Comment('TEXT ') 2011 comment.tail = "TAIL" 2012 2013 self.assertEqual(_bytes('<root><a></a></root>'), 2014 self._writeElement(root)) 2015 root[0].addprevious(comment) 2016 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'), 2017 self._writeElement(root))
2018
2019 - def test_addprevious_root_comment(self):
2020 Element = self.etree.Element 2021 Comment = self.etree.Comment 2022 root = Element('root') 2023 comment = Comment('TEXT ') 2024 comment.tail = "TAIL" 2025 2026 self.assertEqual(_bytes('<root></root>'), 2027 self._writeElement(root)) 2028 root.addprevious(comment) 2029 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'), 2030 self._writeElement(root))
2031 2032 # ET's Elements have items() and key(), but not values()
2033 - def test_attribute_values(self):
2034 XML = self.etree.XML 2035 2036 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>')) 2037 values = root.values() 2038 values.sort() 2039 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
2040 2041 # gives error in ElementTree
2042 - def test_comment_empty(self):
2043 Element = self.etree.Element 2044 Comment = self.etree.Comment 2045 2046 a = Element('a') 2047 a.append(Comment()) 2048 self.assertEqual( 2049 _bytes('<a><!----></a>'), 2050 self._writeElement(a))
2051 2052 # ElementTree ignores comments
2053 - def test_comment_parse_empty(self):
2054 ElementTree = self.etree.ElementTree 2055 tostring = self.etree.tostring 2056 2057 xml = _bytes('<a><b/><!----><c/></a>') 2058 f = BytesIO(xml) 2059 doc = ElementTree(file=f) 2060 a = doc.getroot() 2061 self.assertEqual( 2062 '', 2063 a[1].text) 2064 self.assertEqual( 2065 xml, 2066 tostring(a))
2067 2068 # ElementTree ignores comments
2069 - def test_comment_no_proxy_yet(self):
2070 ElementTree = self.etree.ElementTree 2071 2072 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>') 2073 doc = ElementTree(file=f) 2074 a = doc.getroot() 2075 self.assertEqual( 2076 ' hoi ', 2077 a[1].text)
2078 2079 # does not raise an exception in ElementTree
2080 - def test_comment_immutable(self):
2081 Element = self.etree.Element 2082 Comment = self.etree.Comment 2083 2084 c = Comment() 2085 el = Element('myel') 2086 2087 self.assertRaises(TypeError, c.append, el) 2088 self.assertRaises(TypeError, c.insert, 0, el) 2089 self.assertRaises(TypeError, c.set, "myattr", "test")
2090
2091 - def test_comment_immutable_attrib(self):
2092 c = self.etree.Comment() 2093 self.assertEqual(0, len(c.attrib)) 2094 2095 self.assertFalse(c.attrib.__contains__('nope')) 2096 self.assertFalse('nope' in c.attrib) 2097 self.assertFalse('nope' in c.attrib.keys()) 2098 self.assertFalse('nope' in c.attrib.values()) 2099 self.assertFalse(('nope', 'huhu') in c.attrib.items()) 2100 2101 self.assertEqual([], list(c.attrib)) 2102 self.assertEqual([], list(c.attrib.keys())) 2103 self.assertEqual([], list(c.attrib.items())) 2104 self.assertEqual([], list(c.attrib.values())) 2105 self.assertEqual([], list(c.attrib.iterkeys())) 2106 self.assertEqual([], list(c.attrib.iteritems())) 2107 self.assertEqual([], list(c.attrib.itervalues())) 2108 2109 self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU')) 2110 self.assertRaises(KeyError, c.attrib.pop, 'nope') 2111 2112 self.assertRaises(KeyError, c.attrib.__getitem__, 'only') 2113 self.assertRaises(KeyError, c.attrib.__getitem__, 'names') 2114 self.assertRaises(KeyError, c.attrib.__getitem__, 'nope') 2115 self.assertRaises(KeyError, c.attrib.__setitem__, 'nope', 'yep') 2116 self.assertRaises(KeyError, c.attrib.__delitem__, 'nope')
2117 2118 # test passing 'None' to dump()
2119 - def test_dump_none(self):
2120 self.assertRaises(TypeError, self.etree.dump, None)
2121
2122 - def test_prefix(self):
2123 ElementTree = self.etree.ElementTree 2124 2125 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>') 2126 doc = ElementTree(file=f) 2127 a = doc.getroot() 2128 self.assertEqual( 2129 None, 2130 a.prefix) 2131 self.assertEqual( 2132 'foo', 2133 a[0].prefix)
2134
2135 - def test_prefix_default_ns(self):
2136 ElementTree = self.etree.ElementTree 2137 2138 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>') 2139 doc = ElementTree(file=f) 2140 a = doc.getroot() 2141 self.assertEqual( 2142 None, 2143 a.prefix) 2144 self.assertEqual( 2145 None, 2146 a[0].prefix)
2147
2148 - def test_getparent(self):
2149 Element = self.etree.Element 2150 SubElement = self.etree.SubElement 2151 2152 a = Element('a') 2153 b = SubElement(a, 'b') 2154 c = SubElement(a, 'c') 2155 d = SubElement(b, 'd') 2156 self.assertEqual( 2157 None, 2158 a.getparent()) 2159 self.assertEqual( 2160 a, 2161 b.getparent()) 2162 self.assertEqual( 2163 b.getparent(), 2164 c.getparent()) 2165 self.assertEqual( 2166 b, 2167 d.getparent())
2168
2169 - def test_iterchildren(self):
2170 XML = self.etree.XML 2171 2172 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 2173 result = [] 2174 for el in root.iterchildren(): 2175 result.append(el.tag) 2176 self.assertEqual(['one', 'two', 'three'], result)
2177
2178 - def test_iterchildren_reversed(self):
2179 XML = self.etree.XML 2180 2181 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 2182 result = [] 2183 for el in root.iterchildren(reversed=True): 2184 result.append(el.tag) 2185 self.assertEqual(['three', 'two', 'one'], result)
2186
2187 - def test_iterchildren_tag(self):
2188 XML = self.etree.XML 2189 2190 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 2191 result = [] 2192 for el in root.iterchildren(tag='two'): 2193 result.append(el.text) 2194 self.assertEqual(['Two', 'Bla'], result)
2195
2196 - def test_iterchildren_tag_posarg(self):
2197 XML = self.etree.XML 2198 2199 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 2200 result = [] 2201 for el in root.iterchildren('two'): 2202 result.append(el.text) 2203 self.assertEqual(['Two', 'Bla'], result)
2204
2205 - def test_iterchildren_tag_reversed(self):
2206 XML = self.etree.XML 2207 2208 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 2209 result = [] 2210 for el in root.iterchildren(reversed=True, tag='two'): 2211 result.append(el.text) 2212 self.assertEqual(['Bla', 'Two'], result)
2213
2214 - def test_iterchildren_tag_multiple(self):
2215 XML = self.etree.XML 2216 2217 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 2218 result = [] 2219 for el in root.iterchildren(tag=['two', 'three']): 2220 result.append(el.text) 2221 self.assertEqual(['Two', 'Bla', None], result)
2222
2223 - def test_iterchildren_tag_multiple_posarg(self):
2224 XML = self.etree.XML 2225 2226 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 2227 result = [] 2228 for el in root.iterchildren('two', 'three'): 2229 result.append(el.text) 2230 self.assertEqual(['Two', 'Bla', None], result)
2231
2232 - def test_iterchildren_tag_multiple_reversed(self):
2233 XML = self.etree.XML 2234 2235 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 2236 result = [] 2237 for el in root.iterchildren(reversed=True, tag=['two', 'three']): 2238 result.append(el.text) 2239 self.assertEqual([None, 'Bla', 'Two'], result)
2240
2241 - def test_iterancestors(self):
2242 Element = self.etree.Element 2243 SubElement = self.etree.SubElement 2244 2245 a = Element('a') 2246 b = SubElement(a, 'b') 2247 c = SubElement(a, 'c') 2248 d = SubElement(b, 'd') 2249 self.assertEqual( 2250 [], 2251 list(a.iterancestors())) 2252 self.assertEqual( 2253 [a], 2254 list(b.iterancestors())) 2255 self.assertEqual( 2256 [a], 2257 list(c.iterancestors())) 2258 self.assertEqual( 2259 [b, a], 2260 list(d.iterancestors()))
2261
2262 - def test_iterancestors_tag(self):
2263 Element = self.etree.Element 2264 SubElement = self.etree.SubElement 2265 2266 a = Element('a') 2267 b = SubElement(a, 'b') 2268 c = SubElement(a, 'c') 2269 d = SubElement(b, 'd') 2270 self.assertEqual( 2271 [a], 2272 list(d.iterancestors('a'))) 2273 self.assertEqual( 2274 [a], 2275 list(d.iterancestors(tag='a'))) 2276 2277 self.assertEqual( 2278 [b, a], 2279 list(d.iterancestors('*'))) 2280 self.assertEqual( 2281 [b, a], 2282 list(d.iterancestors(tag='*')))
2283
2284 - def test_iterancestors_tag_multiple(self):
2285 Element = self.etree.Element 2286 SubElement = self.etree.SubElement 2287 2288 a = Element('a') 2289 b = SubElement(a, 'b') 2290 c = SubElement(a, 'c') 2291 d = SubElement(b, 'd') 2292 self.assertEqual( 2293 [b, a], 2294 list(d.iterancestors(tag=('a', 'b')))) 2295 self.assertEqual( 2296 [b, a], 2297 list(d.iterancestors('a', 'b'))) 2298 2299 self.assertEqual( 2300 [], 2301 list(d.iterancestors(tag=('w', 'x', 'y', 'z')))) 2302 self.assertEqual( 2303 [], 2304 list(d.iterancestors('w', 'x', 'y', 'z'))) 2305 2306 self.assertEqual( 2307 [], 2308 list(d.iterancestors(tag=('d', 'x')))) 2309 self.assertEqual( 2310 [], 2311 list(d.iterancestors('d', 'x'))) 2312 2313 self.assertEqual( 2314 [b, a], 2315 list(d.iterancestors(tag=('b', '*')))) 2316 self.assertEqual( 2317 [b, a], 2318 list(d.iterancestors('b', '*'))) 2319 2320 self.assertEqual( 2321 [b], 2322 list(d.iterancestors(tag=('b', 'c')))) 2323 self.assertEqual( 2324 [b], 2325 list(d.iterancestors('b', 'c')))
2326
2327 - def test_iterdescendants(self):
2328 Element = self.etree.Element 2329 SubElement = self.etree.SubElement 2330 2331 a = Element('a') 2332 b = SubElement(a, 'b') 2333 c = SubElement(a, 'c') 2334 d = SubElement(b, 'd') 2335 e = SubElement(c, 'e') 2336 2337 self.assertEqual( 2338 [b, d, c, e], 2339 list(a.iterdescendants())) 2340 self.assertEqual( 2341 [], 2342 list(d.iterdescendants()))
2343
2344 - def test_iterdescendants_tag(self):
2345 Element = self.etree.Element 2346 SubElement = self.etree.SubElement 2347 2348 a = Element('a') 2349 b = SubElement(a, 'b') 2350 c = SubElement(a, 'c') 2351 d = SubElement(b, 'd') 2352 e = SubElement(c, 'e') 2353 2354 self.assertEqual( 2355 [], 2356 list(a.iterdescendants('a'))) 2357 self.assertEqual( 2358 [], 2359 list(a.iterdescendants(tag='a'))) 2360 2361 a2 = SubElement(e, 'a') 2362 self.assertEqual( 2363 [a2], 2364 list(a.iterdescendants('a'))) 2365 2366 self.assertEqual( 2367 [a2], 2368 list(c.iterdescendants('a'))) 2369 self.assertEqual( 2370 [a2], 2371 list(c.iterdescendants(tag='a')))
2372
2373 - def test_iterdescendants_tag_multiple(self):
2374 Element = self.etree.Element 2375 SubElement = self.etree.SubElement 2376 2377 a = Element('a') 2378 b = SubElement(a, 'b') 2379 c = SubElement(a, 'c') 2380 d = SubElement(b, 'd') 2381 e = SubElement(c, 'e') 2382 2383 self.assertEqual( 2384 [b, e], 2385 list(a.iterdescendants(tag=('a', 'b', 'e')))) 2386 self.assertEqual( 2387 [b, e], 2388 list(a.iterdescendants('a', 'b', 'e'))) 2389 2390 a2 = SubElement(e, 'a') 2391 self.assertEqual( 2392 [b, a2], 2393 list(a.iterdescendants(tag=('a', 'b')))) 2394 self.assertEqual( 2395 [b, a2], 2396 list(a.iterdescendants('a', 'b'))) 2397 2398 self.assertEqual( 2399 [], 2400 list(c.iterdescendants(tag=('x', 'y', 'z')))) 2401 self.assertEqual( 2402 [], 2403 list(c.iterdescendants('x', 'y', 'z'))) 2404 2405 self.assertEqual( 2406 [b, d, c, e, a2], 2407 list(a.iterdescendants(tag=('x', 'y', 'z', '*')))) 2408 self.assertEqual( 2409 [b, d, c, e, a2], 2410 list(a.iterdescendants('x', 'y', 'z', '*')))
2411
2412 - def test_getroottree(self):
2413 Element = self.etree.Element 2414 SubElement = self.etree.SubElement 2415 2416 a = Element('a') 2417 b = SubElement(a, 'b') 2418 c = SubElement(a, 'c') 2419 d = SubElement(b, 'd') 2420 self.assertEqual( 2421 a, 2422 a.getroottree().getroot()) 2423 self.assertEqual( 2424 a, 2425 b.getroottree().getroot()) 2426 self.assertEqual( 2427 a, 2428 d.getroottree().getroot())
2429
2430 - def test_getnext(self):
2431 Element = self.etree.Element 2432 SubElement = self.etree.SubElement 2433 2434 a = Element('a') 2435 b = SubElement(a, 'b') 2436 c = SubElement(a, 'c') 2437 self.assertEqual( 2438 None, 2439 a.getnext()) 2440 self.assertEqual( 2441 c, 2442 b.getnext()) 2443 self.assertEqual( 2444 None, 2445 c.getnext())
2446
2447 - def test_getprevious(self):
2448 Element = self.etree.Element 2449 SubElement = self.etree.SubElement 2450 2451 a = Element('a') 2452 b = SubElement(a, 'b') 2453 c = SubElement(a, 'c') 2454 d = SubElement(b, 'd') 2455 self.assertEqual( 2456 None, 2457 a.getprevious()) 2458 self.assertEqual( 2459 b, 2460 c.getprevious()) 2461 self.assertEqual( 2462 None, 2463 b.getprevious())
2464
2465 - def test_itersiblings(self):
2466 Element = self.etree.Element 2467 SubElement = self.etree.SubElement 2468 2469 a = Element('a') 2470 b = SubElement(a, 'b') 2471 c = SubElement(a, 'c') 2472 d = SubElement(b, 'd') 2473 self.assertEqual( 2474 [], 2475 list(a.itersiblings())) 2476 self.assertEqual( 2477 [c], 2478 list(b.itersiblings())) 2479 self.assertEqual( 2480 [], 2481 list(c.itersiblings())) 2482 self.assertEqual( 2483 [b], 2484 list(c.itersiblings(preceding=True))) 2485 self.assertEqual( 2486 [], 2487 list(b.itersiblings(preceding=True)))
2488
2489 - def test_itersiblings_tag(self):
2490 Element = self.etree.Element 2491 SubElement = self.etree.SubElement 2492 2493 a = Element('a') 2494 b = SubElement(a, 'b') 2495 c = SubElement(a, 'c') 2496 d = SubElement(b, 'd') 2497 self.assertEqual( 2498 [], 2499 list(a.itersiblings(tag='XXX'))) 2500 self.assertEqual( 2501 [c], 2502 list(b.itersiblings(tag='c'))) 2503 self.assertEqual( 2504 [c], 2505 list(b.itersiblings(tag='*'))) 2506 self.assertEqual( 2507 [b], 2508 list(c.itersiblings(preceding=True, tag='b'))) 2509 self.assertEqual( 2510 [], 2511 list(c.itersiblings(preceding=True, tag='c')))
2512
2513 - def test_itersiblings_tag_multiple(self):
2514 Element = self.etree.Element 2515 SubElement = self.etree.SubElement 2516 2517 a = Element('a') 2518 b = SubElement(a, 'b') 2519 c = SubElement(a, 'c') 2520 d = SubElement(b, 'd') 2521 e = SubElement(a, 'e') 2522 self.assertEqual( 2523 [], 2524 list(a.itersiblings(tag=('XXX', 'YYY')))) 2525 self.assertEqual( 2526 [c, e], 2527 list(b.itersiblings(tag=('c', 'd', 'e')))) 2528 self.assertEqual( 2529 [b], 2530 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd')))) 2531 self.assertEqual( 2532 [c, b], 2533 list(e.itersiblings(preceding=True, tag=('c', '*'))))
2534
2535 - def test_parseid(self):
2536 parseid = self.etree.parseid 2537 XML = self.etree.XML 2538 xml_text = _bytes(''' 2539 <!DOCTYPE document [ 2540 <!ELEMENT document (h1,p)*> 2541 <!ELEMENT h1 (#PCDATA)> 2542 <!ATTLIST h1 myid ID #REQUIRED> 2543 <!ELEMENT p (#PCDATA)> 2544 <!ATTLIST p someid ID #REQUIRED> 2545 ]> 2546 <document> 2547 <h1 myid="chapter1">...</h1> 2548 <p id="note1" class="note">...</p> 2549 <p>Regular paragraph.</p> 2550 <p xml:id="xmlid">XML:ID paragraph.</p> 2551 <p someid="warn1" class="warning">...</p> 2552 </document> 2553 ''') 2554 2555 tree, dic = parseid(BytesIO(xml_text)) 2556 root = tree.getroot() 2557 root2 = XML(xml_text) 2558 self.assertEqual(self._writeElement(root), 2559 self._writeElement(root2)) 2560 expected = { 2561 "chapter1" : root[0], 2562 "xmlid" : root[3], 2563 "warn1" : root[4] 2564 } 2565 self.assertTrue("chapter1" in dic) 2566 self.assertTrue("warn1" in dic) 2567 self.assertTrue("xmlid" in dic) 2568 self._checkIDDict(dic, expected)
2569
2570 - def test_XMLDTDID(self):
2571 XMLDTDID = self.etree.XMLDTDID 2572 XML = self.etree.XML 2573 xml_text = _bytes(''' 2574 <!DOCTYPE document [ 2575 <!ELEMENT document (h1,p)*> 2576 <!ELEMENT h1 (#PCDATA)> 2577 <!ATTLIST h1 myid ID #REQUIRED> 2578 <!ELEMENT p (#PCDATA)> 2579 <!ATTLIST p someid ID #REQUIRED> 2580 ]> 2581 <document> 2582 <h1 myid="chapter1">...</h1> 2583 <p id="note1" class="note">...</p> 2584 <p>Regular paragraph.</p> 2585 <p xml:id="xmlid">XML:ID paragraph.</p> 2586 <p someid="warn1" class="warning">...</p> 2587 </document> 2588 ''') 2589 2590 root, dic = XMLDTDID(xml_text) 2591 root2 = XML(xml_text) 2592 self.assertEqual(self._writeElement(root), 2593 self._writeElement(root2)) 2594 expected = { 2595 "chapter1" : root[0], 2596 "xmlid" : root[3], 2597 "warn1" : root[4] 2598 } 2599 self.assertTrue("chapter1" in dic) 2600 self.assertTrue("warn1" in dic) 2601 self.assertTrue("xmlid" in dic) 2602 self._checkIDDict(dic, expected)
2603
2604 - def test_XMLDTDID_empty(self):
2605 XMLDTDID = self.etree.XMLDTDID 2606 XML = self.etree.XML 2607 xml_text = _bytes(''' 2608 <document> 2609 <h1 myid="chapter1">...</h1> 2610 <p id="note1" class="note">...</p> 2611 <p>Regular paragraph.</p> 2612 <p someid="warn1" class="warning">...</p> 2613 </document> 2614 ''') 2615 2616 root, dic = XMLDTDID(xml_text) 2617 root2 = XML(xml_text) 2618 self.assertEqual(self._writeElement(root), 2619 self._writeElement(root2)) 2620 expected = {} 2621 self._checkIDDict(dic, expected)
2622
2623 - def test_XMLDTDID_no_id_dict(self):
2624 XMLDTDID = self.etree.XMLDTDID 2625 XML = self.etree.XML 2626 xml_text = _bytes(''' 2627 <!DOCTYPE document [ 2628 <!ELEMENT document (h1,p)*> 2629 <!ELEMENT h1 (#PCDATA)> 2630 <!ATTLIST h1 myid ID #REQUIRED> 2631 <!ELEMENT p (#PCDATA)> 2632 <!ATTLIST p someid ID #REQUIRED> 2633 ]> 2634 <document> 2635 <h1 myid="chapter1">...</h1> 2636 <p id="note1" class="note">...</p> 2637 <p>Regular paragraph.</p> 2638 <p xml:id="xmlid">XML:ID paragraph.</p> 2639 <p someid="warn1" class="warning">...</p> 2640 </document> 2641 ''') 2642 2643 parser = etree.XMLParser(collect_ids=False) 2644 root, dic = XMLDTDID(xml_text, parser=parser) 2645 root2 = XML(xml_text) 2646 self.assertEqual(self._writeElement(root), 2647 self._writeElement(root2)) 2648 self.assertFalse(dic) 2649 self._checkIDDict(dic, {})
2650
2651 - def _checkIDDict(self, dic, expected):
2652 self.assertEqual(len(dic), 2653 len(expected)) 2654 self.assertEqual(sorted(dic.items()), 2655 sorted(expected.items())) 2656 if sys.version_info < (3,): 2657 self.assertEqual(sorted(dic.iteritems()), 2658 sorted(expected.iteritems())) 2659 self.assertEqual(sorted(dic.keys()), 2660 sorted(expected.keys())) 2661 if sys.version_info < (3,): 2662 self.assertEqual(sorted(dic.iterkeys()), 2663 sorted(expected.iterkeys())) 2664 if sys.version_info < (3,): 2665 self.assertEqual(sorted(dic.values()), 2666 sorted(expected.values())) 2667 self.assertEqual(sorted(dic.itervalues()), 2668 sorted(expected.itervalues()))
2669
2670 - def test_register_namespace_xml(self):
2671 self.assertRaises(ValueError, self.etree.register_namespace, 2672 "XML", "http://www.w3.org/XML/1998/namespace") 2673 self.assertRaises(ValueError, self.etree.register_namespace, 2674 "xml", "http://www.w3.org/XML/2345") 2675 self.etree.register_namespace("xml", "http://www.w3.org/XML/1998/namespace") # ok
2676
2677 - def test_namespaces(self):
2678 etree = self.etree 2679 2680 r = {'foo': 'http://ns.infrae.com/foo'} 2681 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2682 self.assertEqual( 2683 'foo', 2684 e.prefix) 2685 self.assertEqual( 2686 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'), 2687 self._writeElement(e))
2688
2689 - def test_namespaces_default(self):
2690 etree = self.etree 2691 2692 r = {None: 'http://ns.infrae.com/foo'} 2693 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2694 self.assertEqual( 2695 None, 2696 e.prefix) 2697 self.assertEqual( 2698 '{http://ns.infrae.com/foo}bar', 2699 e.tag) 2700 self.assertEqual( 2701 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'), 2702 self._writeElement(e))
2703
2704 - def test_namespaces_default_and_other(self):
2705 etree = self.etree 2706 2707 r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'} 2708 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2709 self.assertEqual(None, e.prefix) 2710 self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag) 2711 self.assertEqual( 2712 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'), 2713 self._writeElement(e))
2714
2715 - def test_namespaces_default_and_attr(self):
2716 etree = self.etree 2717 2718 r = {None: 'http://ns.infrae.com/foo', 2719 'hoi': 'http://ns.infrae.com/hoi'} 2720 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2721 e.set('{http://ns.infrae.com/hoi}test', 'value') 2722 self.assertEqual( 2723 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'), 2724 self._writeElement(e))
2725
2726 - def test_attribute_keeps_namespace_prefix_on_merge(self):
2727 etree = self.etree 2728 2729 root = etree.Element('{http://test/ns}root', 2730 nsmap={None: 'http://test/ns'}) 2731 sub = etree.Element('{http://test/ns}sub', 2732 nsmap={'test': 'http://test/ns'}) 2733 2734 sub.attrib['{http://test/ns}attr'] = 'value' 2735 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2736 self.assertEqual( 2737 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'), 2738 etree.tostring(sub)) 2739 2740 root.append(sub) 2741 self.assertEqual( 2742 _bytes('<root xmlns="http://test/ns">' 2743 '<sub xmlns:test="http://test/ns" test:attr="value"/>' 2744 '</root>'), 2745 etree.tostring(root))
2746
2747 - def test_attribute_keeps_namespace_prefix_on_merge_with_nons(self):
2748 etree = self.etree 2749 2750 root = etree.Element('root') 2751 sub = etree.Element('{http://test/ns}sub', 2752 nsmap={'test': 'http://test/ns'}) 2753 2754 sub.attrib['{http://test/ns}attr'] = 'value' 2755 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2756 self.assertEqual( 2757 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'), 2758 etree.tostring(sub)) 2759 2760 root.append(sub) 2761 self.assertEqual( 2762 _bytes('<root>' 2763 '<test:sub xmlns:test="http://test/ns" test:attr="value"/>' 2764 '</root>'), 2765 etree.tostring(root))
2766
2767 - def test_attribute_gets_namespace_prefix_on_merge_with_nons(self):
2768 etree = self.etree 2769 2770 root = etree.Element('root') 2771 sub = etree.Element('{http://test/ns}sub', 2772 nsmap={None: 'http://test/ns'}) 2773 2774 sub.attrib['{http://test/ns}attr'] = 'value' 2775 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2776 self.assertEqual( 2777 _bytes('<sub xmlns="http://test/ns" ' 2778 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'), 2779 etree.tostring(sub)) 2780 2781 root.append(sub) 2782 self.assertEqual( 2783 _bytes('<root>' 2784 '<sub xmlns="http://test/ns"' 2785 ' xmlns:ns0="http://test/ns" ns0:attr="value"/>' 2786 '</root>'), 2787 etree.tostring(root))
2788
2789 - def test_attribute_gets_namespace_prefix_on_merge(self):
2790 etree = self.etree 2791 2792 root = etree.Element('{http://test/ns}root', 2793 nsmap={'test': 'http://test/ns', 2794 None: 'http://test/ns'}) 2795 sub = etree.Element('{http://test/ns}sub', 2796 nsmap={None: 'http://test/ns'}) 2797 2798 sub.attrib['{http://test/ns}attr'] = 'value' 2799 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2800 self.assertEqual( 2801 _bytes('<sub xmlns="http://test/ns" ' 2802 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'), 2803 etree.tostring(sub)) 2804 2805 root.append(sub) 2806 self.assertEqual( 2807 _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">' 2808 '<test:sub test:attr="value"/>' 2809 '</test:root>'), 2810 etree.tostring(root))
2811
2812 - def test_namespaces_elementtree(self):
2813 etree = self.etree 2814 r = {None: 'http://ns.infrae.com/foo', 2815 'hoi': 'http://ns.infrae.com/hoi'} 2816 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r) 2817 tree = etree.ElementTree(element=e) 2818 etree.SubElement(e, '{http://ns.infrae.com/hoi}x') 2819 self.assertEqual( 2820 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'), 2821 self._writeElement(e))
2822
2823 - def test_namespaces_default_copy_element(self):
2824 etree = self.etree 2825 2826 r = {None: 'http://ns.infrae.com/foo'} 2827 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2828 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2829 2830 e1.append(e2) 2831 2832 self.assertEqual( 2833 None, 2834 e1.prefix) 2835 self.assertEqual( 2836 None, 2837 e1[0].prefix) 2838 self.assertEqual( 2839 '{http://ns.infrae.com/foo}bar', 2840 e1.tag) 2841 self.assertEqual( 2842 '{http://ns.infrae.com/foo}bar', 2843 e1[0].tag)
2844
2845 - def test_namespaces_copy_element(self):
2846 etree = self.etree 2847 2848 r = {None: 'http://ns.infrae.com/BAR'} 2849 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r) 2850 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2851 2852 e1.append(e2) 2853 2854 self.assertEqual( 2855 None, 2856 e1.prefix) 2857 self.assertNotEqual( 2858 None, 2859 e2.prefix) 2860 self.assertEqual( 2861 '{http://ns.infrae.com/BAR}bar', 2862 e1.tag) 2863 self.assertEqual( 2864 '{http://ns.infrae.com/foo}bar', 2865 e2.tag)
2866
2867 - def test_namespaces_reuse_after_move(self):
2868 ns_href = "http://a.b.c" 2869 one = self.etree.fromstring( 2870 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href)) 2871 baz = one[0][0] 2872 2873 two = self.etree.fromstring( 2874 _bytes('<root xmlns:ns="%s"/>' % ns_href)) 2875 two.append(baz) 2876 del one # make sure the source document is deallocated 2877 2878 self.assertEqual('{%s}baz' % ns_href, baz.tag) 2879 self.assertEqual( 2880 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href), 2881 self.etree.tostring(two))
2882
2883 - def test_namespace_cleanup(self):
2884 xml = _bytes( 2885 '<foo xmlns="F" xmlns:x="x">' 2886 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">' 2887 '<ns:baz/>' 2888 '</bar></foo>' 2889 ) 2890 root = self.etree.fromstring(xml) 2891 self.assertEqual(xml, self.etree.tostring(root)) 2892 self.etree.cleanup_namespaces(root) 2893 self.assertEqual( 2894 _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'), 2895 self.etree.tostring(root))
2896
2897 - def test_namespace_cleanup_attributes(self):
2898 xml = _bytes( 2899 '<foo xmlns="F" xmlns:x="X" xmlns:a="A">' 2900 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">' 2901 '<ns:baz a:test="attr"/>' 2902 '</bar></foo>' 2903 ) 2904 root = self.etree.fromstring(xml) 2905 self.assertEqual(xml, self.etree.tostring(root)) 2906 self.etree.cleanup_namespaces(root) 2907 self.assertEqual( 2908 _bytes('<foo xmlns="F" xmlns:a="A">' 2909 '<bar xmlns:ns="NS" xmlns="B">' 2910 '<ns:baz a:test="attr"/>' 2911 '</bar></foo>'), 2912 self.etree.tostring(root))
2913
2914 - def test_namespace_cleanup_many(self):
2915 xml = ('<n12:foo ' + 2916 ' '.join('xmlns:n{n}="NS{n}"'.format(n=i) for i in range(100)) + 2917 '><n68:a/></n12:foo>').encode('utf8') 2918 root = self.etree.fromstring(xml) 2919 self.assertEqual(xml, self.etree.tostring(root)) 2920 self.etree.cleanup_namespaces(root) 2921 self.assertEqual( 2922 b'<n12:foo xmlns:n12="NS12" xmlns:n68="NS68"><n68:a/></n12:foo>', 2923 self.etree.tostring(root))
2924
2925 - def test_namespace_cleanup_deep(self):
2926 xml = ('<root>' + 2927 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) + 2928 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8') 2929 root = self.etree.fromstring(xml) 2930 self.assertEqual(xml, self.etree.tostring(root)) 2931 self.etree.cleanup_namespaces(root) 2932 self.assertEqual( 2933 b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 + 2934 b'<n64:x/>' + b'</a>'*100 + b'</root>', 2935 self.etree.tostring(root))
2936
2937 - def test_namespace_cleanup_deep_to_top(self):
2938 xml = ('<root>' + 2939 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) + 2940 '<n64:x xmlns:a="A" a:attr="X"/>' + 2941 '</a>'*100 + 2942 '</root>').encode('utf8') 2943 root = self.etree.fromstring(xml) 2944 self.assertEqual(xml, self.etree.tostring(root)) 2945 self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'}) 2946 self.assertEqual( 2947 b'<root xmlns:n64="NS64">' + b'<a>'*100 + 2948 b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>', 2949 self.etree.tostring(root))
2950
2951 - def test_namespace_cleanup_keep_prefixes(self):
2952 xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">' 2953 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>' 2954 '<foo>foo:bar</foo>' 2955 '</root>').encode('utf8') 2956 root = self.etree.fromstring(xml) 2957 self.assertEqual(xml, self.etree.tostring(root)) 2958 self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo']) 2959 self.assertEqual( 2960 b'<root xmlns:n64="NS64" xmlns:foo="FOO">' 2961 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>' 2962 b'<foo>foo:bar</foo>' 2963 b'</root>', 2964 self.etree.tostring(root))
2965
2966 - def test_namespace_cleanup_keep_prefixes_top(self):
2967 xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">' 2968 '<sub xmlns:foo="FOO">' 2969 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>' 2970 '<foo>foo:bar</foo>' 2971 '</sub>' 2972 '</root>').encode('utf8') 2973 root = self.etree.fromstring(xml) 2974 self.assertEqual(xml, self.etree.tostring(root)) 2975 self.etree.cleanup_namespaces( 2976 root, 2977 top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'}, 2978 keep_ns_prefixes=['foo']) 2979 self.assertEqual( 2980 b'<root xmlns:n64="NS64" xmlns:foo="FOO">' 2981 b'<sub>' 2982 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>' 2983 b'<foo>foo:bar</foo>' 2984 b'</sub>' 2985 b'</root>', 2986 self.etree.tostring(root))
2987
2988 - def test_element_nsmap(self):
2989 etree = self.etree 2990 2991 r = {None: 'http://ns.infrae.com/foo', 2992 'hoi': 'http://ns.infrae.com/hoi'} 2993 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2994 self.assertEqual( 2995 r, 2996 e.nsmap)
2997
2998 - def test_subelement_nsmap(self):
2999 etree = self.etree 3000 3001 re = {None: 'http://ns.infrae.com/foo', 3002 'hoi': 'http://ns.infrae.com/hoi'} 3003 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re) 3004 3005 rs = {None: 'http://ns.infrae.com/honk', 3006 'top': 'http://ns.infrae.com/top'} 3007 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs) 3008 3009 r = re.copy() 3010 r.update(rs) 3011 self.assertEqual(re, e.nsmap) 3012 self.assertEqual(r, s.nsmap)
3013
3014 - def test_html_prefix_nsmap(self):
3015 etree = self.etree 3016 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description') 3017 self.assertEqual({'hha': None}, el.nsmap)
3018
3019 - def test_getiterator_filter_multiple(self):
3020 Element = self.etree.Element 3021 SubElement = self.etree.SubElement 3022 3023 a = Element('a') 3024 b = SubElement(a, 'b') 3025 c = SubElement(a, 'c') 3026 d = SubElement(b, 'd') 3027 e = SubElement(c, 'e') 3028 f = SubElement(c, 'f') 3029 3030 self.assertEqual( 3031 [a, b], 3032 list(a.getiterator('a', 'b'))) 3033 self.assertEqual( 3034 [], 3035 list(a.getiterator('x', 'y'))) 3036 self.assertEqual( 3037 [a, f], 3038 list(a.getiterator('f', 'a'))) 3039 self.assertEqual( 3040 [c, e, f], 3041 list(c.getiterator('c', '*', 'a'))) 3042 self.assertEqual( 3043 [], 3044 list(a.getiterator( (), () )))
3045
3046 - def test_getiterator_filter_multiple_tuple(self):
3047 Element = self.etree.Element 3048 SubElement = self.etree.SubElement 3049 3050 a = Element('a') 3051 b = SubElement(a, 'b') 3052 c = SubElement(a, 'c') 3053 d = SubElement(b, 'd') 3054 e = SubElement(c, 'e') 3055 f = SubElement(c, 'f') 3056 3057 self.assertEqual( 3058 [a, b], 3059 list(a.getiterator( ('a', 'b') ))) 3060 self.assertEqual( 3061 [], 3062 list(a.getiterator( ('x', 'y') ))) 3063 self.assertEqual( 3064 [a, f], 3065 list(a.getiterator( ('f', 'a') ))) 3066 self.assertEqual( 3067 [c, e, f], 3068 list(c.getiterator( ('c', '*', 'a') ))) 3069 self.assertEqual( 3070 [], 3071 list(a.getiterator( () )))
3072
3073 - def test_getiterator_filter_namespace(self):
3074 Element = self.etree.Element 3075 SubElement = self.etree.SubElement 3076 3077 a = Element('{a}a') 3078 b = SubElement(a, '{a}b') 3079 c = SubElement(a, '{a}c') 3080 d = SubElement(b, '{b}d') 3081 e = SubElement(c, '{a}e') 3082 f = SubElement(c, '{b}f') 3083 g = SubElement(c, 'g') 3084 3085 self.assertEqual( 3086 [a], 3087 list(a.getiterator('{a}a'))) 3088 self.assertEqual( 3089 [], 3090 list(a.getiterator('{b}a'))) 3091 self.assertEqual( 3092 [], 3093 list(a.getiterator('a'))) 3094 self.assertEqual( 3095 [a,b,d,c,e,f,g], 3096 list(a.getiterator('*'))) 3097 self.assertEqual( 3098 [f], 3099 list(c.getiterator('{b}*'))) 3100 self.assertEqual( 3101 [d, f], 3102 list(a.getiterator('{b}*'))) 3103 self.assertEqual( 3104 [g], 3105 list(a.getiterator('g'))) 3106 self.assertEqual( 3107 [g], 3108 list(a.getiterator('{}g'))) 3109 self.assertEqual( 3110 [g], 3111 list(a.getiterator('{}*')))
3112
3113 - def test_getiterator_filter_local_name(self):
3114 Element = self.etree.Element 3115 Comment = self.etree.Comment 3116 SubElement = self.etree.SubElement 3117 3118 a = Element('{a}a') 3119 b = SubElement(a, '{nsA}b') 3120 c = SubElement(b, '{nsB}b') 3121 d = SubElement(a, 'b') 3122 e = SubElement(a, '{nsA}e') 3123 f = SubElement(e, '{nsB}e') 3124 g = SubElement(e, 'e') 3125 a.append(Comment('test')) 3126 3127 self.assertEqual( 3128 [b, c, d], 3129 list(a.getiterator('{*}b'))) 3130 self.assertEqual( 3131 [e, f, g], 3132 list(a.getiterator('{*}e'))) 3133 self.assertEqual( 3134 [a, b, c, d, e, f, g], 3135 list(a.getiterator('{*}*')))
3136
3137 - def test_getiterator_filter_entities(self):
3138 Element = self.etree.Element 3139 Entity = self.etree.Entity 3140 SubElement = self.etree.SubElement 3141 3142 a = Element('a') 3143 b = SubElement(a, 'b') 3144 entity_b = Entity("TEST-b") 3145 b.append(entity_b) 3146 3147 self.assertEqual( 3148 [entity_b], 3149 list(a.getiterator(Entity))) 3150 3151 entity_a = Entity("TEST-a") 3152 a.append(entity_a) 3153 3154 self.assertEqual( 3155 [entity_b, entity_a], 3156 list(a.getiterator(Entity))) 3157 3158 self.assertEqual( 3159 [entity_b], 3160 list(b.getiterator(Entity)))
3161
3162 - def test_getiterator_filter_element(self):
3163 Element = self.etree.Element 3164 Comment = self.etree.Comment 3165 PI = self.etree.PI 3166 SubElement = self.etree.SubElement 3167 3168 a = Element('a') 3169 b = SubElement(a, 'b') 3170 a.append(Comment("test")) 3171 a.append(PI("pi", "content")) 3172 c = SubElement(a, 'c') 3173 3174 self.assertEqual( 3175 [a, b, c], 3176 list(a.getiterator(Element)))
3177
3178 - def test_getiterator_filter_all_comment_pi(self):
3179 # ElementTree iterates over everything here 3180 Element = self.etree.Element 3181 Comment = self.etree.Comment 3182 PI = self.etree.PI 3183 SubElement = self.etree.SubElement 3184 3185 a = Element('a') 3186 b = SubElement(a, 'b') 3187 a.append(Comment("test")) 3188 a.append(PI("pi", "content")) 3189 c = SubElement(a, 'c') 3190 3191 self.assertEqual( 3192 [a, b, c], 3193 list(a.getiterator('*')))
3194
3195 - def test_elementtree_getelementpath(self):
3196 a = etree.Element("a") 3197 b = etree.SubElement(a, "b") 3198 c = etree.SubElement(a, "c") 3199 d1 = etree.SubElement(c, "d") 3200 d2 = etree.SubElement(c, "d") 3201 c.text = d1.text = 'TEXT' 3202 3203 tree = etree.ElementTree(a) 3204 self.assertEqual('.', tree.getelementpath(a)) 3205 self.assertEqual('c/d[1]', tree.getelementpath(d1)) 3206 self.assertEqual('c/d[2]', tree.getelementpath(d2)) 3207 3208 self.assertEqual(d1, tree.find(tree.getelementpath(d1))) 3209 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3210 3211 tree = etree.ElementTree(c) 3212 self.assertEqual('.', tree.getelementpath(c)) 3213 self.assertEqual('d[2]', tree.getelementpath(d2)) 3214 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3215 3216 tree = etree.ElementTree(b) # not a parent of a/c/d1/d2 3217 self.assertEqual('.', tree.getelementpath(b)) 3218 self.assertRaises(ValueError, tree.getelementpath, a) 3219 self.assertRaises(ValueError, tree.getelementpath, c) 3220 self.assertRaises(ValueError, tree.getelementpath, d2)
3221
3222 - def test_elementtree_getelementpath_ns(self):
3223 a = etree.Element("{http://ns1/}a") 3224 b = etree.SubElement(a, "{http://ns1/}b") 3225 c = etree.SubElement(a, "{http://ns1/}c") 3226 d1 = etree.SubElement(c, "{http://ns1/}d") 3227 d2 = etree.SubElement(c, "{http://ns2/}d") 3228 d3 = etree.SubElement(c, "{http://ns1/}d") 3229 3230 tree = etree.ElementTree(a) 3231 self.assertEqual('.', tree.getelementpath(a)) 3232 self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]', 3233 tree.getelementpath(d1)) 3234 self.assertEqual('{http://ns1/}c/{http://ns2/}d', 3235 tree.getelementpath(d2)) 3236 self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]', 3237 tree.getelementpath(d3)) 3238 3239 self.assertEqual(a, tree.find(tree.getelementpath(a))) 3240 self.assertEqual(b, tree.find(tree.getelementpath(b))) 3241 self.assertEqual(c, tree.find(tree.getelementpath(c))) 3242 self.assertEqual(d1, tree.find(tree.getelementpath(d1))) 3243 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3244 self.assertEqual(d3, tree.find(tree.getelementpath(d3))) 3245 3246 tree = etree.ElementTree(c) 3247 self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1)) 3248 self.assertEqual('{http://ns2/}d', tree.getelementpath(d2)) 3249 self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3)) 3250 self.assertEqual(d1, tree.find(tree.getelementpath(d1))) 3251 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3252 self.assertEqual(d3, tree.find(tree.getelementpath(d3))) 3253 3254 tree = etree.ElementTree(b) # not a parent of d1/d2 3255 self.assertRaises(ValueError, tree.getelementpath, d1) 3256 self.assertRaises(ValueError, tree.getelementpath, d2)
3257
3258 - def test_elementtree_find_qname(self):
3259 XML = self.etree.XML 3260 ElementTree = self.etree.ElementTree 3261 QName = self.etree.QName 3262 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))) 3263 self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
3264
3265 - def test_elementtree_findall_qname(self):
3266 XML = self.etree.XML 3267 ElementTree = self.etree.ElementTree 3268 QName = self.etree.QName 3269 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))) 3270 self.assertEqual(len(list(tree.findall(QName("c")))), 1)
3271
3272 - def test_elementtree_findall_ns_qname(self):
3273 XML = self.etree.XML 3274 ElementTree = self.etree.ElementTree 3275 QName = self.etree.QName 3276 tree = ElementTree(XML( 3277 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))) 3278 self.assertEqual(len(list(tree.findall(QName("b")))), 2) 3279 self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
3280
3281 - def test_findall_ns(self):
3282 XML = self.etree.XML 3283 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')) 3284 self.assertEqual(len(root.findall(".//{X}b")), 2) 3285 self.assertEqual(len(root.findall(".//{X}*")), 2) 3286 self.assertEqual(len(root.findall(".//b")), 3)
3287
3288 - def test_findall_different_nsmaps(self):
3289 XML = self.etree.XML 3290 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>')) 3291 nsmap = {'xx': 'X'} 3292 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) 3293 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2) 3294 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2) 3295 nsmap = {'xx': 'Y'} 3296 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1) 3297 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1) 3298 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3299
3300 - def test_findall_empty_prefix(self):
3301 XML = self.etree.XML 3302 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>')) 3303 nsmap = {'xx': 'X'} 3304 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) 3305 nsmap = {'xx': 'X', None: 'Y'} 3306 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1) 3307 nsmap = {'xx': 'X', '': 'Y'} 3308 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1)
3309
3310 - def test_findall_syntax_error(self):
3311 XML = self.etree.XML 3312 root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>')) 3313 self.assertRaises(SyntaxError, root.findall, '') 3314 self.assertRaises(SyntaxError, root.findall, '//') # absolute path on Element 3315 self.assertRaises(SyntaxError, root.findall, './//')
3316
3317 - def test_index(self):
3318 etree = self.etree 3319 e = etree.Element('foo') 3320 for i in range(10): 3321 etree.SubElement(e, 'a%s' % i) 3322 for i in range(10): 3323 self.assertEqual( 3324 i, 3325 e.index(e[i])) 3326 self.assertEqual( 3327 3, e.index(e[3], 3)) 3328 self.assertRaises( 3329 ValueError, e.index, e[3], 4) 3330 self.assertRaises( 3331 ValueError, e.index, e[3], 0, 2) 3332 self.assertRaises( 3333 ValueError, e.index, e[8], 0, -3) 3334 self.assertRaises( 3335 ValueError, e.index, e[8], -5, -3) 3336 self.assertEqual( 3337 8, e.index(e[8], 0, -1)) 3338 self.assertEqual( 3339 8, e.index(e[8], -12, -1)) 3340 self.assertEqual( 3341 0, e.index(e[0], -12, -1))
3342
3343 - def test_replace(self):
3344 etree = self.etree 3345 e = etree.Element('foo') 3346 for i in range(10): 3347 el = etree.SubElement(e, 'a%s' % i) 3348 el.text = "text%d" % i 3349 el.tail = "tail%d" % i 3350 3351 child0 = e[0] 3352 child1 = e[1] 3353 child2 = e[2] 3354 3355 e.replace(e[0], e[1]) 3356 self.assertEqual( 3357 9, len(e)) 3358 self.assertEqual( 3359 child1, e[0]) 3360 self.assertEqual( 3361 child1.text, "text1") 3362 self.assertEqual( 3363 child1.tail, "tail1") 3364 self.assertEqual( 3365 child0.tail, "tail0") 3366 self.assertEqual( 3367 child2, e[1]) 3368 3369 e.replace(e[-1], e[0]) 3370 self.assertEqual( 3371 child1, e[-1]) 3372 self.assertEqual( 3373 child1.text, "text1") 3374 self.assertEqual( 3375 child1.tail, "tail1") 3376 self.assertEqual( 3377 child2, e[0])
3378
3379 - def test_replace_new(self):
3380 etree = self.etree 3381 e = etree.Element('foo') 3382 for i in range(10): 3383 etree.SubElement(e, 'a%s' % i) 3384 3385 new_element = etree.Element("test") 3386 new_element.text = "TESTTEXT" 3387 new_element.tail = "TESTTAIL" 3388 child1 = e[1] 3389 e.replace(e[0], new_element) 3390 self.assertEqual( 3391 new_element, e[0]) 3392 self.assertEqual( 3393 "TESTTEXT", 3394 e[0].text) 3395 self.assertEqual( 3396 "TESTTAIL", 3397 e[0].tail) 3398 self.assertEqual( 3399 child1, e[1])
3400
3401 - def test_setslice_all_reversed(self):
3402 Element = self.etree.Element 3403 SubElement = self.etree.SubElement 3404 3405 a = Element('a') 3406 3407 e = Element('e') 3408 f = Element('f') 3409 g = Element('g') 3410 3411 a[:] = [e, f, g] 3412 self.assertEqual( 3413 [e, f, g], 3414 list(a)) 3415 3416 a[::-1] = [e, f, g] 3417 self.assertEqual( 3418 [g, f, e], 3419 list(a))
3420
3421 - def test_setslice_step(self):
3422 Element = self.etree.Element 3423 SubElement = self.etree.SubElement 3424 3425 a = Element('a') 3426 b = SubElement(a, 'b') 3427 c = SubElement(a, 'c') 3428 d = SubElement(a, 'd') 3429 e = SubElement(a, 'e') 3430 3431 x = Element('x') 3432 y = Element('y') 3433 3434 a[1::2] = [x, y] 3435 self.assertEqual( 3436 [b, x, d, y], 3437 list(a))
3438
3439 - def test_setslice_step_negative(self):
3440 Element = self.etree.Element 3441 SubElement = self.etree.SubElement 3442 3443 a = Element('a') 3444 b = SubElement(a, 'b') 3445 c = SubElement(a, 'c') 3446 d = SubElement(a, 'd') 3447 e = SubElement(a, 'e') 3448 3449 x = Element('x') 3450 y = Element('y') 3451 3452 a[1::-1] = [x, y] 3453 self.assertEqual( 3454 [y, x, d, e], 3455 list(a))
3456
3457 - def test_setslice_step_negative2(self):
3458 Element = self.etree.Element 3459 SubElement = self.etree.SubElement 3460 3461 a = Element('a') 3462 b = SubElement(a, 'b') 3463 c = SubElement(a, 'c') 3464 d = SubElement(a, 'd') 3465 e = SubElement(a, 'e') 3466 3467 x = Element('x') 3468 y = Element('y') 3469 3470 a[::-2] = [x, y] 3471 self.assertEqual( 3472 [b, y, d, x], 3473 list(a))
3474
3475 - def test_setslice_step_overrun(self):
3476 Element = self.etree.Element 3477 SubElement = self.etree.SubElement 3478 try: 3479 slice 3480 except NameError: 3481 print("slice() not found") 3482 return 3483 3484 a = Element('a') 3485 b = SubElement(a, 'b') 3486 c = SubElement(a, 'c') 3487 d = SubElement(a, 'd') 3488 e = SubElement(a, 'e') 3489 3490 x = Element('x') 3491 y = Element('y') 3492 z = Element('z') 3493 3494 self.assertRaises( 3495 ValueError, 3496 operator.setitem, a, slice(1,None,2), [x, y, z]) 3497 3498 self.assertEqual( 3499 [b, c, d, e], 3500 list(a))
3501
3502 - def test_sourceline_XML(self):
3503 XML = self.etree.XML 3504 root = XML(_bytes('''<?xml version="1.0"?> 3505 <root><test> 3506 3507 <bla/></test> 3508 </root> 3509 ''')) 3510 3511 self.assertEqual( 3512 [2, 2, 4], 3513 [ el.sourceline for el in root.getiterator() ])
3514
3515 - def test_large_sourceline_XML(self):
3516 XML = self.etree.XML 3517 root = XML(_bytes( 3518 '<?xml version="1.0"?>\n' 3519 '<root>' + '\n' * 65536 + 3520 '<p>' + '\n' * 65536 + '</p>\n' + 3521 '<br/>\n' 3522 '</root>')) 3523 3524 if self.etree.LIBXML_VERSION >= (2, 9): 3525 expected = [2, 131074, 131076] 3526 else: 3527 expected = [2, 65535, 65535] 3528 3529 self.assertEqual(expected, [el.sourceline for el in root.iter()])
3530
3531 - def test_sourceline_parse(self):
3532 parse = self.etree.parse 3533 tree = parse(fileInTestDir('include/test_xinclude.xml')) 3534 3535 self.assertEqual( 3536 [1, 2, 3], 3537 [ el.sourceline for el in tree.getiterator() ])
3538
3539 - def test_sourceline_iterparse_end(self):
3540 iterparse = self.etree.iterparse 3541 lines = [ el.sourceline for (event, el) in 3542 iterparse(fileInTestDir('include/test_xinclude.xml')) ] 3543 3544 self.assertEqual( 3545 [2, 3, 1], 3546 lines)
3547
3548 - def test_sourceline_iterparse_start(self):
3549 iterparse = self.etree.iterparse 3550 lines = [ el.sourceline for (event, el) in 3551 iterparse(fileInTestDir('include/test_xinclude.xml'), 3552 events=("start",)) ] 3553 3554 self.assertEqual( 3555 [1, 2, 3], 3556 lines)
3557
3558 - def test_sourceline_element(self):
3559 Element = self.etree.Element 3560 SubElement = self.etree.SubElement 3561 el = Element("test") 3562 self.assertEqual(None, el.sourceline) 3563 3564 child = SubElement(el, "test") 3565 self.assertEqual(None, el.sourceline) 3566 self.assertEqual(None, child.sourceline)
3567
3568 - def test_XML_base_url_docinfo(self):
3569 etree = self.etree 3570 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3571 docinfo = root.getroottree().docinfo 3572 self.assertEqual(docinfo.URL, "http://no/such/url")
3573
3574 - def test_XML_set_base_url_docinfo(self):
3575 etree = self.etree 3576 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3577 docinfo = root.getroottree().docinfo 3578 self.assertEqual(docinfo.URL, "http://no/such/url") 3579 docinfo.URL = "https://secret/url" 3580 self.assertEqual(docinfo.URL, "https://secret/url")
3581
3582 - def test_parse_stringio_base_url(self):
3583 etree = self.etree 3584 tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url") 3585 docinfo = tree.docinfo 3586 self.assertEqual(docinfo.URL, "http://no/such/url")
3587
3588 - def test_parse_base_url_docinfo(self):
3589 etree = self.etree 3590 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'), 3591 base_url="http://no/such/url") 3592 docinfo = tree.docinfo 3593 self.assertEqual(docinfo.URL, "http://no/such/url")
3594
3595 - def test_HTML_base_url_docinfo(self):
3596 etree = self.etree 3597 root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url") 3598 docinfo = root.getroottree().docinfo 3599 self.assertEqual(docinfo.URL, "http://no/such/url")
3600
3601 - def test_docinfo_public(self):
3602 etree = self.etree 3603 xml_header = '<?xml version="1.0" encoding="ascii"?>' 3604 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN" 3605 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" 3606 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id) 3607 3608 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>') 3609 3610 tree = etree.parse(BytesIO(xml)) 3611 docinfo = tree.docinfo 3612 self.assertEqual(docinfo.encoding, "ascii") 3613 self.assertEqual(docinfo.xml_version, "1.0") 3614 self.assertEqual(docinfo.public_id, pub_id) 3615 self.assertEqual(docinfo.system_url, sys_id) 3616 self.assertEqual(docinfo.root_name, 'html') 3617 self.assertEqual(docinfo.doctype, doctype_string)
3618
3619 - def test_docinfo_system(self):
3620 etree = self.etree 3621 xml_header = '<?xml version="1.0" encoding="UTF-8"?>' 3622 sys_id = "some.dtd" 3623 doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id 3624 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>') 3625 3626 tree = etree.parse(BytesIO(xml)) 3627 docinfo = tree.docinfo 3628 self.assertEqual(docinfo.encoding, "UTF-8") 3629 self.assertEqual(docinfo.xml_version, "1.0") 3630 self.assertEqual(docinfo.public_id, None) 3631 self.assertEqual(docinfo.system_url, sys_id) 3632 self.assertEqual(docinfo.root_name, 'html') 3633 self.assertEqual(docinfo.doctype, doctype_string)
3634
3635 - def test_docinfo_empty(self):
3636 etree = self.etree 3637 xml = _bytes('<html><body></body></html>') 3638 tree = etree.parse(BytesIO(xml)) 3639 docinfo = tree.docinfo 3640 self.assertEqual(docinfo.encoding, "UTF-8") 3641 self.assertEqual(docinfo.xml_version, "1.0") 3642 self.assertEqual(docinfo.public_id, None) 3643 self.assertEqual(docinfo.system_url, None) 3644 self.assertEqual(docinfo.root_name, 'html') 3645 self.assertEqual(docinfo.doctype, '')
3646
3647 - def test_docinfo_name_only(self):
3648 etree = self.etree 3649 xml = _bytes('<!DOCTYPE root><root></root>') 3650 tree = etree.parse(BytesIO(xml)) 3651 docinfo = tree.docinfo 3652 self.assertEqual(docinfo.encoding, "UTF-8") 3653 self.assertEqual(docinfo.xml_version, "1.0") 3654 self.assertEqual(docinfo.public_id, None) 3655 self.assertEqual(docinfo.system_url, None) 3656 self.assertEqual(docinfo.root_name, 'root') 3657 self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
3658
3659 - def test_doctype_name_only_roundtrip(self):
3660 etree = self.etree 3661 xml = _bytes('<!DOCTYPE root>\n<root/>') 3662 tree = etree.parse(BytesIO(xml)) 3663 self.assertEqual(xml, etree.tostring(tree))
3664
3665 - def test_doctype_output_override(self):
3666 etree = self.etree 3667 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN" 3668 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" 3669 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)) 3670 3671 xml = _bytes('<!DOCTYPE root>\n<root/>') 3672 tree = etree.parse(BytesIO(xml)) 3673 self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string), 3674 etree.tostring(tree, doctype=doctype_string))
3675
3676 - def test_xml_base(self):
3677 etree = self.etree 3678 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3679 self.assertEqual(root.base, "http://no/such/url") 3680 self.assertEqual( 3681 root.get('{http://www.w3.org/XML/1998/namespace}base'), None) 3682 root.base = "https://secret/url" 3683 self.assertEqual(root.base, "https://secret/url") 3684 self.assertEqual( 3685 root.get('{http://www.w3.org/XML/1998/namespace}base'), 3686 "https://secret/url")
3687
3688 - def test_xml_base_attribute(self):
3689 etree = self.etree 3690 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3691 self.assertEqual(root.base, "http://no/such/url") 3692 self.assertEqual( 3693 root.get('{http://www.w3.org/XML/1998/namespace}base'), None) 3694 root.set('{http://www.w3.org/XML/1998/namespace}base', 3695 "https://secret/url") 3696 self.assertEqual(root.base, "https://secret/url") 3697 self.assertEqual( 3698 root.get('{http://www.w3.org/XML/1998/namespace}base'), 3699 "https://secret/url")
3700
3701 - def test_html_base(self):
3702 etree = self.etree 3703 root = etree.HTML(_bytes("<html><body></body></html>"), 3704 base_url="http://no/such/url") 3705 self.assertEqual(root.base, "http://no/such/url")
3706
3707 - def test_html_base_tag(self):
3708 etree = self.etree 3709 root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>')) 3710 self.assertEqual(root.base, "http://no/such/url")
3711
3712 - def test_parse_fileobject_unicode(self):
3713 # parse from a file object that returns unicode strings 3714 f = LargeFileLikeUnicode() 3715 tree = self.etree.parse(f) 3716 root = tree.getroot() 3717 self.assertTrue(root.tag.endswith('root'))
3718
3719 - def test_dtd_io(self):
3720 # check that DTDs that go in also go back out 3721 xml = _bytes('''\ 3722 <!DOCTYPE test SYSTEM "test.dtd" [ 3723 <!ENTITY entity "tasty"> 3724 <!ELEMENT test (a)> 3725 <!ELEMENT a (#PCDATA)> 3726 ]> 3727 <test><a>test-test</a></test>\ 3728 ''') 3729 tree = self.etree.parse(BytesIO(xml)) 3730 self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")), 3731 xml.replace(_bytes(" "), _bytes("")))
3732
3733 - def test_byte_zero(self):
3734 Element = self.etree.Element 3735 3736 a = Element('a') 3737 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho') 3738 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho') 3739 3740 self.assertRaises(ValueError, Element, 'ha\0ho')
3741
3742 - def test_unicode_byte_zero(self):
3743 Element = self.etree.Element 3744 3745 a = Element('a') 3746 self.assertRaises(ValueError, setattr, a, "text", 3747 _str('ha\0ho')) 3748 self.assertRaises(ValueError, setattr, a, "tail", 3749 _str('ha\0ho')) 3750 3751 self.assertRaises(ValueError, Element, 3752 _str('ha\0ho'))
3753
3754 - def test_byte_invalid(self):
3755 Element = self.etree.Element 3756 3757 a = Element('a') 3758 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho') 3759 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho') 3760 3761 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho') 3762 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho') 3763 3764 self.assertRaises(ValueError, Element, 'ha\x07ho') 3765 self.assertRaises(ValueError, Element, 'ha\x02ho')
3766
3767 - def test_unicode_byte_invalid(self):
3768 Element = self.etree.Element 3769 3770 a = Element('a') 3771 self.assertRaises(ValueError, setattr, a, "text", 3772 _str('ha\x07ho')) 3773 self.assertRaises(ValueError, setattr, a, "text", 3774 _str('ha\x02ho')) 3775 3776 self.assertRaises(ValueError, setattr, a, "tail", 3777 _str('ha\x07ho')) 3778 self.assertRaises(ValueError, setattr, a, "tail", 3779 _str('ha\x02ho')) 3780 3781 self.assertRaises(ValueError, Element, 3782 _str('ha\x07ho')) 3783 self.assertRaises(ValueError, Element, 3784 _str('ha\x02ho'))
3785
3786 - def test_unicode_byte_invalid_sequence(self):
3787 Element = self.etree.Element 3788 3789 a = Element('a') 3790 self.assertRaises(ValueError, setattr, a, "text", 3791 _str('ha\u1234\x07ho')) 3792 self.assertRaises(ValueError, setattr, a, "text", 3793 _str('ha\u1234\x02ho')) 3794 3795 self.assertRaises(ValueError, setattr, a, "tail", 3796 _str('ha\u1234\x07ho')) 3797 self.assertRaises(ValueError, setattr, a, "tail", 3798 _str('ha\u1234\x02ho')) 3799 3800 self.assertRaises(ValueError, Element, 3801 _str('ha\u1234\x07ho')) 3802 self.assertRaises(ValueError, Element, 3803 _str('ha\u1234\x02ho'))
3804
3805 - def test_encoding_tostring_utf16(self):
3806 # ElementTree fails to serialize this 3807 tostring = self.etree.tostring 3808 Element = self.etree.Element 3809 SubElement = self.etree.SubElement 3810 3811 a = Element('a') 3812 b = SubElement(a, 'b') 3813 c = SubElement(a, 'c') 3814 3815 result = tostring(a, encoding='UTF-16') 3816 self.assertEqual(_bytes('<a><b></b><c></c></a>'), 3817 canonicalize(result))
3818
3819 - def test_tostring_none(self):
3820 # ElementTree raises an AssertionError here 3821 tostring = self.etree.tostring 3822 self.assertRaises(TypeError, self.etree.tostring, None)
3823
3824 - def test_tostring_pretty(self):
3825 tostring = self.etree.tostring 3826 Element = self.etree.Element 3827 SubElement = self.etree.SubElement 3828 3829 a = Element('a') 3830 b = SubElement(a, 'b') 3831 c = SubElement(a, 'c') 3832 3833 result = tostring(a) 3834 self.assertEqual(result, _bytes("<a><b/><c/></a>")) 3835 3836 result = tostring(a, pretty_print=False) 3837 self.assertEqual(result, _bytes("<a><b/><c/></a>")) 3838 3839 result = tostring(a, pretty_print=True) 3840 self.assertEqual(result, _bytes("<a>\n <b/>\n <c/>\n</a>\n"))
3841
3842 - def test_tostring_with_tail(self):
3843 tostring = self.etree.tostring 3844 Element = self.etree.Element 3845 SubElement = self.etree.SubElement 3846 3847 a = Element('a') 3848 a.tail = "aTAIL" 3849 b = SubElement(a, 'b') 3850 b.tail = "bTAIL" 3851 c = SubElement(a, 'c') 3852 3853 result = tostring(a) 3854 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL")) 3855 3856 result = tostring(a, with_tail=False) 3857 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>")) 3858 3859 result = tostring(a, with_tail=True) 3860 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
3861
3862 - def test_tostring_method_html_with_tail(self):
3863 tostring = self.etree.tostring 3864 html = self.etree.fromstring( 3865 '<html><body>' 3866 '<div><p>Some text<i>\r\n</i></p></div>\r\n' 3867 '</body></html>', 3868 parser=self.etree.HTMLParser()) 3869 self.assertEqual(html.tag, 'html') 3870 div = html.find('.//div') 3871 self.assertEqual(div.tail, '\r\n') 3872 result = tostring(div, method='html') 3873 self.assertEqual( 3874 result, 3875 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n")) 3876 result = tostring(div, method='html', with_tail=True) 3877 self.assertEqual( 3878 result, 3879 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n")) 3880 result = tostring(div, method='html', with_tail=False) 3881 self.assertEqual( 3882 result, 3883 _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
3884
3885 - def test_standalone(self):
3886 tostring = self.etree.tostring 3887 XML = self.etree.XML 3888 ElementTree = self.etree.ElementTree 3889 Element = self.etree.Element 3890 3891 tree = Element("root").getroottree() 3892 self.assertEqual(None, tree.docinfo.standalone) 3893 3894 tree = XML(_bytes("<root/>")).getroottree() 3895 self.assertEqual(None, tree.docinfo.standalone) 3896 3897 tree = XML(_bytes( 3898 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>" 3899 )).getroottree() 3900 self.assertEqual(True, tree.docinfo.standalone) 3901 3902 tree = XML(_bytes( 3903 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>" 3904 )).getroottree() 3905 self.assertEqual(False, tree.docinfo.standalone)
3906
3907 - def test_tostring_standalone(self):
3908 tostring = self.etree.tostring 3909 XML = self.etree.XML 3910 ElementTree = self.etree.ElementTree 3911 3912 root = XML(_bytes("<root/>")) 3913 3914 tree = ElementTree(root) 3915 self.assertEqual(None, tree.docinfo.standalone) 3916 3917 result = tostring(root, xml_declaration=True, encoding="ASCII") 3918 self.assertEqual(result, _bytes( 3919 "<?xml version='1.0' encoding='ASCII'?>\n<root/>")) 3920 3921 result = tostring(root, xml_declaration=True, encoding="ASCII", 3922 standalone=True) 3923 self.assertEqual(result, _bytes( 3924 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>")) 3925 3926 tree = ElementTree(XML(result)) 3927 self.assertEqual(True, tree.docinfo.standalone) 3928 3929 result = tostring(root, xml_declaration=True, encoding="ASCII", 3930 standalone=False) 3931 self.assertEqual(result, _bytes( 3932 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>")) 3933 3934 tree = ElementTree(XML(result)) 3935 self.assertEqual(False, tree.docinfo.standalone)
3936
3937 - def test_tostring_standalone_in_out(self):
3938 tostring = self.etree.tostring 3939 XML = self.etree.XML 3940 ElementTree = self.etree.ElementTree 3941 3942 root = XML(_bytes( 3943 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>")) 3944 3945 tree = ElementTree(root) 3946 self.assertEqual(True, tree.docinfo.standalone) 3947 3948 result = tostring(root, xml_declaration=True, encoding="ASCII") 3949 self.assertEqual(result, _bytes( 3950 "<?xml version='1.0' encoding='ASCII'?>\n<root/>")) 3951 3952 result = tostring(root, xml_declaration=True, encoding="ASCII", 3953 standalone=True) 3954 self.assertEqual(result, _bytes( 3955 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3956
3957 - def test_tostring_method_text_encoding(self):
3958 tostring = self.etree.tostring 3959 Element = self.etree.Element 3960 SubElement = self.etree.SubElement 3961 3962 a = Element('a') 3963 a.text = "A" 3964 a.tail = "tail" 3965 b = SubElement(a, 'b') 3966 b.text = "B" 3967 b.tail = _str("Søk på nettet") 3968 c = SubElement(a, 'c') 3969 c.text = "C" 3970 3971 result = tostring(a, method="text", encoding="UTF-16") 3972 3973 self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"), 3974 result)
3975
3976 - def test_tostring_method_text_unicode(self):
3977 tostring = self.etree.tostring 3978 Element = self.etree.Element 3979 SubElement = self.etree.SubElement 3980 3981 a = Element('a') 3982 a.text = _str('Søk på nettetA') 3983 a.tail = "tail" 3984 b = SubElement(a, 'b') 3985 b.text = "B" 3986 b.tail = _str('Søk på nettetB') 3987 c = SubElement(a, 'c') 3988 c.text = "C" 3989 3990 self.assertRaises(UnicodeEncodeError, 3991 tostring, a, method="text") 3992 3993 self.assertEqual( 3994 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'), 3995 tostring(a, encoding="UTF-8", method="text"))
3996
3997 - def test_tounicode(self):
3998 tounicode = self.etree.tounicode 3999 Element = self.etree.Element 4000 SubElement = self.etree.SubElement 4001 4002 a = Element('a') 4003 b = SubElement(a, 'b') 4004 c = SubElement(a, 'c') 4005 4006 self.assertTrue(isinstance(tounicode(a), _unicode)) 4007 self.assertEqual(_bytes('<a><b></b><c></c></a>'), 4008 canonicalize(tounicode(a)))
4009
4010 - def test_tounicode_element(self):
4011 tounicode = self.etree.tounicode 4012 Element = self.etree.Element 4013 SubElement = self.etree.SubElement 4014 4015 a = Element('a') 4016 b = SubElement(a, 'b') 4017 c = SubElement(a, 'c') 4018 d = SubElement(c, 'd') 4019 self.assertTrue(isinstance(tounicode(b), _unicode)) 4020 self.assertTrue(isinstance(tounicode(c), _unicode)) 4021 self.assertEqual(_bytes('<b></b>'), 4022 canonicalize(tounicode(b))) 4023 self.assertEqual(_bytes('<c><d></d></c>'), 4024 canonicalize(tounicode(c)))
4025
4026 - def test_tounicode_none(self):
4027 tounicode = self.etree.tounicode 4028 self.assertRaises(TypeError, self.etree.tounicode, None)
4029
4030 - def test_tounicode_element_tail(self):
4031 tounicode = self.etree.tounicode 4032 Element = self.etree.Element 4033 SubElement = self.etree.SubElement 4034 4035 a = Element('a') 4036 b = SubElement(a, 'b') 4037 c = SubElement(a, 'c') 4038 d = SubElement(c, 'd') 4039 b.tail = 'Foo' 4040 4041 self.assertTrue(isinstance(tounicode(b), _unicode)) 4042 self.assertTrue(tounicode(b) == '<b/>Foo' or 4043 tounicode(b) == '<b />Foo')
4044
4045 - def test_tounicode_pretty(self):
4046 tounicode = self.etree.tounicode 4047 Element = self.etree.Element 4048 SubElement = self.etree.SubElement 4049 4050 a = Element('a') 4051 b = SubElement(a, 'b') 4052 c = SubElement(a, 'c') 4053 4054 result = tounicode(a) 4055 self.assertEqual(result, "<a><b/><c/></a>") 4056 4057 result = tounicode(a, pretty_print=False) 4058 self.assertEqual(result, "<a><b/><c/></a>") 4059 4060 result = tounicode(a, pretty_print=True) 4061 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4062
4063 - def test_tostring_unicode(self):
4064 tostring = self.etree.tostring 4065 Element = self.etree.Element 4066 SubElement = self.etree.SubElement 4067 4068 a = Element('a') 4069 b = SubElement(a, 'b') 4070 c = SubElement(a, 'c') 4071 4072 self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode)) 4073 self.assertEqual(_bytes('<a><b></b><c></c></a>'), 4074 canonicalize(tostring(a, encoding=_unicode)))
4075
4076 - def test_tostring_unicode_element(self):
4077 tostring = self.etree.tostring 4078 Element = self.etree.Element 4079 SubElement = self.etree.SubElement 4080 4081 a = Element('a') 4082 b = SubElement(a, 'b') 4083 c = SubElement(a, 'c') 4084 d = SubElement(c, 'd') 4085 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode)) 4086 self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode)) 4087 self.assertEqual(_bytes('<b></b>'), 4088 canonicalize(tostring(b, encoding=_unicode))) 4089 self.assertEqual(_bytes('<c><d></d></c>'), 4090 canonicalize(tostring(c, encoding=_unicode)))
4091
4092 - def test_tostring_unicode_none(self):
4093 tostring = self.etree.tostring 4094 self.assertRaises(TypeError, self.etree.tostring, 4095 None, encoding=_unicode)
4096
4097 - def test_tostring_unicode_element_tail(self):
4098 tostring = self.etree.tostring 4099 Element = self.etree.Element 4100 SubElement = self.etree.SubElement 4101 4102 a = Element('a') 4103 b = SubElement(a, 'b') 4104 c = SubElement(a, 'c') 4105 d = SubElement(c, 'd') 4106 b.tail = 'Foo' 4107 4108 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode)) 4109 self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or 4110 tostring(b, encoding=_unicode) == '<b />Foo')
4111
4112 - def test_tostring_unicode_pretty(self):
4113 tostring = self.etree.tostring 4114 Element = self.etree.Element 4115 SubElement = self.etree.SubElement 4116 4117 a = Element('a') 4118 b = SubElement(a, 'b') 4119 c = SubElement(a, 'c') 4120 4121 result = tostring(a, encoding=_unicode) 4122 self.assertEqual(result, "<a><b/><c/></a>") 4123 4124 result = tostring(a, encoding=_unicode, pretty_print=False) 4125 self.assertEqual(result, "<a><b/><c/></a>") 4126 4127 result = tostring(a, encoding=_unicode, pretty_print=True) 4128 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4129
4130 - def test_pypy_proxy_collect(self):
4131 root = etree.Element('parent') 4132 etree.SubElement(root, 'child') 4133 4134 self.assertEqual(len(root), 1) 4135 self.assertEqual(root[0].tag, 'child') 4136 4137 # in PyPy, GC used to kill the Python proxy instance without cleanup 4138 gc.collect() 4139 self.assertEqual(len(root), 1) 4140 self.assertEqual(root[0].tag, 'child')
4141
4142 - def test_element_refcycle(self):
4143 class SubEl(etree.ElementBase): 4144 pass
4145 4146 el1 = SubEl() 4147 el2 = SubEl() 4148 self.assertEqual('SubEl', el1.tag) 4149 self.assertEqual('SubEl', el2.tag) 4150 el1.other = el2 4151 el2.other = el1 4152 4153 del el1, el2 4154 gc.collect() 4155 # not really testing anything here, but it shouldn't crash 4156
4157 - def test_proxy_collect_siblings(self):
4158 root = etree.Element('parent') 4159 c1 = etree.SubElement(root, 'child1') 4160 c2 = etree.SubElement(root, 'child2') 4161 4162 root.remove(c1) 4163 root.remove(c2) 4164 c1.addnext(c2) 4165 del c1 4166 # trigger deallocation attempt of c1 4167 c2.getprevious() 4168 # make sure it wasn't deallocated 4169 self.assertEqual('child1', c2.getprevious().tag)
4170
4171 - def test_proxy_collect_siblings_text(self):
4172 root = etree.Element('parent') 4173 c1 = etree.SubElement(root, 'child1') 4174 c2 = etree.SubElement(root, 'child2') 4175 4176 root.remove(c1) 4177 root.remove(c2) 4178 c1.addnext(c2) 4179 c1.tail = 'abc' 4180 c2.tail = 'xyz' 4181 del c1 4182 # trigger deallocation attempt of c1 4183 c2.getprevious() 4184 # make sure it wasn't deallocated 4185 self.assertEqual('child1', c2.getprevious().tag) 4186 self.assertEqual('abc', c2.getprevious().tail)
4187 4188 # helper methods 4189
4190 - def _writeElement(self, element, encoding='us-ascii', compression=0):
4191 """Write out element for comparison. 4192 """ 4193 ElementTree = self.etree.ElementTree 4194 f = BytesIO() 4195 tree = ElementTree(element=element) 4196 tree.write(f, encoding=encoding, compression=compression) 4197 data = f.getvalue() 4198 if compression: 4199 data = zlib.decompress(data) 4200 return canonicalize(data)
4201 4202
4203 -class _XIncludeTestCase(HelperTestCase):
4204 - def test_xinclude_text(self):
4205 filename = fileInTestDir('test_broken.xml') 4206 root = etree.XML(_bytes('''\ 4207 <doc xmlns:xi="http://www.w3.org/2001/XInclude"> 4208 <xi:include href="%s" parse="text"/> 4209 </doc> 4210 ''' % path2url(filename))) 4211 old_text = root.text 4212 content = read_file(filename) 4213 old_tail = root[0].tail 4214 4215 self.include( etree.ElementTree(root) ) 4216 self.assertEqual(old_text + content + old_tail, 4217 root.text)
4218
4219 - def test_xinclude(self):
4220 tree = etree.parse(fileInTestDir('include/test_xinclude.xml')) 4221 self.assertNotEqual( 4222 'a', 4223 tree.getroot()[1].tag) 4224 # process xincludes 4225 self.include( tree ) 4226 # check whether we find it replaced with included data 4227 self.assertEqual( 4228 'a', 4229 tree.getroot()[1].tag)
4230
4231 - def test_xinclude_resolver(self):
4232 class res(etree.Resolver): 4233 include_text = read_file(fileInTestDir('test.xml')) 4234 called = {} 4235 def resolve(self, url, id, context): 4236 if url.endswith(".dtd"): 4237 self.called["dtd"] = True 4238 return self.resolve_filename( 4239 fileInTestDir('test.dtd'), context) 4240 elif url.endswith("test_xinclude.xml"): 4241 self.called["input"] = True 4242 return None # delegate to default resolver 4243 else: 4244 self.called["include"] = True 4245 return self.resolve_string(self.include_text, context)
4246 4247 res_instance = res() 4248 parser = etree.XMLParser(load_dtd = True) 4249 parser.resolvers.add(res_instance) 4250 4251 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'), 4252 parser = parser) 4253 4254 self.include(tree) 4255 4256 called = list(res_instance.called.items()) 4257 called.sort() 4258 self.assertEqual( 4259 [("dtd", True), ("include", True), ("input", True)], 4260 called) 4261
4262 - def test_xinclude_resolver_recursive(self):
4263 data = textwrap.dedent(''' 4264 <doc xmlns:xi="http://www.w3.org/2001/XInclude"> 4265 <foo/> 4266 <xi:include href="./test.xml" /> 4267 </doc> 4268 ''') 4269 4270 class Resolver(etree.Resolver): 4271 called = {} 4272 4273 def resolve(self, url, id, context): 4274 if url.endswith("test_xinclude.xml"): 4275 assert not self.called.get("input") 4276 self.called["input"] = True 4277 return None # delegate to default resolver 4278 elif url.endswith('/test5.xml'): 4279 assert not self.called.get("DONE") 4280 self.called["DONE"] = True 4281 return self.resolve_string('<DONE/>', context) 4282 else: 4283 _, filename = url.rsplit('/', 1) 4284 assert not self.called.get(filename) 4285 self.called[filename] = True 4286 next_data = data.replace( 4287 'test.xml', 'test%d.xml' % len(self.called)) 4288 return self.resolve_string(next_data, context)
4289 4290 res_instance = Resolver() 4291 parser = etree.XMLParser(load_dtd=True) 4292 parser.resolvers.add(res_instance) 4293 4294 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'), 4295 parser=parser) 4296 4297 self.include(tree) 4298 4299 called = list(res_instance.called.items()) 4300 called.sort() 4301 self.assertEqual( 4302 [("DONE", True), ("input", True), ("test.xml", True), 4303 ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)], 4304 called) 4305 4306
4307 -class ETreeXIncludeTestCase(_XIncludeTestCase):
4308 - def include(self, tree):
4309 tree.xinclude()
4310 4311
4312 -class ElementIncludeTestCase(_XIncludeTestCase):
4313 from lxml import ElementInclude 4314
4315 - def include(self, tree, loader=None, max_depth=None):
4316 self.ElementInclude.include(tree.getroot(), loader=loader, max_depth=max_depth)
4317 4318 XINCLUDE = {} 4319 4320 XINCLUDE["Recursive1.xml"] = """\ 4321 <?xml version='1.0'?> 4322 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4323 <p>The following is the source code of Recursive2.xml:</p> 4324 <xi:include href="Recursive2.xml"/> 4325 </document> 4326 """ 4327 4328 XINCLUDE["Recursive2.xml"] = """\ 4329 <?xml version='1.0'?> 4330 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4331 <p>The following is the source code of Recursive3.xml:</p> 4332 <xi:include href="Recursive3.xml"/> 4333 </document> 4334 """ 4335 4336 XINCLUDE["Recursive3.xml"] = """\ 4337 <?xml version='1.0'?> 4338 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4339 <p>The following is the source code of Recursive1.xml:</p> 4340 <xi:include href="Recursive1.xml"/> 4341 </document> 4342 """ 4343 4344 XINCLUDE["NonRecursive1.xml"] = """\ 4345 <?xml version='1.0'?> 4346 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4347 <p>The following is multiple times the source code of NonRecursive3.xml:</p> 4348 <xi:include href="NonRecursive3.xml"/> 4349 <xi:include href="NonRecursive3.xml"/> 4350 <p>The following is multiple times the source code of Leaf.xml:</p> 4351 <xi:include href="Leaf.xml"/> 4352 <xi:include href="Leaf.xml"/> 4353 <xi:include href="Leaf.xml"/> 4354 <p>One more time the source code of NonRecursive3.xml:</p> 4355 <xi:include href="NonRecursive3.xml"/> 4356 </document> 4357 """ 4358 4359 XINCLUDE["NonRecursive2.xml"] = """\ 4360 <?xml version='1.0'?> 4361 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4362 <p>The following is multiple times the source code of NonRecursive3.xml:</p> 4363 <xi:include href="NonRecursive3.xml"/> 4364 <xi:include href="NonRecursive3.xml"/> 4365 </document> 4366 """ 4367 4368 XINCLUDE["NonRecursive3.xml"] = """\ 4369 <?xml version='1.0'?> 4370 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4371 <p>The following is multiple times the source code of Leaf.xml:</p> 4372 <xi:include href="Leaf.xml"/> 4373 <xi:include href="Leaf.xml"/> 4374 </document> 4375 """ 4376 4377 XINCLUDE["Leaf.xml"] = """\ 4378 <?xml version='1.0'?> 4379 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4380 <p>No further includes</p> 4381 </document> 4382 """ 4383
4384 - def xinclude_loader(self, href, parse="xml", encoding=None):
4385 try: 4386 data = textwrap.dedent(self.XINCLUDE[href]) 4387 except KeyError: 4388 raise OSError("resource not found") 4389 if parse == "xml": 4390 data = etree.fromstring(data) 4391 return data
4392
4393 - def test_xinclude_failures(self):
4394 # Test infinitely recursive includes. 4395 document = self.xinclude_loader("Recursive1.xml").getroottree() 4396 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm: 4397 self.include(document, self.xinclude_loader) 4398 self.assertEqual(str(cm.exception), 4399 "recursive include of 'Recursive2.xml' detected") 4400 4401 # Test 'max_depth' limitation. 4402 document = self.xinclude_loader("Recursive1.xml").getroottree() 4403 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm: 4404 self.include(document, self.xinclude_loader, max_depth=None) 4405 self.assertEqual(str(cm.exception), 4406 "recursive include of 'Recursive2.xml' detected") 4407 4408 document = self.xinclude_loader("Recursive1.xml").getroottree() 4409 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm: 4410 self.include(document, self.xinclude_loader, max_depth=0) 4411 self.assertEqual(str(cm.exception), 4412 "maximum xinclude depth reached when including file Recursive2.xml") 4413 4414 document = self.xinclude_loader("Recursive1.xml").getroottree() 4415 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm: 4416 self.include(document, self.xinclude_loader, max_depth=1) 4417 self.assertEqual(str(cm.exception), 4418 "maximum xinclude depth reached when including file Recursive3.xml") 4419 4420 document = self.xinclude_loader("Recursive1.xml").getroottree() 4421 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm: 4422 self.include(document, self.xinclude_loader, max_depth=2) 4423 self.assertEqual(str(cm.exception), 4424 "maximum xinclude depth reached when including file Recursive1.xml") 4425 4426 document = self.xinclude_loader("Recursive1.xml").getroottree() 4427 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm: 4428 self.include(document, self.xinclude_loader, max_depth=3) 4429 self.assertEqual(str(cm.exception), 4430 "recursive include of 'Recursive2.xml' detected")
4431
4433 # Test that including the same file multiple times, but on the same level 4434 # is not detected as recursive include 4435 document = self.xinclude_loader("NonRecursive3.xml").getroottree() 4436 self.include(document, self.xinclude_loader) 4437 4438 # same but for more than one level 4439 document = self.xinclude_loader("NonRecursive1.xml").getroottree() 4440 self.include(document, self.xinclude_loader) 4441 4442 # same but no Leaf.xml in top-level file 4443 document = self.xinclude_loader("NonRecursive2.xml").getroottree() 4444 self.include(document, self.xinclude_loader)
4445 4446
4447 -class ETreeC14NTestCase(HelperTestCase):
4448 - def test_c14n(self):
4449 tree = self.parse(_bytes('<a><b/></a>')) 4450 f = BytesIO() 4451 tree.write_c14n(f) 4452 s = f.getvalue() 4453 self.assertEqual(_bytes('<a><b></b></a>'), 4454 s)
4455
4456 - def test_c14n_gzip(self):
4457 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4458 f = BytesIO() 4459 tree.write_c14n(f, compression=9) 4460 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile: 4461 s = gzfile.read() 4462 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'), 4463 s)
4464
4465 - def test_c14n_file(self):
4466 tree = self.parse(_bytes('<a><b/></a>')) 4467 with tmpfile() as filename: 4468 tree.write_c14n(filename) 4469 data = read_file(filename, 'rb') 4470 self.assertEqual(_bytes('<a><b></b></a>'), 4471 data)
4472
4473 - def test_c14n_file_gzip(self):
4474 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4475 with tmpfile() as filename: 4476 tree.write_c14n(filename, compression=9) 4477 with gzip.open(filename, 'rb') as f: 4478 data = f.read() 4479 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'), 4480 data)
4481
4482 - def test_c14n2_file_gzip(self):
4483 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4484 with tmpfile() as filename: 4485 tree.write(filename, method='c14n2', compression=9) 4486 with gzip.open(filename, 'rb') as f: 4487 data = f.read() 4488 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'), 4489 data)
4490
4491 - def test_c14n2_with_text(self):
4492 tree = self.parse( 4493 b'<?xml version="1.0"?> <a> abc \n <b> btext </b> btail <c/> ctail </a> ') 4494 f = BytesIO() 4495 tree.write(f, method='c14n2') 4496 s = f.getvalue() 4497 self.assertEqual(b'<a> abc \n <b> btext </b> btail <c></c> ctail </a>', 4498 s) 4499 4500 f = BytesIO() 4501 tree.write(f, method='c14n2', strip_text=True) 4502 s = f.getvalue() 4503 self.assertEqual(b'<a>abc<b>btext</b>btail<c></c>ctail</a>', 4504 s)
4505
4506 - def test_c14n_with_comments(self):
4507 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4508 f = BytesIO() 4509 tree.write_c14n(f) 4510 s = f.getvalue() 4511 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4512 s) 4513 f = BytesIO() 4514 tree.write_c14n(f, with_comments=True) 4515 s = f.getvalue() 4516 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4517 s) 4518 f = BytesIO() 4519 tree.write_c14n(f, with_comments=False) 4520 s = f.getvalue() 4521 self.assertEqual(_bytes('<a><b></b></a>'), 4522 s)
4523
4524 - def test_c14n2_with_comments(self):
4525 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4526 f = BytesIO() 4527 tree.write(f, method='c14n2') 4528 s = f.getvalue() 4529 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4530 s) 4531 f = BytesIO() 4532 tree.write(f, method='c14n2', with_comments=True) 4533 s = f.getvalue() 4534 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4535 s) 4536 f = BytesIO() 4537 tree.write(f, method='c14n2', with_comments=False) 4538 s = f.getvalue() 4539 self.assertEqual(_bytes('<a><b></b></a>'), 4540 s)
4541
4543 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4544 s = etree.tostring(tree, method='c14n') 4545 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4546 s) 4547 s = etree.tostring(tree, method='c14n', with_comments=True) 4548 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4549 s) 4550 s = etree.tostring(tree, method='c14n', with_comments=False) 4551 self.assertEqual(_bytes('<a><b></b></a>'), 4552 s)
4553
4555 tree = self.parse(b'<!--hi--><a><!--ho--><b/></a><!--hu-->') 4556 s = etree.tostring(tree, method='c14n2') 4557 self.assertEqual(b'<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->', 4558 s) 4559 s = etree.tostring(tree, method='c14n2', with_comments=True) 4560 self.assertEqual(b'<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->', 4561 s) 4562 s = etree.tostring(tree, method='c14n2', with_comments=False) 4563 self.assertEqual(b'<a><b></b></a>', 4564 s)
4565
4567 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4568 s = etree.tostring(tree.getroot(), method='c14n') 4569 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'), 4570 s) 4571 s = etree.tostring(tree.getroot(), method='c14n', with_comments=True) 4572 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'), 4573 s) 4574 s = etree.tostring(tree.getroot(), method='c14n', with_comments=False) 4575 self.assertEqual(_bytes('<a><b></b></a>'), 4576 s)
4577
4578 - def test_c14n_exclusive(self):
4579 tree = self.parse(_bytes( 4580 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4581 f = BytesIO() 4582 tree.write_c14n(f) 4583 s = f.getvalue() 4584 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4585 s) 4586 f = BytesIO() 4587 tree.write_c14n(f, exclusive=False) 4588 s = f.getvalue() 4589 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4590 s) 4591 f = BytesIO() 4592 tree.write_c14n(f, exclusive=True) 4593 s = f.getvalue() 4594 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'), 4595 s) 4596 4597 f = BytesIO() 4598 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z']) 4599 s = f.getvalue() 4600 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'), 4601 s)
4602
4604 tree = self.parse(_bytes( 4605 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4606 s = etree.tostring(tree, method='c14n') 4607 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4608 s) 4609 s = etree.tostring(tree, method='c14n', exclusive=False) 4610 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4611 s) 4612 s = etree.tostring(tree, method='c14n', exclusive=True) 4613 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'), 4614 s) 4615 4616 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y']) 4617 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'), 4618 s)
4619
4621 tree = self.parse(_bytes( 4622 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4623 s = etree.tostring(tree.getroot(), method='c14n') 4624 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4625 s) 4626 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False) 4627 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4628 s) 4629 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True) 4630 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'), 4631 s) 4632 4633 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False) 4634 self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'), 4635 s) 4636 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True) 4637 self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'), 4638 s) 4639 4640 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y']) 4641 self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'), 4642 s)
4643
4645 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)""" 4646 tree = self.parse(_bytes( 4647 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4648 4649 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z']) 4650 self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4651 s)
4652 4653
4654 -class ETreeWriteTestCase(HelperTestCase):
4655 - def test_write(self):
4656 tree = self.parse(_bytes('<a><b/></a>')) 4657 f = BytesIO() 4658 tree.write(f) 4659 s = f.getvalue() 4660 self.assertEqual(_bytes('<a><b/></a>'), 4661 s)
4662
4663 - def test_write_doctype(self):
4664 tree = self.parse(_bytes('<a><b/></a>')) 4665 f = BytesIO() 4666 tree.write(f, doctype='HUHU') 4667 s = f.getvalue() 4668 self.assertEqual(_bytes('HUHU\n<a><b/></a>'), 4669 s)
4670
4671 - def test_write_gzip(self):
4672 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4673 f = BytesIO() 4674 tree.write(f, compression=9) 4675 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile: 4676 s = gzfile.read() 4677 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4678 s)
4679
4680 - def test_write_gzip_doctype(self):
4681 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4682 f = BytesIO() 4683 tree.write(f, compression=9, doctype='<!DOCTYPE a>') 4684 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile: 4685 s = gzfile.read() 4686 self.assertEqual(_bytes('<!DOCTYPE a>\n<a>'+'<b/>'*200+'</a>'), 4687 s)
4688
4689 - def test_write_gzip_level(self):
4690 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4691 f = BytesIO() 4692 tree.write(f, compression=0) 4693 s0 = f.getvalue() 4694 4695 f = BytesIO() 4696 tree.write(f) 4697 self.assertEqual(f.getvalue(), s0) 4698 4699 f = BytesIO() 4700 tree.write(f, compression=1) 4701 s = f.getvalue() 4702 self.assertTrue(len(s) <= len(s0)) 4703 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile: 4704 s1 = gzfile.read() 4705 4706 f = BytesIO() 4707 tree.write(f, compression=9) 4708 s = f.getvalue() 4709 self.assertTrue(len(s) <= len(s0)) 4710 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile: 4711 s9 = gzfile.read() 4712 4713 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4714 s0) 4715 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4716 s1) 4717 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4718 s9)
4719
4720 - def test_write_file(self):
4721 tree = self.parse(_bytes('<a><b/></a>')) 4722 with tmpfile() as filename: 4723 tree.write(filename) 4724 data = read_file(filename, 'rb') 4725 self.assertEqual(_bytes('<a><b/></a>'), 4726 data)
4727
4728 - def test_write_file_gzip(self):
4729 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4730 with tmpfile() as filename: 4731 tree.write(filename, compression=9) 4732 with gzip.open(filename, 'rb') as f: 4733 data = f.read() 4734 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4735 data)
4736
4737 - def test_write_file_gzip_parse(self):
4738 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4739 with tmpfile() as filename: 4740 tree.write(filename, compression=9) 4741 data = etree.tostring(etree.parse(filename)) 4742 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4743 data)
4744
4746 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4747 with tmpfile() as filename: 4748 tree.write(filename, compression=9) 4749 with gzip.GzipFile(filename) as f: 4750 data = etree.tostring(etree.parse(f)) 4751 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4752 data)
4753
4754 - def test_write_file_url(self):
4755 xml = _bytes('<a>'+'<b/>'*200+'</a>') 4756 tree = self.parse(xml) 4757 with tmpfile(prefix="p+%20", suffix=".xml") as filename: 4758 url = 'file://' + (filename if sys.platform != 'win32' 4759 else '/' + filename.replace('\\', '/')) 4760 tree.write(url) 4761 data = read_file(filename, 'rb').replace(_bytes('\n'), _bytes('')) 4762 self.assertEqual(data, xml)
4763 4764
4765 -class ETreeErrorLogTest(HelperTestCase):
4766 etree = etree 4767
4768 - def test_parse_error_logging(self):
4769 parse = self.etree.parse 4770 f = BytesIO('<a><b></c></b></a>') 4771 self.etree.clear_error_log() 4772 try: 4773 parse(f) 4774 logs = None 4775 except SyntaxError: 4776 e = sys.exc_info()[1] 4777 logs = e.error_log 4778 f.close() 4779 self.assertTrue([ log for log in logs 4780 if 'mismatch' in log.message ]) 4781 self.assertTrue([ log for log in logs 4782 if 'PARSER' in log.domain_name]) 4783 self.assertTrue([ log for log in logs 4784 if 'ERR_TAG_NAME_MISMATCH' in log.type_name ]) 4785 self.assertTrue([ log for log in logs 4786 if 1 == log.line ]) 4787 self.assertTrue([ log for log in logs 4788 if 15 == log.column ])
4789
4790 - def _test_python_error_logging(self):
4791 """This can't really be tested as long as there isn't a way to 4792 reset the logging setup ... 4793 """ 4794 parse = self.etree.parse 4795 4796 messages = [] 4797 class Logger(self.etree.PyErrorLog): 4798 def log(self, entry, message, *args): 4799 messages.append(message)
4800 4801 self.etree.use_global_python_log(Logger()) 4802 f = BytesIO('<a><b></c></b></a>') 4803 try: 4804 parse(f) 4805 except SyntaxError: 4806 pass 4807 f.close() 4808 4809 self.assertTrue([ message for message in messages 4810 if 'mismatch' in message ]) 4811 self.assertTrue([ message for message in messages 4812 if ':PARSER:' in message]) 4813 self.assertTrue([ message for message in messages 4814 if ':ERR_TAG_NAME_MISMATCH:' in message ]) 4815 self.assertTrue([ message for message in messages 4816 if ':1:15:' in message ]) 4817 4818
4819 -class XMLPullParserTest(unittest.TestCase):
4820 etree = etree 4821
4822 - def assert_event_tags(self, events, expected):
4823 self.assertEqual([(action, elem.tag) for action, elem in events], 4824 expected)
4825
4827 class Target(object): 4828 def start(self, tag, attrib): 4829 return 'start(%s)' % tag
4830 def end(self, tag): 4831 return 'end(%s)' % tag
4832 def close(self): 4833 return 'close()' 4834 4835 parser = self.etree.XMLPullParser(target=Target()) 4836 events = parser.read_events() 4837 4838 parser.feed('<root><element>') 4839 self.assertFalse(list(events)) 4840 self.assertFalse(list(events)) 4841 parser.feed('</element><child>') 4842 self.assertEqual([('end', 'end(element)')], list(events)) 4843 parser.feed('</child>') 4844 self.assertEqual([('end', 'end(child)')], list(events)) 4845 parser.feed('</root>') 4846 self.assertEqual([('end', 'end(root)')], list(events)) 4847 self.assertFalse(list(events)) 4848 self.assertEqual('close()', parser.close()) 4849
4850 - def test_pull_from_simple_target_start_end(self):
4851 class Target(object): 4852 def start(self, tag, attrib): 4853 return 'start(%s)' % tag
4854 def end(self, tag): 4855 return 'end(%s)' % tag 4856 def close(self): 4857 return 'close()' 4858 4859 parser = self.etree.XMLPullParser( 4860 ['start', 'end'], target=Target()) 4861 events = parser.read_events() 4862 4863 parser.feed('<root><element>') 4864 self.assertEqual( 4865 [('start', 'start(root)'), ('start', 'start(element)')], 4866 list(events)) 4867 self.assertFalse(list(events)) 4868 parser.feed('</element><child>') 4869 self.assertEqual( 4870 [('end', 'end(element)'), ('start', 'start(child)')], 4871 list(events)) 4872 parser.feed('</child>') 4873 self.assertEqual( 4874 [('end', 'end(child)')], 4875 list(events)) 4876 parser.feed('</root>') 4877 self.assertEqual( 4878 [('end', 'end(root)')], 4879 list(events)) 4880 self.assertFalse(list(events)) 4881 self.assertEqual('close()', parser.close()) 4882
4883 - def test_pull_from_tree_builder(self):
4884 parser = self.etree.XMLPullParser( 4885 ['start', 'end'], target=etree.TreeBuilder()) 4886 events = parser.read_events() 4887 4888 parser.feed('<root><element>') 4889 self.assert_event_tags( 4890 events, [('start', 'root'), ('start', 'element')]) 4891 self.assertFalse(list(events)) 4892 parser.feed('</element><child>') 4893 self.assert_event_tags( 4894 events, [('end', 'element'), ('start', 'child')]) 4895 parser.feed('</child>') 4896 self.assert_event_tags( 4897 events, [('end', 'child')]) 4898 parser.feed('</root>') 4899 self.assert_event_tags( 4900 events, [('end', 'root')]) 4901 self.assertFalse(list(events)) 4902 root = parser.close() 4903 self.assertEqual('root', root.tag)
4904
4905 - def test_pull_from_tree_builder_subclass(self):
4906 class Target(etree.TreeBuilder): 4907 def end(self, tag): 4908 el = super(Target, self).end(tag) 4909 el.tag += '-huhu' 4910 return el
4911 4912 parser = self.etree.XMLPullParser( 4913 ['start', 'end'], target=Target()) 4914 events = parser.read_events() 4915 4916 parser.feed('<root><element>') 4917 self.assert_event_tags( 4918 events, [('start', 'root'), ('start', 'element')]) 4919 self.assertFalse(list(events)) 4920 parser.feed('</element><child>') 4921 self.assert_event_tags( 4922 events, [('end', 'element-huhu'), ('start', 'child')]) 4923 parser.feed('</child>') 4924 self.assert_event_tags( 4925 events, [('end', 'child-huhu')]) 4926 parser.feed('</root>') 4927 self.assert_event_tags( 4928 events, [('end', 'root-huhu')]) 4929 self.assertFalse(list(events)) 4930 root = parser.close() 4931 self.assertEqual('root-huhu', root.tag) 4932 4933
4934 -def test_suite():
4935 suite = unittest.TestSuite() 4936 suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)]) 4937 suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)]) 4938 suite.addTests([unittest.makeSuite(ElementIncludeTestCase)]) 4939 suite.addTests([unittest.makeSuite(ETreeC14NTestCase)]) 4940 suite.addTests([unittest.makeSuite(ETreeWriteTestCase)]) 4941 suite.addTests([unittest.makeSuite(ETreeErrorLogTest)]) 4942 suite.addTests([unittest.makeSuite(XMLPullParserTest)]) 4943 4944 # add original doctests from ElementTree selftest modules 4945 from . import selftest, selftest2 4946 suite.addTests(doctest.DocTestSuite(selftest)) 4947 suite.addTests(doctest.DocTestSuite(selftest2)) 4948 4949 # add doctests 4950 suite.addTests(doctest.DocTestSuite(etree)) 4951 suite.addTests( 4952 [make_doctest('../../../doc/tutorial.txt')]) 4953 suite.addTests( 4954 [make_doctest('../../../doc/api.txt')]) 4955 suite.addTests( 4956 [make_doctest('../../../doc/FAQ.txt')]) 4957 suite.addTests( 4958 [make_doctest('../../../doc/parsing.txt')]) 4959 suite.addTests( 4960 [make_doctest('../../../doc/resolvers.txt')]) 4961 return suite
4962 4963 4964 if __name__ == '__main__': 4965 print('to test use test.py %s' % __file__) 4966