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_itertext_comment_pi(self):
1452 # https://bugs.launchpad.net/lxml/+bug/1844674 1453 XML = self.etree.XML 1454 root = XML(_bytes( 1455 "<root>RTEXT<a></a>ATAIL<b/><!-- COMMENT -->CTAIL<?PI PITEXT?> PITAIL </root>" 1456 )) 1457 1458 text = list(root.itertext()) 1459 self.assertEqual(["RTEXT", "ATAIL", "CTAIL", " PITAIL "], 1460 text)
1461
1462 - def test_resolve_string_dtd(self):
1463 parse = self.etree.parse 1464 parser = self.etree.XMLParser(dtd_validation=True) 1465 assertEqual = self.assertEqual 1466 test_url = _str("__nosuch.dtd") 1467 1468 class MyResolver(self.etree.Resolver): 1469 def resolve(self, url, id, context): 1470 assertEqual(url, test_url) 1471 return self.resolve_string( 1472 _str('''<!ENTITY myentity "%s"> 1473 <!ELEMENT doc ANY>''') % url, context)
1474 1475 parser.resolvers.add(MyResolver()) 1476 1477 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1478 tree = parse(StringIO(xml), parser) 1479 root = tree.getroot() 1480 self.assertEqual(root.text, test_url) 1481
1482 - def test_resolve_bytes_dtd(self):
1483 parse = self.etree.parse 1484 parser = self.etree.XMLParser(dtd_validation=True) 1485 assertEqual = self.assertEqual 1486 test_url = _str("__nosuch.dtd") 1487 1488 class MyResolver(self.etree.Resolver): 1489 def resolve(self, url, id, context): 1490 assertEqual(url, test_url) 1491 return self.resolve_string( 1492 (_str('''<!ENTITY myentity "%s"> 1493 <!ELEMENT doc ANY>''') % url).encode('utf-8'), 1494 context)
1495 1496 parser.resolvers.add(MyResolver()) 1497 1498 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1499 tree = parse(StringIO(xml), parser) 1500 root = tree.getroot() 1501 self.assertEqual(root.text, test_url) 1502
1503 - def test_resolve_filelike_dtd(self):
1504 parse = self.etree.parse 1505 parser = self.etree.XMLParser(dtd_validation=True) 1506 assertEqual = self.assertEqual 1507 test_url = _str("__nosuch.dtd") 1508 1509 class MyResolver(self.etree.Resolver): 1510 def resolve(self, url, id, context): 1511 assertEqual(url, test_url) 1512 return self.resolve_file( 1513 SillyFileLike( 1514 _str('''<!ENTITY myentity "%s"> 1515 <!ELEMENT doc ANY>''') % url), context)
1516 1517 parser.resolvers.add(MyResolver()) 1518 1519 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1520 tree = parse(StringIO(xml), parser) 1521 root = tree.getroot() 1522 self.assertEqual(root.text, test_url) 1523
1524 - def test_resolve_filename_dtd(self):
1525 parse = self.etree.parse 1526 parser = self.etree.XMLParser(attribute_defaults=True) 1527 assertEqual = self.assertEqual 1528 test_url = _str("__nosuch.dtd") 1529 1530 class MyResolver(self.etree.Resolver): 1531 def resolve(self, url, id, context): 1532 assertEqual(url, test_url) 1533 return self.resolve_filename( 1534 fileInTestDir('test.dtd'), context)
1535 1536 parser.resolvers.add(MyResolver()) 1537 1538 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1539 tree = parse(StringIO(xml), parser) 1540 root = tree.getroot() 1541 self.assertEqual( 1542 root.attrib, {'default': 'valueA'}) 1543 self.assertEqual( 1544 root[0].attrib, {'default': 'valueB'}) 1545
1546 - def test_resolve_filename_dtd_relative(self):
1547 parse = self.etree.parse 1548 parser = self.etree.XMLParser(attribute_defaults=True) 1549 assertEqual = self.assertEqual 1550 test_url = _str("__nosuch.dtd") 1551 1552 class MyResolver(self.etree.Resolver): 1553 def resolve(self, url, id, context): 1554 expected = fileUrlInTestDir(test_url) 1555 url = url.replace('file://', 'file:') # depends on libxml2 version 1556 expected = expected.replace('file://', 'file:') 1557 assertEqual(url, expected) 1558 return self.resolve_filename( 1559 fileUrlInTestDir('test.dtd'), context)
1560 1561 parser.resolvers.add(MyResolver()) 1562 1563 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1564 tree = parse(StringIO(xml), parser, 1565 base_url=fileUrlInTestDir('__test.xml')) 1566 root = tree.getroot() 1567 self.assertEqual( 1568 root.attrib, {'default': 'valueA'}) 1569 self.assertEqual( 1570 root[0].attrib, {'default': 'valueB'}) 1571
1572 - def test_resolve_file_dtd(self):
1573 parse = self.etree.parse 1574 parser = self.etree.XMLParser(attribute_defaults=True) 1575 assertEqual = self.assertEqual 1576 test_url = _str("__nosuch.dtd") 1577 1578 class MyResolver(self.etree.Resolver): 1579 def resolve(self, url, id, context): 1580 assertEqual(url, test_url) 1581 return self.resolve_file( 1582 open(fileInTestDir('test.dtd'), 'rb'), context)
1583 1584 parser.resolvers.add(MyResolver()) 1585 1586 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1587 tree = parse(StringIO(xml), parser) 1588 root = tree.getroot() 1589 self.assertEqual( 1590 root.attrib, {'default': 'valueA'}) 1591 self.assertEqual( 1592 root[0].attrib, {'default': 'valueB'}) 1593
1594 - def test_resolve_empty(self):
1595 parse = self.etree.parse 1596 parser = self.etree.XMLParser(load_dtd=True) 1597 assertEqual = self.assertEqual 1598 test_url = _str("__nosuch.dtd") 1599 1600 class check(object): 1601 resolved = False
1602 1603 class MyResolver(self.etree.Resolver): 1604 def resolve(self, url, id, context): 1605 assertEqual(url, test_url) 1606 check.resolved = True 1607 return self.resolve_empty(context) 1608 1609 parser.resolvers.add(MyResolver()) 1610 1611 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1612 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser) 1613 self.assertTrue(check.resolved) 1614
1615 - def test_resolve_error(self):
1616 parse = self.etree.parse 1617 parser = self.etree.XMLParser(dtd_validation=True) 1618 1619 class _LocalException(Exception): 1620 pass
1621 1622 class MyResolver(self.etree.Resolver): 1623 def resolve(self, url, id, context): 1624 raise _LocalException 1625 1626 parser.resolvers.add(MyResolver()) 1627 1628 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>' 1629 self.assertRaises(_LocalException, parse, BytesIO(xml), parser) 1630
1631 - def test_entity_parse(self):
1632 parse = self.etree.parse 1633 tostring = self.etree.tostring 1634 parser = self.etree.XMLParser(resolve_entities=False) 1635 Entity = self.etree.Entity 1636 1637 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>') 1638 tree = parse(BytesIO(xml), parser) 1639 root = tree.getroot() 1640 self.assertEqual(root[0].tag, Entity) 1641 self.assertEqual(root[0].text, "&myentity;") 1642 self.assertEqual(root[0].tail, None) 1643 self.assertEqual(root[0].name, "myentity") 1644 1645 self.assertEqual(_bytes('<doc>&myentity;</doc>'), 1646 tostring(root))
1647
1648 - def test_entity_restructure(self):
1649 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp "&#160;"> ]> 1650 <root> 1651 <child1/> 1652 <child2/> 1653 <child3>&nbsp;</child3> 1654 </root>''') 1655 1656 parser = self.etree.XMLParser(resolve_entities=False) 1657 root = etree.fromstring(xml, parser) 1658 self.assertEqual([ el.tag for el in root ], 1659 ['child1', 'child2', 'child3']) 1660 1661 root[0] = root[-1] 1662 self.assertEqual([ el.tag for el in root ], 1663 ['child3', 'child2']) 1664 self.assertEqual(root[0][0].text, '&nbsp;') 1665 self.assertEqual(root[0][0].name, 'nbsp')
1666
1667 - def test_entity_append(self):
1668 Entity = self.etree.Entity 1669 Element = self.etree.Element 1670 tostring = self.etree.tostring 1671 1672 root = Element("root") 1673 root.append( Entity("test") ) 1674 1675 self.assertEqual(root[0].tag, Entity) 1676 self.assertEqual(root[0].text, "&test;") 1677 self.assertEqual(root[0].tail, None) 1678 self.assertEqual(root[0].name, "test") 1679 1680 self.assertEqual(_bytes('<root>&test;</root>'), 1681 tostring(root))
1682
1683 - def test_entity_append_parsed(self):
1684 Entity = self.etree.Entity 1685 Element = self.etree.Element 1686 parser = self.etree.XMLParser(resolve_entities=False) 1687 entity = self.etree.XML('''<!DOCTYPE data [ 1688 <!ENTITY a "a"> 1689 <!ENTITY b "&a;"> 1690 ]> 1691 <data>&b;</data> 1692 ''', parser) 1693 1694 el = Element('test') 1695 el.append(entity) 1696 self.assertEqual(el.tag, 'test') 1697 self.assertEqual(el[0].tag, 'data') 1698 self.assertEqual(el[0][0].tag, Entity) 1699 self.assertEqual(el[0][0].name, 'b')
1700
1701 - def test_entity_values(self):
1702 Entity = self.etree.Entity 1703 self.assertEqual(Entity("test").text, '&test;') 1704 self.assertEqual(Entity("#17683").text, '&#17683;') 1705 self.assertEqual(Entity("#x1768").text, '&#x1768;') 1706 self.assertEqual(Entity("#x98AF").text, '&#x98AF;')
1707
1708 - def test_entity_error(self):
1709 Entity = self.etree.Entity 1710 self.assertRaises(ValueError, Entity, 'a b c') 1711 self.assertRaises(ValueError, Entity, 'a,b') 1712 self.assertRaises(ValueError, Entity, 'a\0b') 1713 self.assertRaises(ValueError, Entity, '#abc') 1714 self.assertRaises(ValueError, Entity, '#xxyz')
1715
1716 - def test_cdata(self):
1717 CDATA = self.etree.CDATA 1718 Element = self.etree.Element 1719 tostring = self.etree.tostring 1720 1721 root = Element("root") 1722 root.text = CDATA('test') 1723 1724 self.assertEqual('test', 1725 root.text) 1726 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1727 tostring(root))
1728
1729 - def test_cdata_tail(self):
1730 CDATA = self.etree.CDATA 1731 Element = self.etree.Element 1732 SubElement = self.etree.SubElement 1733 tostring = self.etree.tostring 1734 1735 root = Element("root") 1736 child = SubElement(root, 'child') 1737 child.tail = CDATA('test') 1738 1739 self.assertEqual('test', child.tail) 1740 self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'), 1741 tostring(root)) 1742 1743 root = Element("root") 1744 root.tail = CDATA('test') 1745 1746 self.assertEqual('test', root.tail) 1747 self.assertEqual(_bytes('<root/><![CDATA[test]]>'), 1748 tostring(root))
1749
1750 - def test_cdata_type(self):
1751 CDATA = self.etree.CDATA 1752 Element = self.etree.Element 1753 root = Element("root") 1754 1755 root.text = CDATA("test") 1756 self.assertEqual('test', root.text) 1757 1758 root.text = CDATA(_str("test")) 1759 self.assertEqual('test', root.text) 1760 1761 self.assertRaises(TypeError, CDATA, 1)
1762
1763 - def test_cdata_errors(self):
1764 CDATA = self.etree.CDATA 1765 Element = self.etree.Element 1766 1767 root = Element("root") 1768 cdata = CDATA('test') 1769 1770 self.assertRaises(TypeError, 1771 root.set, 'attr', cdata) 1772 self.assertRaises(TypeError, 1773 operator.setitem, root.attrib, 'attr', cdata)
1774
1775 - def test_cdata_parser(self):
1776 tostring = self.etree.tostring 1777 parser = self.etree.XMLParser(strip_cdata=False) 1778 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1779 1780 self.assertEqual('test', root.text) 1781 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1782 tostring(root))
1783
1784 - def test_cdata_xpath(self):
1785 tostring = self.etree.tostring 1786 parser = self.etree.XMLParser(strip_cdata=False) 1787 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1788 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1789 tostring(root)) 1790 1791 self.assertEqual(['test'], root.xpath('//text()'))
1792 1793 # TypeError in etree, AssertionError in ElementTree;
1794 - def test_setitem_assert(self):
1795 Element = self.etree.Element 1796 SubElement = self.etree.SubElement 1797 1798 a = Element('a') 1799 b = SubElement(a, 'b') 1800 1801 self.assertRaises(TypeError, 1802 a.__setitem__, 0, 'foo')
1803
1804 - def test_append_error(self):
1805 Element = self.etree.Element 1806 root = Element('root') 1807 # raises AssertionError in ElementTree 1808 self.assertRaises(TypeError, root.append, None) 1809 self.assertRaises(TypeError, root.extend, [None]) 1810 self.assertRaises(TypeError, root.extend, [Element('one'), None]) 1811 self.assertEqual('one', root[0].tag)
1812
1813 - def test_append_recursive_error(self):
1814 Element = self.etree.Element 1815 SubElement = self.etree.SubElement 1816 root = Element('root') 1817 self.assertRaises(ValueError, root.append, root) 1818 child = SubElement(root, 'child') 1819 self.assertRaises(ValueError, child.append, root) 1820 child2 = SubElement(child, 'child2') 1821 self.assertRaises(ValueError, child2.append, root) 1822 self.assertRaises(ValueError, child2.append, child) 1823 self.assertEqual('child2', root[0][0].tag)
1824
1825 - def test_addnext(self):
1826 Element = self.etree.Element 1827 SubElement = self.etree.SubElement 1828 root = Element('root') 1829 SubElement(root, 'a') 1830 SubElement(root, 'b') 1831 1832 self.assertEqual(['a', 'b'], 1833 [c.tag for c in root]) 1834 root[1].addnext(root[0]) 1835 self.assertEqual(['b', 'a'], 1836 [c.tag for c in root])
1837
1838 - def test_addprevious(self):
1839 Element = self.etree.Element 1840 SubElement = self.etree.SubElement 1841 root = Element('root') 1842 SubElement(root, 'a') 1843 SubElement(root, 'b') 1844 1845 self.assertEqual(['a', 'b'], 1846 [c.tag for c in root]) 1847 root[0].addprevious(root[1]) 1848 self.assertEqual(['b', 'a'], 1849 [c.tag for c in root])
1850
1851 - def test_addnext_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.addnext, 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_addprevious_cycle(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 # appending parent as sibling is forbidden 1869 self.assertRaises(ValueError, b.addprevious, a) 1870 self.assertEqual(['a'], [c.tag for c in root]) 1871 self.assertEqual(['b'], [c.tag for c in a])
1872
1873 - def test_addnext_cycle_long(self):
1874 Element = self.etree.Element 1875 SubElement = self.etree.SubElement 1876 root = Element('root') 1877 a = SubElement(root, 'a') 1878 b = SubElement(a, 'b') 1879 c = SubElement(b, 'c') 1880 # appending parent as sibling is forbidden 1881 self.assertRaises(ValueError, c.addnext, a)
1882
1883 - def test_addprevious_cycle_long(self):
1884 Element = self.etree.Element 1885 SubElement = self.etree.SubElement 1886 root = Element('root') 1887 a = SubElement(root, 'a') 1888 b = SubElement(a, 'b') 1889 c = SubElement(b, 'c') 1890 # appending parent as sibling is forbidden 1891 self.assertRaises(ValueError, c.addprevious, a)
1892
1893 - def test_addprevious_noops(self):
1894 Element = self.etree.Element 1895 SubElement = self.etree.SubElement 1896 root = Element('root') 1897 a = SubElement(root, 'a') 1898 b = SubElement(root, 'b') 1899 a.addprevious(a) 1900 self.assertEqual('a', root[0].tag) 1901 self.assertEqual('b', root[1].tag) 1902 b.addprevious(b) 1903 self.assertEqual('a', root[0].tag) 1904 self.assertEqual('b', root[1].tag) 1905 b.addprevious(a) 1906 self.assertEqual('a', root[0].tag) 1907 self.assertEqual('b', root[1].tag)
1908
1909 - def test_addnext_noops(self):
1910 Element = self.etree.Element 1911 SubElement = self.etree.SubElement 1912 root = Element('root') 1913 a = SubElement(root, 'a') 1914 b = SubElement(root, 'b') 1915 a.addnext(a) 1916 self.assertEqual('a', root[0].tag) 1917 self.assertEqual('b', root[1].tag) 1918 b.addnext(b) 1919 self.assertEqual('a', root[0].tag) 1920 self.assertEqual('b', root[1].tag) 1921 a.addnext(b) 1922 self.assertEqual('a', root[0].tag) 1923 self.assertEqual('b', root[1].tag)
1924
1925 - def test_addnext_root(self):
1926 Element = self.etree.Element 1927 a = Element('a') 1928 b = Element('b') 1929 self.assertRaises(TypeError, a.addnext, b)
1930
1931 - def test_addprevious_pi(self):
1932 Element = self.etree.Element 1933 SubElement = self.etree.SubElement 1934 PI = self.etree.PI 1935 root = Element('root') 1936 SubElement(root, 'a') 1937 pi = PI('TARGET', 'TEXT') 1938 pi.tail = "TAIL" 1939 1940 self.assertEqual(_bytes('<root><a></a></root>'), 1941 self._writeElement(root)) 1942 root[0].addprevious(pi) 1943 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'), 1944 self._writeElement(root))
1945
1946 - def test_addprevious_root_pi(self):
1947 Element = self.etree.Element 1948 PI = self.etree.PI 1949 root = Element('root') 1950 pi = PI('TARGET', 'TEXT') 1951 pi.tail = "TAIL" 1952 1953 self.assertEqual(_bytes('<root></root>'), 1954 self._writeElement(root)) 1955 root.addprevious(pi) 1956 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'), 1957 self._writeElement(root))
1958
1959 - def test_addnext_pi(self):
1960 Element = self.etree.Element 1961 SubElement = self.etree.SubElement 1962 PI = self.etree.PI 1963 root = Element('root') 1964 SubElement(root, 'a') 1965 pi = PI('TARGET', 'TEXT') 1966 pi.tail = "TAIL" 1967 1968 self.assertEqual(_bytes('<root><a></a></root>'), 1969 self._writeElement(root)) 1970 root[0].addnext(pi) 1971 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'), 1972 self._writeElement(root))
1973
1974 - def test_addnext_root_pi(self):
1975 Element = self.etree.Element 1976 PI = self.etree.PI 1977 root = Element('root') 1978 pi = PI('TARGET', 'TEXT') 1979 pi.tail = "TAIL" 1980 1981 self.assertEqual(_bytes('<root></root>'), 1982 self._writeElement(root)) 1983 root.addnext(pi) 1984 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'), 1985 self._writeElement(root))
1986
1987 - def test_addnext_comment(self):
1988 Element = self.etree.Element 1989 SubElement = self.etree.SubElement 1990 Comment = self.etree.Comment 1991 root = Element('root') 1992 SubElement(root, 'a') 1993 comment = Comment('TEXT ') 1994 comment.tail = "TAIL" 1995 1996 self.assertEqual(_bytes('<root><a></a></root>'), 1997 self._writeElement(root)) 1998 root[0].addnext(comment) 1999 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'), 2000 self._writeElement(root))
2001
2002 - def test_addnext_root_comment(self):
2003 Element = self.etree.Element 2004 Comment = self.etree.Comment 2005 root = Element('root') 2006 comment = Comment('TEXT ') 2007 comment.tail = "TAIL" 2008 2009 self.assertEqual(_bytes('<root></root>'), 2010 self._writeElement(root)) 2011 root.addnext(comment) 2012 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'), 2013 self._writeElement(root))
2014
2015 - def test_addprevious_comment(self):
2016 Element = self.etree.Element 2017 SubElement = self.etree.SubElement 2018 Comment = self.etree.Comment 2019 root = Element('root') 2020 SubElement(root, 'a') 2021 comment = Comment('TEXT ') 2022 comment.tail = "TAIL" 2023 2024 self.assertEqual(_bytes('<root><a></a></root>'), 2025 self._writeElement(root)) 2026 root[0].addprevious(comment) 2027 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'), 2028 self._writeElement(root))
2029
2030 - def test_addprevious_root_comment(self):
2031 Element = self.etree.Element 2032 Comment = self.etree.Comment 2033 root = Element('root') 2034 comment = Comment('TEXT ') 2035 comment.tail = "TAIL" 2036 2037 self.assertEqual(_bytes('<root></root>'), 2038 self._writeElement(root)) 2039 root.addprevious(comment) 2040 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'), 2041 self._writeElement(root))
2042 2043 # ET's Elements have items() and key(), but not values()
2044 - def test_attribute_values(self):
2045 XML = self.etree.XML 2046 2047 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>')) 2048 values = root.values() 2049 values.sort() 2050 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
2051 2052 # gives error in ElementTree
2053 - def test_comment_empty(self):
2054 Element = self.etree.Element 2055 Comment = self.etree.Comment 2056 2057 a = Element('a') 2058 a.append(Comment()) 2059 self.assertEqual( 2060 _bytes('<a><!----></a>'), 2061 self._writeElement(a))
2062 2063 # ElementTree ignores comments
2064 - def test_comment_parse_empty(self):
2065 ElementTree = self.etree.ElementTree 2066 tostring = self.etree.tostring 2067 2068 xml = _bytes('<a><b/><!----><c/></a>') 2069 f = BytesIO(xml) 2070 doc = ElementTree(file=f) 2071 a = doc.getroot() 2072 self.assertEqual( 2073 '', 2074 a[1].text) 2075 self.assertEqual( 2076 xml, 2077 tostring(a))
2078 2079 # ElementTree ignores comments
2080 - def test_comment_no_proxy_yet(self):
2081 ElementTree = self.etree.ElementTree 2082 2083 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>') 2084 doc = ElementTree(file=f) 2085 a = doc.getroot() 2086 self.assertEqual( 2087 ' hoi ', 2088 a[1].text)
2089 2090 # does not raise an exception in ElementTree
2091 - def test_comment_immutable(self):
2092 Element = self.etree.Element 2093 Comment = self.etree.Comment 2094 2095 c = Comment() 2096 el = Element('myel') 2097 2098 self.assertRaises(TypeError, c.append, el) 2099 self.assertRaises(TypeError, c.insert, 0, el) 2100 self.assertRaises(TypeError, c.set, "myattr", "test")
2101
2102 - def test_comment_immutable_attrib(self):
2103 c = self.etree.Comment() 2104 self.assertEqual(0, len(c.attrib)) 2105 2106 self.assertFalse(c.attrib.__contains__('nope')) 2107 self.assertFalse('nope' in c.attrib) 2108 self.assertFalse('nope' in c.attrib.keys()) 2109 self.assertFalse('nope' in c.attrib.values()) 2110 self.assertFalse(('nope', 'huhu') in c.attrib.items()) 2111 2112 self.assertEqual([], list(c.attrib)) 2113 self.assertEqual([], list(c.attrib.keys())) 2114 self.assertEqual([], list(c.attrib.items())) 2115 self.assertEqual([], list(c.attrib.values())) 2116 self.assertEqual([], list(c.attrib.iterkeys())) 2117 self.assertEqual([], list(c.attrib.iteritems())) 2118 self.assertEqual([], list(c.attrib.itervalues())) 2119 2120 self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU')) 2121 self.assertRaises(KeyError, c.attrib.pop, 'nope') 2122 2123 self.assertRaises(KeyError, c.attrib.__getitem__, 'only') 2124 self.assertRaises(KeyError, c.attrib.__getitem__, 'names') 2125 self.assertRaises(KeyError, c.attrib.__getitem__, 'nope') 2126 self.assertRaises(KeyError, c.attrib.__setitem__, 'nope', 'yep') 2127 self.assertRaises(KeyError, c.attrib.__delitem__, 'nope')
2128 2129 # test passing 'None' to dump()
2130 - def test_dump_none(self):
2131 self.assertRaises(TypeError, self.etree.dump, None)
2132
2133 - def test_prefix(self):
2134 ElementTree = self.etree.ElementTree 2135 2136 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>') 2137 doc = ElementTree(file=f) 2138 a = doc.getroot() 2139 self.assertEqual( 2140 None, 2141 a.prefix) 2142 self.assertEqual( 2143 'foo', 2144 a[0].prefix)
2145
2146 - def test_prefix_default_ns(self):
2147 ElementTree = self.etree.ElementTree 2148 2149 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>') 2150 doc = ElementTree(file=f) 2151 a = doc.getroot() 2152 self.assertEqual( 2153 None, 2154 a.prefix) 2155 self.assertEqual( 2156 None, 2157 a[0].prefix)
2158
2159 - def test_getparent(self):
2160 Element = self.etree.Element 2161 SubElement = self.etree.SubElement 2162 2163 a = Element('a') 2164 b = SubElement(a, 'b') 2165 c = SubElement(a, 'c') 2166 d = SubElement(b, 'd') 2167 self.assertEqual( 2168 None, 2169 a.getparent()) 2170 self.assertEqual( 2171 a, 2172 b.getparent()) 2173 self.assertEqual( 2174 b.getparent(), 2175 c.getparent()) 2176 self.assertEqual( 2177 b, 2178 d.getparent())
2179
2180 - def test_iterchildren(self):
2181 XML = self.etree.XML 2182 2183 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 2184 result = [] 2185 for el in root.iterchildren(): 2186 result.append(el.tag) 2187 self.assertEqual(['one', 'two', 'three'], result)
2188
2189 - def test_iterchildren_reversed(self):
2190 XML = self.etree.XML 2191 2192 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 2193 result = [] 2194 for el in root.iterchildren(reversed=True): 2195 result.append(el.tag) 2196 self.assertEqual(['three', 'two', 'one'], result)
2197
2198 - def test_iterchildren_tag(self):
2199 XML = self.etree.XML 2200 2201 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 2202 result = [] 2203 for el in root.iterchildren(tag='two'): 2204 result.append(el.text) 2205 self.assertEqual(['Two', 'Bla'], result)
2206
2207 - def test_iterchildren_tag_posarg(self):
2208 XML = self.etree.XML 2209 2210 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 2211 result = [] 2212 for el in root.iterchildren('two'): 2213 result.append(el.text) 2214 self.assertEqual(['Two', 'Bla'], result)
2215
2216 - def test_iterchildren_tag_reversed(self):
2217 XML = self.etree.XML 2218 2219 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 2220 result = [] 2221 for el in root.iterchildren(reversed=True, tag='two'): 2222 result.append(el.text) 2223 self.assertEqual(['Bla', 'Two'], result)
2224
2225 - def test_iterchildren_tag_multiple(self):
2226 XML = self.etree.XML 2227 2228 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 2229 result = [] 2230 for el in root.iterchildren(tag=['two', 'three']): 2231 result.append(el.text) 2232 self.assertEqual(['Two', 'Bla', None], result)
2233
2234 - def test_iterchildren_tag_multiple_posarg(self):
2235 XML = self.etree.XML 2236 2237 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 2238 result = [] 2239 for el in root.iterchildren('two', 'three'): 2240 result.append(el.text) 2241 self.assertEqual(['Two', 'Bla', None], result)
2242
2243 - def test_iterchildren_tag_multiple_reversed(self):
2244 XML = self.etree.XML 2245 2246 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 2247 result = [] 2248 for el in root.iterchildren(reversed=True, tag=['two', 'three']): 2249 result.append(el.text) 2250 self.assertEqual([None, 'Bla', 'Two'], result)
2251
2252 - def test_iterancestors(self):
2253 Element = self.etree.Element 2254 SubElement = self.etree.SubElement 2255 2256 a = Element('a') 2257 b = SubElement(a, 'b') 2258 c = SubElement(a, 'c') 2259 d = SubElement(b, 'd') 2260 self.assertEqual( 2261 [], 2262 list(a.iterancestors())) 2263 self.assertEqual( 2264 [a], 2265 list(b.iterancestors())) 2266 self.assertEqual( 2267 [a], 2268 list(c.iterancestors())) 2269 self.assertEqual( 2270 [b, a], 2271 list(d.iterancestors()))
2272
2273 - def test_iterancestors_tag(self):
2274 Element = self.etree.Element 2275 SubElement = self.etree.SubElement 2276 2277 a = Element('a') 2278 b = SubElement(a, 'b') 2279 c = SubElement(a, 'c') 2280 d = SubElement(b, 'd') 2281 self.assertEqual( 2282 [a], 2283 list(d.iterancestors('a'))) 2284 self.assertEqual( 2285 [a], 2286 list(d.iterancestors(tag='a'))) 2287 2288 self.assertEqual( 2289 [b, a], 2290 list(d.iterancestors('*'))) 2291 self.assertEqual( 2292 [b, a], 2293 list(d.iterancestors(tag='*')))
2294
2295 - def test_iterancestors_tag_multiple(self):
2296 Element = self.etree.Element 2297 SubElement = self.etree.SubElement 2298 2299 a = Element('a') 2300 b = SubElement(a, 'b') 2301 c = SubElement(a, 'c') 2302 d = SubElement(b, 'd') 2303 self.assertEqual( 2304 [b, a], 2305 list(d.iterancestors(tag=('a', 'b')))) 2306 self.assertEqual( 2307 [b, a], 2308 list(d.iterancestors('a', 'b'))) 2309 2310 self.assertEqual( 2311 [], 2312 list(d.iterancestors(tag=('w', 'x', 'y', 'z')))) 2313 self.assertEqual( 2314 [], 2315 list(d.iterancestors('w', 'x', 'y', 'z'))) 2316 2317 self.assertEqual( 2318 [], 2319 list(d.iterancestors(tag=('d', 'x')))) 2320 self.assertEqual( 2321 [], 2322 list(d.iterancestors('d', 'x'))) 2323 2324 self.assertEqual( 2325 [b, a], 2326 list(d.iterancestors(tag=('b', '*')))) 2327 self.assertEqual( 2328 [b, a], 2329 list(d.iterancestors('b', '*'))) 2330 2331 self.assertEqual( 2332 [b], 2333 list(d.iterancestors(tag=('b', 'c')))) 2334 self.assertEqual( 2335 [b], 2336 list(d.iterancestors('b', 'c')))
2337
2338 - def test_iterdescendants(self):
2339 Element = self.etree.Element 2340 SubElement = self.etree.SubElement 2341 2342 a = Element('a') 2343 b = SubElement(a, 'b') 2344 c = SubElement(a, 'c') 2345 d = SubElement(b, 'd') 2346 e = SubElement(c, 'e') 2347 2348 self.assertEqual( 2349 [b, d, c, e], 2350 list(a.iterdescendants())) 2351 self.assertEqual( 2352 [], 2353 list(d.iterdescendants()))
2354
2355 - def test_iterdescendants_tag(self):
2356 Element = self.etree.Element 2357 SubElement = self.etree.SubElement 2358 2359 a = Element('a') 2360 b = SubElement(a, 'b') 2361 c = SubElement(a, 'c') 2362 d = SubElement(b, 'd') 2363 e = SubElement(c, 'e') 2364 2365 self.assertEqual( 2366 [], 2367 list(a.iterdescendants('a'))) 2368 self.assertEqual( 2369 [], 2370 list(a.iterdescendants(tag='a'))) 2371 2372 a2 = SubElement(e, 'a') 2373 self.assertEqual( 2374 [a2], 2375 list(a.iterdescendants('a'))) 2376 2377 self.assertEqual( 2378 [a2], 2379 list(c.iterdescendants('a'))) 2380 self.assertEqual( 2381 [a2], 2382 list(c.iterdescendants(tag='a')))
2383
2384 - def test_iterdescendants_tag_multiple(self):
2385 Element = self.etree.Element 2386 SubElement = self.etree.SubElement 2387 2388 a = Element('a') 2389 b = SubElement(a, 'b') 2390 c = SubElement(a, 'c') 2391 d = SubElement(b, 'd') 2392 e = SubElement(c, 'e') 2393 2394 self.assertEqual( 2395 [b, e], 2396 list(a.iterdescendants(tag=('a', 'b', 'e')))) 2397 self.assertEqual( 2398 [b, e], 2399 list(a.iterdescendants('a', 'b', 'e'))) 2400 2401 a2 = SubElement(e, 'a') 2402 self.assertEqual( 2403 [b, a2], 2404 list(a.iterdescendants(tag=('a', 'b')))) 2405 self.assertEqual( 2406 [b, a2], 2407 list(a.iterdescendants('a', 'b'))) 2408 2409 self.assertEqual( 2410 [], 2411 list(c.iterdescendants(tag=('x', 'y', 'z')))) 2412 self.assertEqual( 2413 [], 2414 list(c.iterdescendants('x', 'y', 'z'))) 2415 2416 self.assertEqual( 2417 [b, d, c, e, a2], 2418 list(a.iterdescendants(tag=('x', 'y', 'z', '*')))) 2419 self.assertEqual( 2420 [b, d, c, e, a2], 2421 list(a.iterdescendants('x', 'y', 'z', '*')))
2422
2423 - def test_getroottree(self):
2424 Element = self.etree.Element 2425 SubElement = self.etree.SubElement 2426 2427 a = Element('a') 2428 b = SubElement(a, 'b') 2429 c = SubElement(a, 'c') 2430 d = SubElement(b, 'd') 2431 self.assertEqual( 2432 a, 2433 a.getroottree().getroot()) 2434 self.assertEqual( 2435 a, 2436 b.getroottree().getroot()) 2437 self.assertEqual( 2438 a, 2439 d.getroottree().getroot())
2440
2441 - def test_getnext(self):
2442 Element = self.etree.Element 2443 SubElement = self.etree.SubElement 2444 2445 a = Element('a') 2446 b = SubElement(a, 'b') 2447 c = SubElement(a, 'c') 2448 self.assertEqual( 2449 None, 2450 a.getnext()) 2451 self.assertEqual( 2452 c, 2453 b.getnext()) 2454 self.assertEqual( 2455 None, 2456 c.getnext())
2457
2458 - def test_getprevious(self):
2459 Element = self.etree.Element 2460 SubElement = self.etree.SubElement 2461 2462 a = Element('a') 2463 b = SubElement(a, 'b') 2464 c = SubElement(a, 'c') 2465 d = SubElement(b, 'd') 2466 self.assertEqual( 2467 None, 2468 a.getprevious()) 2469 self.assertEqual( 2470 b, 2471 c.getprevious()) 2472 self.assertEqual( 2473 None, 2474 b.getprevious())
2475
2476 - def test_itersiblings(self):
2477 Element = self.etree.Element 2478 SubElement = self.etree.SubElement 2479 2480 a = Element('a') 2481 b = SubElement(a, 'b') 2482 c = SubElement(a, 'c') 2483 d = SubElement(b, 'd') 2484 self.assertEqual( 2485 [], 2486 list(a.itersiblings())) 2487 self.assertEqual( 2488 [c], 2489 list(b.itersiblings())) 2490 self.assertEqual( 2491 [], 2492 list(c.itersiblings())) 2493 self.assertEqual( 2494 [b], 2495 list(c.itersiblings(preceding=True))) 2496 self.assertEqual( 2497 [], 2498 list(b.itersiblings(preceding=True)))
2499
2500 - def test_itersiblings_tag(self):
2501 Element = self.etree.Element 2502 SubElement = self.etree.SubElement 2503 2504 a = Element('a') 2505 b = SubElement(a, 'b') 2506 c = SubElement(a, 'c') 2507 d = SubElement(b, 'd') 2508 self.assertEqual( 2509 [], 2510 list(a.itersiblings(tag='XXX'))) 2511 self.assertEqual( 2512 [c], 2513 list(b.itersiblings(tag='c'))) 2514 self.assertEqual( 2515 [c], 2516 list(b.itersiblings(tag='*'))) 2517 self.assertEqual( 2518 [b], 2519 list(c.itersiblings(preceding=True, tag='b'))) 2520 self.assertEqual( 2521 [], 2522 list(c.itersiblings(preceding=True, tag='c')))
2523
2524 - def test_itersiblings_tag_multiple(self):
2525 Element = self.etree.Element 2526 SubElement = self.etree.SubElement 2527 2528 a = Element('a') 2529 b = SubElement(a, 'b') 2530 c = SubElement(a, 'c') 2531 d = SubElement(b, 'd') 2532 e = SubElement(a, 'e') 2533 self.assertEqual( 2534 [], 2535 list(a.itersiblings(tag=('XXX', 'YYY')))) 2536 self.assertEqual( 2537 [c, e], 2538 list(b.itersiblings(tag=('c', 'd', 'e')))) 2539 self.assertEqual( 2540 [b], 2541 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd')))) 2542 self.assertEqual( 2543 [c, b], 2544 list(e.itersiblings(preceding=True, tag=('c', '*'))))
2545
2546 - def test_parseid(self):
2547 parseid = self.etree.parseid 2548 XML = self.etree.XML 2549 xml_text = _bytes(''' 2550 <!DOCTYPE document [ 2551 <!ELEMENT document (h1,p)*> 2552 <!ELEMENT h1 (#PCDATA)> 2553 <!ATTLIST h1 myid ID #REQUIRED> 2554 <!ELEMENT p (#PCDATA)> 2555 <!ATTLIST p someid ID #REQUIRED> 2556 ]> 2557 <document> 2558 <h1 myid="chapter1">...</h1> 2559 <p id="note1" class="note">...</p> 2560 <p>Regular paragraph.</p> 2561 <p xml:id="xmlid">XML:ID paragraph.</p> 2562 <p someid="warn1" class="warning">...</p> 2563 </document> 2564 ''') 2565 2566 tree, dic = parseid(BytesIO(xml_text)) 2567 root = tree.getroot() 2568 root2 = XML(xml_text) 2569 self.assertEqual(self._writeElement(root), 2570 self._writeElement(root2)) 2571 expected = { 2572 "chapter1" : root[0], 2573 "xmlid" : root[3], 2574 "warn1" : root[4] 2575 } 2576 self.assertTrue("chapter1" in dic) 2577 self.assertTrue("warn1" in dic) 2578 self.assertTrue("xmlid" in dic) 2579 self._checkIDDict(dic, expected)
2580
2581 - def test_XMLDTDID(self):
2582 XMLDTDID = self.etree.XMLDTDID 2583 XML = self.etree.XML 2584 xml_text = _bytes(''' 2585 <!DOCTYPE document [ 2586 <!ELEMENT document (h1,p)*> 2587 <!ELEMENT h1 (#PCDATA)> 2588 <!ATTLIST h1 myid ID #REQUIRED> 2589 <!ELEMENT p (#PCDATA)> 2590 <!ATTLIST p someid ID #REQUIRED> 2591 ]> 2592 <document> 2593 <h1 myid="chapter1">...</h1> 2594 <p id="note1" class="note">...</p> 2595 <p>Regular paragraph.</p> 2596 <p xml:id="xmlid">XML:ID paragraph.</p> 2597 <p someid="warn1" class="warning">...</p> 2598 </document> 2599 ''') 2600 2601 root, dic = XMLDTDID(xml_text) 2602 root2 = XML(xml_text) 2603 self.assertEqual(self._writeElement(root), 2604 self._writeElement(root2)) 2605 expected = { 2606 "chapter1" : root[0], 2607 "xmlid" : root[3], 2608 "warn1" : root[4] 2609 } 2610 self.assertTrue("chapter1" in dic) 2611 self.assertTrue("warn1" in dic) 2612 self.assertTrue("xmlid" in dic) 2613 self._checkIDDict(dic, expected)
2614
2615 - def test_XMLDTDID_empty(self):
2616 XMLDTDID = self.etree.XMLDTDID 2617 XML = self.etree.XML 2618 xml_text = _bytes(''' 2619 <document> 2620 <h1 myid="chapter1">...</h1> 2621 <p id="note1" class="note">...</p> 2622 <p>Regular paragraph.</p> 2623 <p someid="warn1" class="warning">...</p> 2624 </document> 2625 ''') 2626 2627 root, dic = XMLDTDID(xml_text) 2628 root2 = XML(xml_text) 2629 self.assertEqual(self._writeElement(root), 2630 self._writeElement(root2)) 2631 expected = {} 2632 self._checkIDDict(dic, expected)
2633
2634 - def test_XMLDTDID_no_id_dict(self):
2635 XMLDTDID = self.etree.XMLDTDID 2636 XML = self.etree.XML 2637 xml_text = _bytes(''' 2638 <!DOCTYPE document [ 2639 <!ELEMENT document (h1,p)*> 2640 <!ELEMENT h1 (#PCDATA)> 2641 <!ATTLIST h1 myid ID #REQUIRED> 2642 <!ELEMENT p (#PCDATA)> 2643 <!ATTLIST p someid ID #REQUIRED> 2644 ]> 2645 <document> 2646 <h1 myid="chapter1">...</h1> 2647 <p id="note1" class="note">...</p> 2648 <p>Regular paragraph.</p> 2649 <p xml:id="xmlid">XML:ID paragraph.</p> 2650 <p someid="warn1" class="warning">...</p> 2651 </document> 2652 ''') 2653 2654 parser = etree.XMLParser(collect_ids=False) 2655 root, dic = XMLDTDID(xml_text, parser=parser) 2656 root2 = XML(xml_text) 2657 self.assertEqual(self._writeElement(root), 2658 self._writeElement(root2)) 2659 self.assertFalse(dic) 2660 self._checkIDDict(dic, {})
2661
2662 - def _checkIDDict(self, dic, expected):
2663 self.assertEqual(len(dic), 2664 len(expected)) 2665 self.assertEqual(sorted(dic.items()), 2666 sorted(expected.items())) 2667 if sys.version_info < (3,): 2668 self.assertEqual(sorted(dic.iteritems()), 2669 sorted(expected.iteritems())) 2670 self.assertEqual(sorted(dic.keys()), 2671 sorted(expected.keys())) 2672 if sys.version_info < (3,): 2673 self.assertEqual(sorted(dic.iterkeys()), 2674 sorted(expected.iterkeys())) 2675 if sys.version_info < (3,): 2676 self.assertEqual(sorted(dic.values()), 2677 sorted(expected.values())) 2678 self.assertEqual(sorted(dic.itervalues()), 2679 sorted(expected.itervalues()))
2680
2681 - def test_register_namespace_xml(self):
2682 self.assertRaises(ValueError, self.etree.register_namespace, 2683 "XML", "http://www.w3.org/XML/1998/namespace") 2684 self.assertRaises(ValueError, self.etree.register_namespace, 2685 "xml", "http://www.w3.org/XML/2345") 2686 self.etree.register_namespace("xml", "http://www.w3.org/XML/1998/namespace") # ok
2687
2688 - def test_namespaces(self):
2689 etree = self.etree 2690 2691 r = {'foo': 'http://ns.infrae.com/foo'} 2692 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2693 self.assertEqual( 2694 'foo', 2695 e.prefix) 2696 self.assertEqual( 2697 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'), 2698 self._writeElement(e))
2699
2700 - def test_namespaces_default(self):
2701 etree = self.etree 2702 2703 r = {None: 'http://ns.infrae.com/foo'} 2704 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2705 self.assertEqual( 2706 None, 2707 e.prefix) 2708 self.assertEqual( 2709 '{http://ns.infrae.com/foo}bar', 2710 e.tag) 2711 self.assertEqual( 2712 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'), 2713 self._writeElement(e))
2714
2715 - def test_namespaces_default_and_other(self):
2716 etree = self.etree 2717 2718 r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'} 2719 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2720 self.assertEqual(None, e.prefix) 2721 self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag) 2722 self.assertEqual( 2723 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'), 2724 self._writeElement(e))
2725
2726 - def test_namespaces_default_and_attr(self):
2727 etree = self.etree 2728 2729 r = {None: 'http://ns.infrae.com/foo', 2730 'hoi': 'http://ns.infrae.com/hoi'} 2731 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2732 e.set('{http://ns.infrae.com/hoi}test', 'value') 2733 self.assertEqual( 2734 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'), 2735 self._writeElement(e))
2736
2737 - def test_attribute_keeps_namespace_prefix_on_merge(self):
2738 etree = self.etree 2739 2740 root = etree.Element('{http://test/ns}root', 2741 nsmap={None: 'http://test/ns'}) 2742 sub = etree.Element('{http://test/ns}sub', 2743 nsmap={'test': 'http://test/ns'}) 2744 2745 sub.attrib['{http://test/ns}attr'] = 'value' 2746 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2747 self.assertEqual( 2748 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'), 2749 etree.tostring(sub)) 2750 2751 root.append(sub) 2752 self.assertEqual( 2753 _bytes('<root xmlns="http://test/ns">' 2754 '<sub xmlns:test="http://test/ns" test:attr="value"/>' 2755 '</root>'), 2756 etree.tostring(root))
2757
2758 - def test_attribute_keeps_namespace_prefix_on_merge_with_nons(self):
2759 etree = self.etree 2760 2761 root = etree.Element('root') 2762 sub = etree.Element('{http://test/ns}sub', 2763 nsmap={'test': 'http://test/ns'}) 2764 2765 sub.attrib['{http://test/ns}attr'] = 'value' 2766 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2767 self.assertEqual( 2768 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'), 2769 etree.tostring(sub)) 2770 2771 root.append(sub) 2772 self.assertEqual( 2773 _bytes('<root>' 2774 '<test:sub xmlns:test="http://test/ns" test:attr="value"/>' 2775 '</root>'), 2776 etree.tostring(root))
2777
2778 - def test_attribute_gets_namespace_prefix_on_merge_with_nons(self):
2779 etree = self.etree 2780 2781 root = etree.Element('root') 2782 sub = etree.Element('{http://test/ns}sub', 2783 nsmap={None: 'http://test/ns'}) 2784 2785 sub.attrib['{http://test/ns}attr'] = 'value' 2786 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2787 self.assertEqual( 2788 _bytes('<sub xmlns="http://test/ns" ' 2789 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'), 2790 etree.tostring(sub)) 2791 2792 root.append(sub) 2793 self.assertEqual( 2794 _bytes('<root>' 2795 '<sub xmlns="http://test/ns"' 2796 ' xmlns:ns0="http://test/ns" ns0:attr="value"/>' 2797 '</root>'), 2798 etree.tostring(root))
2799
2800 - def test_attribute_gets_namespace_prefix_on_merge(self):
2801 etree = self.etree 2802 2803 root = etree.Element('{http://test/ns}root', 2804 nsmap={'test': 'http://test/ns', 2805 None: 'http://test/ns'}) 2806 sub = etree.Element('{http://test/ns}sub', 2807 nsmap={None: 'http://test/ns'}) 2808 2809 sub.attrib['{http://test/ns}attr'] = 'value' 2810 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value') 2811 self.assertEqual( 2812 _bytes('<sub xmlns="http://test/ns" ' 2813 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'), 2814 etree.tostring(sub)) 2815 2816 root.append(sub) 2817 self.assertEqual( 2818 _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">' 2819 '<test:sub test:attr="value"/>' 2820 '</test:root>'), 2821 etree.tostring(root))
2822
2823 - def test_namespaces_elementtree(self):
2824 etree = self.etree 2825 r = {None: 'http://ns.infrae.com/foo', 2826 'hoi': 'http://ns.infrae.com/hoi'} 2827 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r) 2828 tree = etree.ElementTree(element=e) 2829 etree.SubElement(e, '{http://ns.infrae.com/hoi}x') 2830 self.assertEqual( 2831 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'), 2832 self._writeElement(e))
2833
2834 - def test_namespaces_default_copy_element(self):
2835 etree = self.etree 2836 2837 r = {None: 'http://ns.infrae.com/foo'} 2838 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2839 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2840 2841 e1.append(e2) 2842 2843 self.assertEqual( 2844 None, 2845 e1.prefix) 2846 self.assertEqual( 2847 None, 2848 e1[0].prefix) 2849 self.assertEqual( 2850 '{http://ns.infrae.com/foo}bar', 2851 e1.tag) 2852 self.assertEqual( 2853 '{http://ns.infrae.com/foo}bar', 2854 e1[0].tag)
2855
2856 - def test_namespaces_copy_element(self):
2857 etree = self.etree 2858 2859 r = {None: 'http://ns.infrae.com/BAR'} 2860 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r) 2861 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 2862 2863 e1.append(e2) 2864 2865 self.assertEqual( 2866 None, 2867 e1.prefix) 2868 self.assertNotEqual( 2869 None, 2870 e2.prefix) 2871 self.assertEqual( 2872 '{http://ns.infrae.com/BAR}bar', 2873 e1.tag) 2874 self.assertEqual( 2875 '{http://ns.infrae.com/foo}bar', 2876 e2.tag)
2877
2878 - def test_namespaces_reuse_after_move(self):
2879 ns_href = "http://a.b.c" 2880 one = self.etree.fromstring( 2881 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href)) 2882 baz = one[0][0] 2883 2884 two = self.etree.fromstring( 2885 _bytes('<root xmlns:ns="%s"/>' % ns_href)) 2886 two.append(baz) 2887 del one # make sure the source document is deallocated 2888 2889 self.assertEqual('{%s}baz' % ns_href, baz.tag) 2890 self.assertEqual( 2891 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href), 2892 self.etree.tostring(two))
2893
2894 - def test_namespace_cleanup(self):
2895 xml = _bytes( 2896 '<foo xmlns="F" xmlns:x="x">' 2897 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">' 2898 '<ns:baz/>' 2899 '</bar></foo>' 2900 ) 2901 root = self.etree.fromstring(xml) 2902 self.assertEqual(xml, self.etree.tostring(root)) 2903 self.etree.cleanup_namespaces(root) 2904 self.assertEqual( 2905 _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'), 2906 self.etree.tostring(root))
2907
2908 - def test_namespace_cleanup_attributes(self):
2909 xml = _bytes( 2910 '<foo xmlns="F" xmlns:x="X" xmlns:a="A">' 2911 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">' 2912 '<ns:baz a:test="attr"/>' 2913 '</bar></foo>' 2914 ) 2915 root = self.etree.fromstring(xml) 2916 self.assertEqual(xml, self.etree.tostring(root)) 2917 self.etree.cleanup_namespaces(root) 2918 self.assertEqual( 2919 _bytes('<foo xmlns="F" xmlns:a="A">' 2920 '<bar xmlns:ns="NS" xmlns="B">' 2921 '<ns:baz a:test="attr"/>' 2922 '</bar></foo>'), 2923 self.etree.tostring(root))
2924
2925 - def test_namespace_cleanup_many(self):
2926 xml = ('<n12:foo ' + 2927 ' '.join('xmlns:n{n}="NS{n}"'.format(n=i) for i in range(100)) + 2928 '><n68:a/></n12:foo>').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'<n12:foo xmlns:n12="NS12" xmlns:n68="NS68"><n68:a/></n12:foo>', 2934 self.etree.tostring(root))
2935
2936 - def test_namespace_cleanup_deep(self):
2937 xml = ('<root>' + 2938 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) + 2939 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8') 2940 root = self.etree.fromstring(xml) 2941 self.assertEqual(xml, self.etree.tostring(root)) 2942 self.etree.cleanup_namespaces(root) 2943 self.assertEqual( 2944 b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 + 2945 b'<n64:x/>' + b'</a>'*100 + b'</root>', 2946 self.etree.tostring(root))
2947
2948 - def test_namespace_cleanup_deep_to_top(self):
2949 xml = ('<root>' + 2950 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) + 2951 '<n64:x xmlns:a="A" a:attr="X"/>' + 2952 '</a>'*100 + 2953 '</root>').encode('utf8') 2954 root = self.etree.fromstring(xml) 2955 self.assertEqual(xml, self.etree.tostring(root)) 2956 self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'}) 2957 self.assertEqual( 2958 b'<root xmlns:n64="NS64">' + b'<a>'*100 + 2959 b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>', 2960 self.etree.tostring(root))
2961
2962 - def test_namespace_cleanup_keep_prefixes(self):
2963 xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">' 2964 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>' 2965 '<foo>foo:bar</foo>' 2966 '</root>').encode('utf8') 2967 root = self.etree.fromstring(xml) 2968 self.assertEqual(xml, self.etree.tostring(root)) 2969 self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo']) 2970 self.assertEqual( 2971 b'<root xmlns:n64="NS64" xmlns:foo="FOO">' 2972 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>' 2973 b'<foo>foo:bar</foo>' 2974 b'</root>', 2975 self.etree.tostring(root))
2976
2977 - def test_namespace_cleanup_keep_prefixes_top(self):
2978 xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">' 2979 '<sub xmlns:foo="FOO">' 2980 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>' 2981 '<foo>foo:bar</foo>' 2982 '</sub>' 2983 '</root>').encode('utf8') 2984 root = self.etree.fromstring(xml) 2985 self.assertEqual(xml, self.etree.tostring(root)) 2986 self.etree.cleanup_namespaces( 2987 root, 2988 top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'}, 2989 keep_ns_prefixes=['foo']) 2990 self.assertEqual( 2991 b'<root xmlns:n64="NS64" xmlns:foo="FOO">' 2992 b'<sub>' 2993 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>' 2994 b'<foo>foo:bar</foo>' 2995 b'</sub>' 2996 b'</root>', 2997 self.etree.tostring(root))
2998
2999 - def test_element_nsmap(self):
3000 etree = self.etree 3001 3002 r = {None: 'http://ns.infrae.com/foo', 3003 'hoi': 'http://ns.infrae.com/hoi'} 3004 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r) 3005 self.assertEqual( 3006 r, 3007 e.nsmap)
3008
3009 - def test_subelement_nsmap(self):
3010 etree = self.etree 3011 3012 re = {None: 'http://ns.infrae.com/foo', 3013 'hoi': 'http://ns.infrae.com/hoi'} 3014 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re) 3015 3016 rs = {None: 'http://ns.infrae.com/honk', 3017 'top': 'http://ns.infrae.com/top'} 3018 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs) 3019 3020 r = re.copy() 3021 r.update(rs) 3022 self.assertEqual(re, e.nsmap) 3023 self.assertEqual(r, s.nsmap)
3024
3025 - def test_html_prefix_nsmap(self):
3026 etree = self.etree 3027 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description') 3028 self.assertEqual({'hha': None}, el.nsmap)
3029
3030 - def test_getiterator_filter_multiple(self):
3031 Element = self.etree.Element 3032 SubElement = self.etree.SubElement 3033 3034 a = Element('a') 3035 b = SubElement(a, 'b') 3036 c = SubElement(a, 'c') 3037 d = SubElement(b, 'd') 3038 e = SubElement(c, 'e') 3039 f = SubElement(c, 'f') 3040 3041 self.assertEqual( 3042 [a, b], 3043 list(a.getiterator('a', 'b'))) 3044 self.assertEqual( 3045 [], 3046 list(a.getiterator('x', 'y'))) 3047 self.assertEqual( 3048 [a, f], 3049 list(a.getiterator('f', 'a'))) 3050 self.assertEqual( 3051 [c, e, f], 3052 list(c.getiterator('c', '*', 'a'))) 3053 self.assertEqual( 3054 [], 3055 list(a.getiterator( (), () )))
3056
3057 - def test_getiterator_filter_multiple_tuple(self):
3058 Element = self.etree.Element 3059 SubElement = self.etree.SubElement 3060 3061 a = Element('a') 3062 b = SubElement(a, 'b') 3063 c = SubElement(a, 'c') 3064 d = SubElement(b, 'd') 3065 e = SubElement(c, 'e') 3066 f = SubElement(c, 'f') 3067 3068 self.assertEqual( 3069 [a, b], 3070 list(a.getiterator( ('a', 'b') ))) 3071 self.assertEqual( 3072 [], 3073 list(a.getiterator( ('x', 'y') ))) 3074 self.assertEqual( 3075 [a, f], 3076 list(a.getiterator( ('f', 'a') ))) 3077 self.assertEqual( 3078 [c, e, f], 3079 list(c.getiterator( ('c', '*', 'a') ))) 3080 self.assertEqual( 3081 [], 3082 list(a.getiterator( () )))
3083
3084 - def test_getiterator_filter_namespace(self):
3085 Element = self.etree.Element 3086 SubElement = self.etree.SubElement 3087 3088 a = Element('{a}a') 3089 b = SubElement(a, '{a}b') 3090 c = SubElement(a, '{a}c') 3091 d = SubElement(b, '{b}d') 3092 e = SubElement(c, '{a}e') 3093 f = SubElement(c, '{b}f') 3094 g = SubElement(c, 'g') 3095 3096 self.assertEqual( 3097 [a], 3098 list(a.getiterator('{a}a'))) 3099 self.assertEqual( 3100 [], 3101 list(a.getiterator('{b}a'))) 3102 self.assertEqual( 3103 [], 3104 list(a.getiterator('a'))) 3105 self.assertEqual( 3106 [a,b,d,c,e,f,g], 3107 list(a.getiterator('*'))) 3108 self.assertEqual( 3109 [f], 3110 list(c.getiterator('{b}*'))) 3111 self.assertEqual( 3112 [d, f], 3113 list(a.getiterator('{b}*'))) 3114 self.assertEqual( 3115 [g], 3116 list(a.getiterator('g'))) 3117 self.assertEqual( 3118 [g], 3119 list(a.getiterator('{}g'))) 3120 self.assertEqual( 3121 [g], 3122 list(a.getiterator('{}*')))
3123
3124 - def test_getiterator_filter_local_name(self):
3125 Element = self.etree.Element 3126 Comment = self.etree.Comment 3127 SubElement = self.etree.SubElement 3128 3129 a = Element('{a}a') 3130 b = SubElement(a, '{nsA}b') 3131 c = SubElement(b, '{nsB}b') 3132 d = SubElement(a, 'b') 3133 e = SubElement(a, '{nsA}e') 3134 f = SubElement(e, '{nsB}e') 3135 g = SubElement(e, 'e') 3136 a.append(Comment('test')) 3137 3138 self.assertEqual( 3139 [b, c, d], 3140 list(a.getiterator('{*}b'))) 3141 self.assertEqual( 3142 [e, f, g], 3143 list(a.getiterator('{*}e'))) 3144 self.assertEqual( 3145 [a, b, c, d, e, f, g], 3146 list(a.getiterator('{*}*')))
3147
3148 - def test_getiterator_filter_entities(self):
3149 Element = self.etree.Element 3150 Entity = self.etree.Entity 3151 SubElement = self.etree.SubElement 3152 3153 a = Element('a') 3154 b = SubElement(a, 'b') 3155 entity_b = Entity("TEST-b") 3156 b.append(entity_b) 3157 3158 self.assertEqual( 3159 [entity_b], 3160 list(a.getiterator(Entity))) 3161 3162 entity_a = Entity("TEST-a") 3163 a.append(entity_a) 3164 3165 self.assertEqual( 3166 [entity_b, entity_a], 3167 list(a.getiterator(Entity))) 3168 3169 self.assertEqual( 3170 [entity_b], 3171 list(b.getiterator(Entity)))
3172
3173 - def test_getiterator_filter_element(self):
3174 Element = self.etree.Element 3175 Comment = self.etree.Comment 3176 PI = self.etree.PI 3177 SubElement = self.etree.SubElement 3178 3179 a = Element('a') 3180 b = SubElement(a, 'b') 3181 a.append(Comment("test")) 3182 a.append(PI("pi", "content")) 3183 c = SubElement(a, 'c') 3184 3185 self.assertEqual( 3186 [a, b, c], 3187 list(a.getiterator(Element)))
3188
3189 - def test_getiterator_filter_all_comment_pi(self):
3190 # ElementTree iterates over everything here 3191 Element = self.etree.Element 3192 Comment = self.etree.Comment 3193 PI = self.etree.PI 3194 SubElement = self.etree.SubElement 3195 3196 a = Element('a') 3197 b = SubElement(a, 'b') 3198 a.append(Comment("test")) 3199 a.append(PI("pi", "content")) 3200 c = SubElement(a, 'c') 3201 3202 self.assertEqual( 3203 [a, b, c], 3204 list(a.getiterator('*')))
3205
3206 - def test_elementtree_getelementpath(self):
3207 a = etree.Element("a") 3208 b = etree.SubElement(a, "b") 3209 c = etree.SubElement(a, "c") 3210 d1 = etree.SubElement(c, "d") 3211 d2 = etree.SubElement(c, "d") 3212 c.text = d1.text = 'TEXT' 3213 3214 tree = etree.ElementTree(a) 3215 self.assertEqual('.', tree.getelementpath(a)) 3216 self.assertEqual('c/d[1]', tree.getelementpath(d1)) 3217 self.assertEqual('c/d[2]', tree.getelementpath(d2)) 3218 3219 self.assertEqual(d1, tree.find(tree.getelementpath(d1))) 3220 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3221 3222 tree = etree.ElementTree(c) 3223 self.assertEqual('.', tree.getelementpath(c)) 3224 self.assertEqual('d[2]', tree.getelementpath(d2)) 3225 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3226 3227 tree = etree.ElementTree(b) # not a parent of a/c/d1/d2 3228 self.assertEqual('.', tree.getelementpath(b)) 3229 self.assertRaises(ValueError, tree.getelementpath, a) 3230 self.assertRaises(ValueError, tree.getelementpath, c) 3231 self.assertRaises(ValueError, tree.getelementpath, d2)
3232
3233 - def test_elementtree_getelementpath_ns(self):
3234 a = etree.Element("{http://ns1/}a") 3235 b = etree.SubElement(a, "{http://ns1/}b") 3236 c = etree.SubElement(a, "{http://ns1/}c") 3237 d1 = etree.SubElement(c, "{http://ns1/}d") 3238 d2 = etree.SubElement(c, "{http://ns2/}d") 3239 d3 = etree.SubElement(c, "{http://ns1/}d") 3240 3241 tree = etree.ElementTree(a) 3242 self.assertEqual('.', tree.getelementpath(a)) 3243 self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]', 3244 tree.getelementpath(d1)) 3245 self.assertEqual('{http://ns1/}c/{http://ns2/}d', 3246 tree.getelementpath(d2)) 3247 self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]', 3248 tree.getelementpath(d3)) 3249 3250 self.assertEqual(a, tree.find(tree.getelementpath(a))) 3251 self.assertEqual(b, tree.find(tree.getelementpath(b))) 3252 self.assertEqual(c, tree.find(tree.getelementpath(c))) 3253 self.assertEqual(d1, tree.find(tree.getelementpath(d1))) 3254 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3255 self.assertEqual(d3, tree.find(tree.getelementpath(d3))) 3256 3257 tree = etree.ElementTree(c) 3258 self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1)) 3259 self.assertEqual('{http://ns2/}d', tree.getelementpath(d2)) 3260 self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3)) 3261 self.assertEqual(d1, tree.find(tree.getelementpath(d1))) 3262 self.assertEqual(d2, tree.find(tree.getelementpath(d2))) 3263 self.assertEqual(d3, tree.find(tree.getelementpath(d3))) 3264 3265 tree = etree.ElementTree(b) # not a parent of d1/d2 3266 self.assertRaises(ValueError, tree.getelementpath, d1) 3267 self.assertRaises(ValueError, tree.getelementpath, d2)
3268
3269 - def test_elementtree_iter_qname(self):
3270 XML = self.etree.XML 3271 ElementTree = self.etree.ElementTree 3272 QName = self.etree.QName 3273 tree = ElementTree(XML( 3274 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))) 3275 self.assertEqual( 3276 list(tree.iter(QName("b"))), 3277 list(tree.iter("b")), 3278 ) 3279 self.assertEqual( 3280 list(tree.iter(QName("X", "b"))), 3281 list(tree.iter("{X}b")), 3282 ) 3283 3284 self.assertEqual( 3285 [e.tag for e in tree.iter(QName("X", "b"), QName("b"))], 3286 ['{X}b', 'b', '{X}b', 'b', 'b'] 3287 ) 3288 self.assertEqual( 3289 list(tree.iter(QName("X", "b"), QName("b"))), 3290 list(tree.iter("{X}b", "b")) 3291 )
3292
3293 - def test_elementtree_find_qname(self):
3294 XML = self.etree.XML 3295 ElementTree = self.etree.ElementTree 3296 QName = self.etree.QName 3297 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))) 3298 self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
3299
3300 - def test_elementtree_findall_qname(self):
3301 XML = self.etree.XML 3302 ElementTree = self.etree.ElementTree 3303 QName = self.etree.QName 3304 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))) 3305 self.assertEqual(len(list(tree.findall(QName("c")))), 1)
3306
3307 - def test_elementtree_findall_ns_qname(self):
3308 XML = self.etree.XML 3309 ElementTree = self.etree.ElementTree 3310 QName = self.etree.QName 3311 tree = ElementTree(XML( 3312 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))) 3313 self.assertEqual(len(list(tree.findall(QName("b")))), 2) 3314 self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
3315
3316 - def test_findall_ns(self):
3317 XML = self.etree.XML 3318 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')) 3319 self.assertEqual(len(root.findall(".//{X}b")), 2) 3320 self.assertEqual(len(root.findall(".//{X}*")), 2) 3321 self.assertEqual(len(root.findall(".//b")), 3)
3322
3323 - def test_findall_different_nsmaps(self):
3324 XML = self.etree.XML 3325 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>')) 3326 nsmap = {'xx': 'X'} 3327 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) 3328 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2) 3329 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2) 3330 nsmap = {'xx': 'Y'} 3331 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1) 3332 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1) 3333 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3334
3335 - def test_findall_empty_prefix(self):
3336 XML = self.etree.XML 3337 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>')) 3338 nsmap = {'xx': 'X'} 3339 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) 3340 nsmap = {'xx': 'X', None: 'Y'} 3341 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1) 3342 nsmap = {'xx': 'X', '': 'Y'} 3343 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1)
3344
3345 - def test_findall_syntax_error(self):
3346 XML = self.etree.XML 3347 root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>')) 3348 self.assertRaises(SyntaxError, root.findall, '') 3349 self.assertRaises(SyntaxError, root.findall, '//') # absolute path on Element 3350 self.assertRaises(SyntaxError, root.findall, './//')
3351
3352 - def test_index(self):
3353 etree = self.etree 3354 e = etree.Element('foo') 3355 for i in range(10): 3356 etree.SubElement(e, 'a%s' % i) 3357 for i in range(10): 3358 self.assertEqual( 3359 i, 3360 e.index(e[i])) 3361 self.assertEqual( 3362 3, e.index(e[3], 3)) 3363 self.assertRaises( 3364 ValueError, e.index, e[3], 4) 3365 self.assertRaises( 3366 ValueError, e.index, e[3], 0, 2) 3367 self.assertRaises( 3368 ValueError, e.index, e[8], 0, -3) 3369 self.assertRaises( 3370 ValueError, e.index, e[8], -5, -3) 3371 self.assertEqual( 3372 8, e.index(e[8], 0, -1)) 3373 self.assertEqual( 3374 8, e.index(e[8], -12, -1)) 3375 self.assertEqual( 3376 0, e.index(e[0], -12, -1))
3377
3378 - def test_replace(self):
3379 etree = self.etree 3380 e = etree.Element('foo') 3381 for i in range(10): 3382 el = etree.SubElement(e, 'a%s' % i) 3383 el.text = "text%d" % i 3384 el.tail = "tail%d" % i 3385 3386 child0 = e[0] 3387 child1 = e[1] 3388 child2 = e[2] 3389 3390 e.replace(e[0], e[1]) 3391 self.assertEqual( 3392 9, len(e)) 3393 self.assertEqual( 3394 child1, e[0]) 3395 self.assertEqual( 3396 child1.text, "text1") 3397 self.assertEqual( 3398 child1.tail, "tail1") 3399 self.assertEqual( 3400 child0.tail, "tail0") 3401 self.assertEqual( 3402 child2, e[1]) 3403 3404 e.replace(e[-1], e[0]) 3405 self.assertEqual( 3406 child1, e[-1]) 3407 self.assertEqual( 3408 child1.text, "text1") 3409 self.assertEqual( 3410 child1.tail, "tail1") 3411 self.assertEqual( 3412 child2, e[0])
3413
3414 - def test_replace_new(self):
3415 etree = self.etree 3416 e = etree.Element('foo') 3417 for i in range(10): 3418 etree.SubElement(e, 'a%s' % i) 3419 3420 new_element = etree.Element("test") 3421 new_element.text = "TESTTEXT" 3422 new_element.tail = "TESTTAIL" 3423 child1 = e[1] 3424 e.replace(e[0], new_element) 3425 self.assertEqual( 3426 new_element, e[0]) 3427 self.assertEqual( 3428 "TESTTEXT", 3429 e[0].text) 3430 self.assertEqual( 3431 "TESTTAIL", 3432 e[0].tail) 3433 self.assertEqual( 3434 child1, e[1])
3435
3436 - def test_setslice_all_reversed(self):
3437 Element = self.etree.Element 3438 SubElement = self.etree.SubElement 3439 3440 a = Element('a') 3441 3442 e = Element('e') 3443 f = Element('f') 3444 g = Element('g') 3445 3446 a[:] = [e, f, g] 3447 self.assertEqual( 3448 [e, f, g], 3449 list(a)) 3450 3451 a[::-1] = [e, f, g] 3452 self.assertEqual( 3453 [g, f, e], 3454 list(a))
3455
3456 - def test_setslice_step(self):
3457 Element = self.etree.Element 3458 SubElement = self.etree.SubElement 3459 3460 a = Element('a') 3461 b = SubElement(a, 'b') 3462 c = SubElement(a, 'c') 3463 d = SubElement(a, 'd') 3464 e = SubElement(a, 'e') 3465 3466 x = Element('x') 3467 y = Element('y') 3468 3469 a[1::2] = [x, y] 3470 self.assertEqual( 3471 [b, x, d, y], 3472 list(a))
3473
3474 - def test_setslice_step_negative(self):
3475 Element = self.etree.Element 3476 SubElement = self.etree.SubElement 3477 3478 a = Element('a') 3479 b = SubElement(a, 'b') 3480 c = SubElement(a, 'c') 3481 d = SubElement(a, 'd') 3482 e = SubElement(a, 'e') 3483 3484 x = Element('x') 3485 y = Element('y') 3486 3487 a[1::-1] = [x, y] 3488 self.assertEqual( 3489 [y, x, d, e], 3490 list(a))
3491
3492 - def test_setslice_step_negative2(self):
3493 Element = self.etree.Element 3494 SubElement = self.etree.SubElement 3495 3496 a = Element('a') 3497 b = SubElement(a, 'b') 3498 c = SubElement(a, 'c') 3499 d = SubElement(a, 'd') 3500 e = SubElement(a, 'e') 3501 3502 x = Element('x') 3503 y = Element('y') 3504 3505 a[::-2] = [x, y] 3506 self.assertEqual( 3507 [b, y, d, x], 3508 list(a))
3509
3510 - def test_setslice_step_overrun(self):
3511 Element = self.etree.Element 3512 SubElement = self.etree.SubElement 3513 try: 3514 slice 3515 except NameError: 3516 print("slice() not found") 3517 return 3518 3519 a = Element('a') 3520 b = SubElement(a, 'b') 3521 c = SubElement(a, 'c') 3522 d = SubElement(a, 'd') 3523 e = SubElement(a, 'e') 3524 3525 x = Element('x') 3526 y = Element('y') 3527 z = Element('z') 3528 3529 self.assertRaises( 3530 ValueError, 3531 operator.setitem, a, slice(1,None,2), [x, y, z]) 3532 3533 self.assertEqual( 3534 [b, c, d, e], 3535 list(a))
3536
3537 - def test_sourceline_XML(self):
3538 XML = self.etree.XML 3539 root = XML(_bytes('''<?xml version="1.0"?> 3540 <root><test> 3541 3542 <bla/></test> 3543 </root> 3544 ''')) 3545 3546 self.assertEqual( 3547 [2, 2, 4], 3548 [ el.sourceline for el in root.getiterator() ])
3549
3550 - def test_large_sourceline_XML(self):
3551 XML = self.etree.XML 3552 root = XML(_bytes( 3553 '<?xml version="1.0"?>\n' 3554 '<root>' + '\n' * 65536 + 3555 '<p>' + '\n' * 65536 + '</p>\n' + 3556 '<br/>\n' 3557 '</root>')) 3558 3559 if self.etree.LIBXML_VERSION >= (2, 9): 3560 expected = [2, 131074, 131076] 3561 else: 3562 expected = [2, 65535, 65535] 3563 3564 self.assertEqual(expected, [el.sourceline for el in root.iter()])
3565
3566 - def test_sourceline_parse(self):
3567 parse = self.etree.parse 3568 tree = parse(fileInTestDir('include/test_xinclude.xml')) 3569 3570 self.assertEqual( 3571 [1, 2, 3], 3572 [ el.sourceline for el in tree.getiterator() ])
3573
3574 - def test_sourceline_iterparse_end(self):
3575 iterparse = self.etree.iterparse 3576 lines = [ el.sourceline for (event, el) in 3577 iterparse(fileInTestDir('include/test_xinclude.xml')) ] 3578 3579 self.assertEqual( 3580 [2, 3, 1], 3581 lines)
3582
3583 - def test_sourceline_iterparse_start(self):
3584 iterparse = self.etree.iterparse 3585 lines = [ el.sourceline for (event, el) in 3586 iterparse(fileInTestDir('include/test_xinclude.xml'), 3587 events=("start",)) ] 3588 3589 self.assertEqual( 3590 [1, 2, 3], 3591 lines)
3592
3593 - def test_sourceline_element(self):
3594 Element = self.etree.Element 3595 SubElement = self.etree.SubElement 3596 el = Element("test") 3597 self.assertEqual(None, el.sourceline) 3598 3599 child = SubElement(el, "test") 3600 self.assertEqual(None, el.sourceline) 3601 self.assertEqual(None, child.sourceline)
3602
3603 - def test_XML_base_url_docinfo(self):
3604 etree = self.etree 3605 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3606 docinfo = root.getroottree().docinfo 3607 self.assertEqual(docinfo.URL, "http://no/such/url")
3608
3609 - def test_XML_set_base_url_docinfo(self):
3610 etree = self.etree 3611 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3612 docinfo = root.getroottree().docinfo 3613 self.assertEqual(docinfo.URL, "http://no/such/url") 3614 docinfo.URL = "https://secret/url" 3615 self.assertEqual(docinfo.URL, "https://secret/url")
3616
3617 - def test_parse_stringio_base_url(self):
3618 etree = self.etree 3619 tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url") 3620 docinfo = tree.docinfo 3621 self.assertEqual(docinfo.URL, "http://no/such/url")
3622
3623 - def test_parse_base_url_docinfo(self):
3624 etree = self.etree 3625 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'), 3626 base_url="http://no/such/url") 3627 docinfo = tree.docinfo 3628 self.assertEqual(docinfo.URL, "http://no/such/url")
3629
3630 - def test_HTML_base_url_docinfo(self):
3631 etree = self.etree 3632 root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url") 3633 docinfo = root.getroottree().docinfo 3634 self.assertEqual(docinfo.URL, "http://no/such/url")
3635
3636 - def test_docinfo_public(self):
3637 etree = self.etree 3638 xml_header = '<?xml version="1.0" encoding="ascii"?>' 3639 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN" 3640 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" 3641 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id) 3642 3643 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>') 3644 3645 tree = etree.parse(BytesIO(xml)) 3646 docinfo = tree.docinfo 3647 self.assertEqual(docinfo.encoding, "ascii") 3648 self.assertEqual(docinfo.xml_version, "1.0") 3649 self.assertEqual(docinfo.public_id, pub_id) 3650 self.assertEqual(docinfo.system_url, sys_id) 3651 self.assertEqual(docinfo.root_name, 'html') 3652 self.assertEqual(docinfo.doctype, doctype_string)
3653
3654 - def test_docinfo_system(self):
3655 etree = self.etree 3656 xml_header = '<?xml version="1.0" encoding="UTF-8"?>' 3657 sys_id = "some.dtd" 3658 doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id 3659 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>') 3660 3661 tree = etree.parse(BytesIO(xml)) 3662 docinfo = tree.docinfo 3663 self.assertEqual(docinfo.encoding, "UTF-8") 3664 self.assertEqual(docinfo.xml_version, "1.0") 3665 self.assertEqual(docinfo.public_id, None) 3666 self.assertEqual(docinfo.system_url, sys_id) 3667 self.assertEqual(docinfo.root_name, 'html') 3668 self.assertEqual(docinfo.doctype, doctype_string)
3669
3670 - def test_docinfo_empty(self):
3671 etree = self.etree 3672 xml = _bytes('<html><body></body></html>') 3673 tree = etree.parse(BytesIO(xml)) 3674 docinfo = tree.docinfo 3675 self.assertEqual(docinfo.encoding, "UTF-8") 3676 self.assertEqual(docinfo.xml_version, "1.0") 3677 self.assertEqual(docinfo.public_id, None) 3678 self.assertEqual(docinfo.system_url, None) 3679 self.assertEqual(docinfo.root_name, 'html') 3680 self.assertEqual(docinfo.doctype, '')
3681
3682 - def test_docinfo_name_only(self):
3683 etree = self.etree 3684 xml = _bytes('<!DOCTYPE root><root></root>') 3685 tree = etree.parse(BytesIO(xml)) 3686 docinfo = tree.docinfo 3687 self.assertEqual(docinfo.encoding, "UTF-8") 3688 self.assertEqual(docinfo.xml_version, "1.0") 3689 self.assertEqual(docinfo.public_id, None) 3690 self.assertEqual(docinfo.system_url, None) 3691 self.assertEqual(docinfo.root_name, 'root') 3692 self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
3693
3694 - def test_doctype_name_only_roundtrip(self):
3695 etree = self.etree 3696 xml = _bytes('<!DOCTYPE root>\n<root/>') 3697 tree = etree.parse(BytesIO(xml)) 3698 self.assertEqual(xml, etree.tostring(tree))
3699
3700 - def test_doctype_output_override(self):
3701 etree = self.etree 3702 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN" 3703 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" 3704 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)) 3705 3706 xml = _bytes('<!DOCTYPE root>\n<root/>') 3707 tree = etree.parse(BytesIO(xml)) 3708 self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string), 3709 etree.tostring(tree, doctype=doctype_string))
3710
3711 - def test_xml_base(self):
3712 etree = self.etree 3713 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3714 self.assertEqual(root.base, "http://no/such/url") 3715 self.assertEqual( 3716 root.get('{http://www.w3.org/XML/1998/namespace}base'), None) 3717 root.base = "https://secret/url" 3718 self.assertEqual(root.base, "https://secret/url") 3719 self.assertEqual( 3720 root.get('{http://www.w3.org/XML/1998/namespace}base'), 3721 "https://secret/url")
3722
3723 - def test_xml_base_attribute(self):
3724 etree = self.etree 3725 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url") 3726 self.assertEqual(root.base, "http://no/such/url") 3727 self.assertEqual( 3728 root.get('{http://www.w3.org/XML/1998/namespace}base'), None) 3729 root.set('{http://www.w3.org/XML/1998/namespace}base', 3730 "https://secret/url") 3731 self.assertEqual(root.base, "https://secret/url") 3732 self.assertEqual( 3733 root.get('{http://www.w3.org/XML/1998/namespace}base'), 3734 "https://secret/url")
3735
3736 - def test_html_base(self):
3737 etree = self.etree 3738 root = etree.HTML(_bytes("<html><body></body></html>"), 3739 base_url="http://no/such/url") 3740 self.assertEqual(root.base, "http://no/such/url")
3741
3742 - def test_html_base_tag(self):
3743 etree = self.etree 3744 root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>')) 3745 self.assertEqual(root.base, "http://no/such/url")
3746
3747 - def test_indent(self):
3748 ET = self.etree 3749 elem = ET.XML("<root></root>") 3750 ET.indent(elem) 3751 self.assertEqual(ET.tostring(elem), b'<root/>') 3752 3753 elem = ET.XML("<html><body>text</body></html>") 3754 ET.indent(elem) 3755 self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>\n</html>') 3756 3757 elem = ET.XML("<html> <body>text</body> </html>") 3758 ET.indent(elem) 3759 self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>\n</html>') 3760 3761 elem = ET.XML("<html> <body>text</body> </html>") 3762 ET.indent(elem) 3763 self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>\n</html>') 3764 3765 elem = ET.XML("<html><body>text</body>tail</html>") 3766 ET.indent(elem) 3767 self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>tail</html>') 3768 3769 elem = ET.XML("<html><body><p>par</p>\n<p>text</p>\t<p><br/></p></body></html>") 3770 ET.indent(elem) 3771 self.assertEqual( 3772 ET.tostring(elem), 3773 b'<html>\n' 3774 b' <body>\n' 3775 b' <p>par</p>\n' 3776 b' <p>text</p>\n' 3777 b' <p>\n' 3778 b' <br/>\n' 3779 b' </p>\n' 3780 b' </body>\n' 3781 b'</html>' 3782 ) 3783 3784 elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 3785 ET.indent(elem) 3786 self.assertEqual( 3787 ET.tostring(elem), 3788 b'<html>\n' 3789 b' <body>\n' 3790 b' <p>pre<br/>post</p>\n' 3791 b' <p>text</p>\n' 3792 b' </body>\n' 3793 b'</html>' 3794 )
3795
3796 - def test_indent_space(self):
3797 ET = self.etree 3798 elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 3799 ET.indent(elem, space='\t') 3800 self.assertEqual( 3801 ET.tostring(elem), 3802 b'<html>\n' 3803 b'\t<body>\n' 3804 b'\t\t<p>pre<br/>post</p>\n' 3805 b'\t\t<p>text</p>\n' 3806 b'\t</body>\n' 3807 b'</html>' 3808 ) 3809 3810 elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 3811 ET.indent(elem, space='') 3812 self.assertEqual( 3813 ET.tostring(elem), 3814 b'<html>\n' 3815 b'<body>\n' 3816 b'<p>pre<br/>post</p>\n' 3817 b'<p>text</p>\n' 3818 b'</body>\n' 3819 b'</html>' 3820 )
3821
3822 - def test_indent_space_caching(self):
3823 ET = self.etree 3824 elem = ET.XML("<html><body><p>par</p><p>text</p><p><br/></p><p /></body></html>") 3825 ET.indent(elem) 3826 self.assertEqual( 3827 {el.tail for el in elem.iter()}, 3828 {None, "\n", "\n ", "\n "} 3829 ) 3830 self.assertEqual( 3831 {el.text for el in elem.iter()}, 3832 {None, "\n ", "\n ", "\n ", "par", "text"} 3833 )
3834 # NOTE: lxml does not reuse Python text strings across elements. 3835 #self.assertEqual( 3836 # len({el.tail for el in elem.iter()}), 3837 # len({id(el.tail) for el in elem.iter()}), 3838 #) 3839
3840 - def test_indent_level(self):
3841 ET = self.etree 3842 elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 3843 try: 3844 ET.indent(elem, level=-1) 3845 except ValueError: 3846 pass 3847 else: 3848 self.assertTrue(False, "ValueError not raised") 3849 self.assertEqual( 3850 ET.tostring(elem), 3851 b"<html><body><p>pre<br/>post</p><p>text</p></body></html>" 3852 ) 3853 3854 ET.indent(elem, level=2) 3855 self.assertEqual( 3856 ET.tostring(elem), 3857 b'<html>\n' 3858 b' <body>\n' 3859 b' <p>pre<br/>post</p>\n' 3860 b' <p>text</p>\n' 3861 b' </body>\n' 3862 b' </html>' 3863 ) 3864 3865 elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 3866 ET.indent(elem, level=1, space=' ') 3867 self.assertEqual( 3868 ET.tostring(elem), 3869 b'<html>\n' 3870 b' <body>\n' 3871 b' <p>pre<br/>post</p>\n' 3872 b' <p>text</p>\n' 3873 b' </body>\n' 3874 b' </html>' 3875 )
3876
3877 - def test_parse_fileobject_unicode(self):
3878 # parse from a file object that returns unicode strings 3879 f = LargeFileLikeUnicode() 3880 tree = self.etree.parse(f) 3881 root = tree.getroot() 3882 self.assertTrue(root.tag.endswith('root'))
3883
3884 - def test_dtd_io(self):
3885 # check that DTDs that go in also go back out 3886 xml = _bytes('''\ 3887 <!DOCTYPE test SYSTEM "test.dtd" [ 3888 <!ENTITY entity "tasty"> 3889 <!ELEMENT test (a)> 3890 <!ELEMENT a (#PCDATA)> 3891 ]> 3892 <test><a>test-test</a></test>\ 3893 ''') 3894 tree = self.etree.parse(BytesIO(xml)) 3895 self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")), 3896 xml.replace(_bytes(" "), _bytes("")))
3897
3898 - def test_byte_zero(self):
3899 Element = self.etree.Element 3900 3901 a = Element('a') 3902 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho') 3903 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho') 3904 3905 self.assertRaises(ValueError, Element, 'ha\0ho')
3906
3907 - def test_unicode_byte_zero(self):
3908 Element = self.etree.Element 3909 3910 a = Element('a') 3911 self.assertRaises(ValueError, setattr, a, "text", 3912 _str('ha\0ho')) 3913 self.assertRaises(ValueError, setattr, a, "tail", 3914 _str('ha\0ho')) 3915 3916 self.assertRaises(ValueError, Element, 3917 _str('ha\0ho'))
3918
3919 - def test_byte_invalid(self):
3920 Element = self.etree.Element 3921 3922 a = Element('a') 3923 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho') 3924 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho') 3925 3926 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho') 3927 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho') 3928 3929 self.assertRaises(ValueError, Element, 'ha\x07ho') 3930 self.assertRaises(ValueError, Element, 'ha\x02ho')
3931
3932 - def test_unicode_byte_invalid(self):
3933 Element = self.etree.Element 3934 3935 a = Element('a') 3936 self.assertRaises(ValueError, setattr, a, "text", 3937 _str('ha\x07ho')) 3938 self.assertRaises(ValueError, setattr, a, "text", 3939 _str('ha\x02ho')) 3940 3941 self.assertRaises(ValueError, setattr, a, "tail", 3942 _str('ha\x07ho')) 3943 self.assertRaises(ValueError, setattr, a, "tail", 3944 _str('ha\x02ho')) 3945 3946 self.assertRaises(ValueError, Element, 3947 _str('ha\x07ho')) 3948 self.assertRaises(ValueError, Element, 3949 _str('ha\x02ho'))
3950
3951 - def test_unicode_byte_invalid_sequence(self):
3952 Element = self.etree.Element 3953 3954 a = Element('a') 3955 self.assertRaises(ValueError, setattr, a, "text", 3956 _str('ha\u1234\x07ho')) 3957 self.assertRaises(ValueError, setattr, a, "text", 3958 _str('ha\u1234\x02ho')) 3959 3960 self.assertRaises(ValueError, setattr, a, "tail", 3961 _str('ha\u1234\x07ho')) 3962 self.assertRaises(ValueError, setattr, a, "tail", 3963 _str('ha\u1234\x02ho')) 3964 3965 self.assertRaises(ValueError, Element, 3966 _str('ha\u1234\x07ho')) 3967 self.assertRaises(ValueError, Element, 3968 _str('ha\u1234\x02ho'))
3969
3970 - def test_encoding_tostring_utf16(self):
3971 # ElementTree fails to serialize this 3972 tostring = self.etree.tostring 3973 Element = self.etree.Element 3974 SubElement = self.etree.SubElement 3975 3976 a = Element('a') 3977 b = SubElement(a, 'b') 3978 c = SubElement(a, 'c') 3979 3980 result = tostring(a, encoding='UTF-16') 3981 self.assertEqual(_bytes('<a><b></b><c></c></a>'), 3982 canonicalize(result))
3983
3984 - def test_tostring_none(self):
3985 # ElementTree raises an AssertionError here 3986 tostring = self.etree.tostring 3987 self.assertRaises(TypeError, self.etree.tostring, None)
3988
3989 - def test_tostring_pretty(self):
3990 tostring = self.etree.tostring 3991 Element = self.etree.Element 3992 SubElement = self.etree.SubElement 3993 3994 a = Element('a') 3995 b = SubElement(a, 'b') 3996 c = SubElement(a, 'c') 3997 3998 result = tostring(a) 3999 self.assertEqual(result, _bytes("<a><b/><c/></a>")) 4000 4001 result = tostring(a, pretty_print=False) 4002 self.assertEqual(result, _bytes("<a><b/><c/></a>")) 4003 4004 result = tostring(a, pretty_print=True) 4005 self.assertEqual(result, _bytes("<a>\n <b/>\n <c/>\n</a>\n"))
4006
4007 - def test_tostring_with_tail(self):
4008 tostring = self.etree.tostring 4009 Element = self.etree.Element 4010 SubElement = self.etree.SubElement 4011 4012 a = Element('a') 4013 a.tail = "aTAIL" 4014 b = SubElement(a, 'b') 4015 b.tail = "bTAIL" 4016 c = SubElement(a, 'c') 4017 4018 result = tostring(a) 4019 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL")) 4020 4021 result = tostring(a, with_tail=False) 4022 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>")) 4023 4024 result = tostring(a, with_tail=True) 4025 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
4026
4027 - def test_tostring_method_html_with_tail(self):
4028 tostring = self.etree.tostring 4029 html = self.etree.fromstring( 4030 '<html><body>' 4031 '<div><p>Some text<i>\r\n</i></p></div>\r\n' 4032 '</body></html>', 4033 parser=self.etree.HTMLParser()) 4034 self.assertEqual(html.tag, 'html') 4035 div = html.find('.//div') 4036 self.assertEqual(div.tail, '\r\n') 4037 result = tostring(div, method='html') 4038 self.assertEqual( 4039 result, 4040 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n")) 4041 result = tostring(div, method='html', with_tail=True) 4042 self.assertEqual( 4043 result, 4044 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n")) 4045 result = tostring(div, method='html', with_tail=False) 4046 self.assertEqual( 4047 result, 4048 _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
4049
4050 - def test_standalone(self):
4051 tostring = self.etree.tostring 4052 XML = self.etree.XML 4053 ElementTree = self.etree.ElementTree 4054 Element = self.etree.Element 4055 4056 tree = Element("root").getroottree() 4057 self.assertEqual(None, tree.docinfo.standalone) 4058 4059 tree = XML(_bytes("<root/>")).getroottree() 4060 self.assertEqual(None, tree.docinfo.standalone) 4061 4062 tree = XML(_bytes( 4063 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>" 4064 )).getroottree() 4065 self.assertEqual(True, tree.docinfo.standalone) 4066 4067 tree = XML(_bytes( 4068 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>" 4069 )).getroottree() 4070 self.assertEqual(False, tree.docinfo.standalone)
4071
4072 - def test_tostring_standalone(self):
4073 tostring = self.etree.tostring 4074 XML = self.etree.XML 4075 ElementTree = self.etree.ElementTree 4076 4077 root = XML(_bytes("<root/>")) 4078 4079 tree = ElementTree(root) 4080 self.assertEqual(None, tree.docinfo.standalone) 4081 4082 result = tostring(root, xml_declaration=True, encoding="ASCII") 4083 self.assertEqual(result, _bytes( 4084 "<?xml version='1.0' encoding='ASCII'?>\n<root/>")) 4085 4086 result = tostring(root, xml_declaration=True, encoding="ASCII", 4087 standalone=True) 4088 self.assertEqual(result, _bytes( 4089 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>")) 4090 4091 tree = ElementTree(XML(result)) 4092 self.assertEqual(True, tree.docinfo.standalone) 4093 4094 result = tostring(root, xml_declaration=True, encoding="ASCII", 4095 standalone=False) 4096 self.assertEqual(result, _bytes( 4097 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>")) 4098 4099 tree = ElementTree(XML(result)) 4100 self.assertEqual(False, tree.docinfo.standalone)
4101
4102 - def test_tostring_standalone_in_out(self):
4103 tostring = self.etree.tostring 4104 XML = self.etree.XML 4105 ElementTree = self.etree.ElementTree 4106 4107 root = XML(_bytes( 4108 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>")) 4109 4110 tree = ElementTree(root) 4111 self.assertEqual(True, tree.docinfo.standalone) 4112 4113 result = tostring(root, xml_declaration=True, encoding="ASCII") 4114 self.assertEqual(result, _bytes( 4115 "<?xml version='1.0' encoding='ASCII'?>\n<root/>")) 4116 4117 result = tostring(root, xml_declaration=True, encoding="ASCII", 4118 standalone=True) 4119 self.assertEqual(result, _bytes( 4120 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
4121
4122 - def test_tostring_method_text_encoding(self):
4123 tostring = self.etree.tostring 4124 Element = self.etree.Element 4125 SubElement = self.etree.SubElement 4126 4127 a = Element('a') 4128 a.text = "A" 4129 a.tail = "tail" 4130 b = SubElement(a, 'b') 4131 b.text = "B" 4132 b.tail = _str("Søk på nettet") 4133 c = SubElement(a, 'c') 4134 c.text = "C" 4135 4136 result = tostring(a, method="text", encoding="UTF-16") 4137 4138 self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"), 4139 result)
4140
4141 - def test_tostring_method_text_unicode(self):
4142 tostring = self.etree.tostring 4143 Element = self.etree.Element 4144 SubElement = self.etree.SubElement 4145 4146 a = Element('a') 4147 a.text = _str('Søk på nettetA') 4148 a.tail = "tail" 4149 b = SubElement(a, 'b') 4150 b.text = "B" 4151 b.tail = _str('Søk på nettetB') 4152 c = SubElement(a, 'c') 4153 c.text = "C" 4154 4155 self.assertRaises(UnicodeEncodeError, 4156 tostring, a, method="text") 4157 4158 self.assertEqual( 4159 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'), 4160 tostring(a, encoding="UTF-8", method="text"))
4161
4162 - def test_tounicode(self):
4163 tounicode = self.etree.tounicode 4164 Element = self.etree.Element 4165 SubElement = self.etree.SubElement 4166 4167 a = Element('a') 4168 b = SubElement(a, 'b') 4169 c = SubElement(a, 'c') 4170 4171 self.assertTrue(isinstance(tounicode(a), _unicode)) 4172 self.assertEqual(_bytes('<a><b></b><c></c></a>'), 4173 canonicalize(tounicode(a)))
4174
4175 - def test_tounicode_element(self):
4176 tounicode = self.etree.tounicode 4177 Element = self.etree.Element 4178 SubElement = self.etree.SubElement 4179 4180 a = Element('a') 4181 b = SubElement(a, 'b') 4182 c = SubElement(a, 'c') 4183 d = SubElement(c, 'd') 4184 self.assertTrue(isinstance(tounicode(b), _unicode)) 4185 self.assertTrue(isinstance(tounicode(c), _unicode)) 4186 self.assertEqual(_bytes('<b></b>'), 4187 canonicalize(tounicode(b))) 4188 self.assertEqual(_bytes('<c><d></d></c>'), 4189 canonicalize(tounicode(c)))
4190
4191 - def test_tounicode_none(self):
4192 tounicode = self.etree.tounicode 4193 self.assertRaises(TypeError, self.etree.tounicode, None)
4194
4195 - def test_tounicode_element_tail(self):
4196 tounicode = self.etree.tounicode 4197 Element = self.etree.Element 4198 SubElement = self.etree.SubElement 4199 4200 a = Element('a') 4201 b = SubElement(a, 'b') 4202 c = SubElement(a, 'c') 4203 d = SubElement(c, 'd') 4204 b.tail = 'Foo' 4205 4206 self.assertTrue(isinstance(tounicode(b), _unicode)) 4207 self.assertTrue(tounicode(b) == '<b/>Foo' or 4208 tounicode(b) == '<b />Foo')
4209
4210 - def test_tounicode_pretty(self):
4211 tounicode = self.etree.tounicode 4212 Element = self.etree.Element 4213 SubElement = self.etree.SubElement 4214 4215 a = Element('a') 4216 b = SubElement(a, 'b') 4217 c = SubElement(a, 'c') 4218 4219 result = tounicode(a) 4220 self.assertEqual(result, "<a><b/><c/></a>") 4221 4222 result = tounicode(a, pretty_print=False) 4223 self.assertEqual(result, "<a><b/><c/></a>") 4224 4225 result = tounicode(a, pretty_print=True) 4226 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4227
4228 - def test_tostring_unicode(self):
4229 tostring = self.etree.tostring 4230 Element = self.etree.Element 4231 SubElement = self.etree.SubElement 4232 4233 a = Element('a') 4234 b = SubElement(a, 'b') 4235 c = SubElement(a, 'c') 4236 4237 self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode)) 4238 self.assertEqual(_bytes('<a><b></b><c></c></a>'), 4239 canonicalize(tostring(a, encoding=_unicode)))
4240
4241 - def test_tostring_unicode_element(self):
4242 tostring = self.etree.tostring 4243 Element = self.etree.Element 4244 SubElement = self.etree.SubElement 4245 4246 a = Element('a') 4247 b = SubElement(a, 'b') 4248 c = SubElement(a, 'c') 4249 d = SubElement(c, 'd') 4250 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode)) 4251 self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode)) 4252 self.assertEqual(_bytes('<b></b>'), 4253 canonicalize(tostring(b, encoding=_unicode))) 4254 self.assertEqual(_bytes('<c><d></d></c>'), 4255 canonicalize(tostring(c, encoding=_unicode)))
4256
4257 - def test_tostring_unicode_none(self):
4258 tostring = self.etree.tostring 4259 self.assertRaises(TypeError, self.etree.tostring, 4260 None, encoding=_unicode)
4261
4262 - def test_tostring_unicode_element_tail(self):
4263 tostring = self.etree.tostring 4264 Element = self.etree.Element 4265 SubElement = self.etree.SubElement 4266 4267 a = Element('a') 4268 b = SubElement(a, 'b') 4269 c = SubElement(a, 'c') 4270 d = SubElement(c, 'd') 4271 b.tail = 'Foo' 4272 4273 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode)) 4274 self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or 4275 tostring(b, encoding=_unicode) == '<b />Foo')
4276
4277 - def test_tostring_unicode_pretty(self):
4278 tostring = self.etree.tostring 4279 Element = self.etree.Element 4280 SubElement = self.etree.SubElement 4281 4282 a = Element('a') 4283 b = SubElement(a, 'b') 4284 c = SubElement(a, 'c') 4285 4286 result = tostring(a, encoding=_unicode) 4287 self.assertEqual(result, "<a><b/><c/></a>") 4288 4289 result = tostring(a, encoding=_unicode, pretty_print=False) 4290 self.assertEqual(result, "<a><b/><c/></a>") 4291 4292 result = tostring(a, encoding=_unicode, pretty_print=True) 4293 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4294
4295 - def test_pypy_proxy_collect(self):
4296 root = etree.Element('parent') 4297 etree.SubElement(root, 'child') 4298 4299 self.assertEqual(len(root), 1) 4300 self.assertEqual(root[0].tag, 'child') 4301 4302 # in PyPy, GC used to kill the Python proxy instance without cleanup 4303 gc.collect() 4304 self.assertEqual(len(root), 1) 4305 self.assertEqual(root[0].tag, 'child')
4306
4307 - def test_element_refcycle(self):
4308 class SubEl(etree.ElementBase): 4309 pass
4310 4311 el1 = SubEl() 4312 el2 = SubEl() 4313 self.assertEqual('SubEl', el1.tag) 4314 self.assertEqual('SubEl', el2.tag) 4315 el1.other = el2 4316 el2.other = el1 4317 4318 del el1, el2 4319 gc.collect() 4320 # not really testing anything here, but it shouldn't crash 4321
4322 - def test_proxy_collect_siblings(self):
4323 root = etree.Element('parent') 4324 c1 = etree.SubElement(root, 'child1') 4325 c2 = etree.SubElement(root, 'child2') 4326 4327 root.remove(c1) 4328 root.remove(c2) 4329 c1.addnext(c2) 4330 del c1 4331 # trigger deallocation attempt of c1 4332 c2.getprevious() 4333 # make sure it wasn't deallocated 4334 self.assertEqual('child1', c2.getprevious().tag)
4335
4336 - def test_proxy_collect_siblings_text(self):
4337 root = etree.Element('parent') 4338 c1 = etree.SubElement(root, 'child1') 4339 c2 = etree.SubElement(root, 'child2') 4340 4341 root.remove(c1) 4342 root.remove(c2) 4343 c1.addnext(c2) 4344 c1.tail = 'abc' 4345 c2.tail = 'xyz' 4346 del c1 4347 # trigger deallocation attempt of c1 4348 c2.getprevious() 4349 # make sure it wasn't deallocated 4350 self.assertEqual('child1', c2.getprevious().tag) 4351 self.assertEqual('abc', c2.getprevious().tail)
4352 4353 # helper methods 4354
4355 - def _writeElement(self, element, encoding='us-ascii', compression=0):
4356 """Write out element for comparison. 4357 """ 4358 ElementTree = self.etree.ElementTree 4359 f = BytesIO() 4360 tree = ElementTree(element=element) 4361 tree.write(f, encoding=encoding, compression=compression) 4362 data = f.getvalue() 4363 if compression: 4364 data = zlib.decompress(data) 4365 return canonicalize(data)
4366 4367
4368 -class _XIncludeTestCase(HelperTestCase):
4369 - def test_xinclude_text(self):
4370 filename = fileInTestDir('test_broken.xml') 4371 root = etree.XML(_bytes('''\ 4372 <doc xmlns:xi="http://www.w3.org/2001/XInclude"> 4373 <xi:include href="%s" parse="text"/> 4374 </doc> 4375 ''' % path2url(filename))) 4376 old_text = root.text 4377 content = read_file(filename) 4378 old_tail = root[0].tail 4379 4380 self.include( etree.ElementTree(root) ) 4381 self.assertEqual(old_text + content + old_tail, 4382 root.text)
4383
4384 - def test_xinclude(self):
4385 tree = etree.parse(fileInTestDir('include/test_xinclude.xml')) 4386 self.assertNotEqual( 4387 'a', 4388 tree.getroot()[1].tag) 4389 # process xincludes 4390 self.include( tree ) 4391 # check whether we find it replaced with included data 4392 self.assertEqual( 4393 'a', 4394 tree.getroot()[1].tag)
4395
4396 - def test_xinclude_resolver(self):
4397 class res(etree.Resolver): 4398 include_text = read_file(fileInTestDir('test.xml')) 4399 called = {} 4400 def resolve(self, url, id, context): 4401 if url.endswith(".dtd"): 4402 self.called["dtd"] = True 4403 return self.resolve_filename( 4404 fileInTestDir('test.dtd'), context) 4405 elif url.endswith("test_xinclude.xml"): 4406 self.called["input"] = True 4407 return None # delegate to default resolver 4408 else: 4409 self.called["include"] = True 4410 return self.resolve_string(self.include_text, context)
4411 4412 res_instance = res() 4413 parser = etree.XMLParser(load_dtd = True) 4414 parser.resolvers.add(res_instance) 4415 4416 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'), 4417 parser = parser) 4418 4419 self.include(tree) 4420 4421 called = list(res_instance.called.items()) 4422 called.sort() 4423 self.assertEqual( 4424 [("dtd", True), ("include", True), ("input", True)], 4425 called) 4426
4427 - def test_xinclude_resolver_recursive(self):
4428 data = textwrap.dedent(''' 4429 <doc xmlns:xi="http://www.w3.org/2001/XInclude"> 4430 <foo/> 4431 <xi:include href="./test.xml" /> 4432 </doc> 4433 ''') 4434 4435 class Resolver(etree.Resolver): 4436 called = {} 4437 4438 def resolve(self, url, id, context): 4439 if url.endswith("test_xinclude.xml"): 4440 assert not self.called.get("input") 4441 self.called["input"] = True 4442 return None # delegate to default resolver 4443 elif url.endswith('/test5.xml'): 4444 assert not self.called.get("DONE") 4445 self.called["DONE"] = True 4446 return self.resolve_string('<DONE/>', context) 4447 else: 4448 _, filename = url.rsplit('/', 1) 4449 assert not self.called.get(filename) 4450 self.called[filename] = True 4451 next_data = data.replace( 4452 'test.xml', 'test%d.xml' % len(self.called)) 4453 return self.resolve_string(next_data, context)
4454 4455 res_instance = Resolver() 4456 parser = etree.XMLParser(load_dtd=True) 4457 parser.resolvers.add(res_instance) 4458 4459 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'), 4460 parser=parser) 4461 4462 self.include(tree) 4463 4464 called = list(res_instance.called.items()) 4465 called.sort() 4466 self.assertEqual( 4467 [("DONE", True), ("input", True), ("test.xml", True), 4468 ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)], 4469 called) 4470 4471
4472 -class ETreeXIncludeTestCase(_XIncludeTestCase):
4473 - def include(self, tree):
4474 tree.xinclude()
4475 4476
4477 -class ElementIncludeTestCase(_XIncludeTestCase):
4478 from lxml import ElementInclude 4479
4480 - def include(self, tree, loader=None, max_depth=None):
4481 self.ElementInclude.include(tree.getroot(), loader=loader, max_depth=max_depth)
4482 4483 XINCLUDE = {} 4484 4485 XINCLUDE["Recursive1.xml"] = """\ 4486 <?xml version='1.0'?> 4487 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4488 <p>The following is the source code of Recursive2.xml:</p> 4489 <xi:include href="Recursive2.xml"/> 4490 </document> 4491 """ 4492 4493 XINCLUDE["Recursive2.xml"] = """\ 4494 <?xml version='1.0'?> 4495 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4496 <p>The following is the source code of Recursive3.xml:</p> 4497 <xi:include href="Recursive3.xml"/> 4498 </document> 4499 """ 4500 4501 XINCLUDE["Recursive3.xml"] = """\ 4502 <?xml version='1.0'?> 4503 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4504 <p>The following is the source code of Recursive1.xml:</p> 4505 <xi:include href="Recursive1.xml"/> 4506 </document> 4507 """ 4508 4509 XINCLUDE["NonRecursive1.xml"] = """\ 4510 <?xml version='1.0'?> 4511 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4512 <p>The following is multiple times the source code of NonRecursive3.xml:</p> 4513 <xi:include href="NonRecursive3.xml"/> 4514 <xi:include href="NonRecursive3.xml"/> 4515 <p>The following is multiple times the source code of Leaf.xml:</p> 4516 <xi:include href="Leaf.xml"/> 4517 <xi:include href="Leaf.xml"/> 4518 <xi:include href="Leaf.xml"/> 4519 <p>One more time the source code of NonRecursive3.xml:</p> 4520 <xi:include href="NonRecursive3.xml"/> 4521 </document> 4522 """ 4523 4524 XINCLUDE["NonRecursive2.xml"] = """\ 4525 <?xml version='1.0'?> 4526 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4527 <p>The following is multiple times the source code of NonRecursive3.xml:</p> 4528 <xi:include href="NonRecursive3.xml"/> 4529 <xi:include href="NonRecursive3.xml"/> 4530 </document> 4531 """ 4532 4533 XINCLUDE["NonRecursive3.xml"] = """\ 4534 <?xml version='1.0'?> 4535 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4536 <p>The following is multiple times the source code of Leaf.xml:</p> 4537 <xi:include href="Leaf.xml"/> 4538 <xi:include href="Leaf.xml"/> 4539 </document> 4540 """ 4541 4542 XINCLUDE["Leaf.xml"] = """\ 4543 <?xml version='1.0'?> 4544 <document xmlns:xi="http://www.w3.org/2001/XInclude"> 4545 <p>No further includes</p> 4546 </document> 4547 """ 4548
4549 - def xinclude_loader(self, href, parse="xml", encoding=None):
4550 try: 4551 data = textwrap.dedent(self.XINCLUDE[href]) 4552 except KeyError: 4553 raise OSError("resource not found") 4554 if parse == "xml": 4555 data = etree.fromstring(data) 4556 return data
4557
4558 - def test_xinclude_failures(self):
4559 # Test infinitely recursive includes. 4560 document = self.xinclude_loader("Recursive1.xml").getroottree() 4561 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm: 4562 self.include(document, self.xinclude_loader) 4563 self.assertEqual(str(cm.exception), 4564 "recursive include of 'Recursive2.xml' detected") 4565 4566 # Test 'max_depth' limitation. 4567 document = self.xinclude_loader("Recursive1.xml").getroottree() 4568 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm: 4569 self.include(document, self.xinclude_loader, max_depth=None) 4570 self.assertEqual(str(cm.exception), 4571 "recursive include of 'Recursive2.xml' detected") 4572 4573 document = self.xinclude_loader("Recursive1.xml").getroottree() 4574 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm: 4575 self.include(document, self.xinclude_loader, max_depth=0) 4576 self.assertEqual(str(cm.exception), 4577 "maximum xinclude depth reached when including file Recursive2.xml") 4578 4579 document = self.xinclude_loader("Recursive1.xml").getroottree() 4580 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm: 4581 self.include(document, self.xinclude_loader, max_depth=1) 4582 self.assertEqual(str(cm.exception), 4583 "maximum xinclude depth reached when including file Recursive3.xml") 4584 4585 document = self.xinclude_loader("Recursive1.xml").getroottree() 4586 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm: 4587 self.include(document, self.xinclude_loader, max_depth=2) 4588 self.assertEqual(str(cm.exception), 4589 "maximum xinclude depth reached when including file Recursive1.xml") 4590 4591 document = self.xinclude_loader("Recursive1.xml").getroottree() 4592 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm: 4593 self.include(document, self.xinclude_loader, max_depth=3) 4594 self.assertEqual(str(cm.exception), 4595 "recursive include of 'Recursive2.xml' detected")
4596
4598 # Test that including the same file multiple times, but on the same level 4599 # is not detected as recursive include 4600 document = self.xinclude_loader("NonRecursive3.xml").getroottree() 4601 self.include(document, self.xinclude_loader) 4602 4603 # same but for more than one level 4604 document = self.xinclude_loader("NonRecursive1.xml").getroottree() 4605 self.include(document, self.xinclude_loader) 4606 4607 # same but no Leaf.xml in top-level file 4608 document = self.xinclude_loader("NonRecursive2.xml").getroottree() 4609 self.include(document, self.xinclude_loader)
4610 4611
4612 -class ETreeC14NTestCase(HelperTestCase):
4613 - def test_c14n(self):
4614 tree = self.parse(_bytes('<a><b/></a>')) 4615 f = BytesIO() 4616 tree.write_c14n(f) 4617 s = f.getvalue() 4618 self.assertEqual(_bytes('<a><b></b></a>'), 4619 s)
4620
4621 - def test_c14n_gzip(self):
4622 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4623 f = BytesIO() 4624 tree.write_c14n(f, compression=9) 4625 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile: 4626 s = gzfile.read() 4627 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'), 4628 s)
4629
4630 - def test_c14n_file(self):
4631 tree = self.parse(_bytes('<a><b/></a>')) 4632 with tmpfile() as filename: 4633 tree.write_c14n(filename) 4634 data = read_file(filename, 'rb') 4635 self.assertEqual(_bytes('<a><b></b></a>'), 4636 data)
4637
4638 - def test_c14n_file_gzip(self):
4639 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4640 with tmpfile() as filename: 4641 tree.write_c14n(filename, compression=9) 4642 with gzip.open(filename, 'rb') as f: 4643 data = f.read() 4644 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'), 4645 data)
4646
4647 - def test_c14n2_file_gzip(self):
4648 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4649 with tmpfile() as filename: 4650 tree.write(filename, method='c14n2', compression=9) 4651 with gzip.open(filename, 'rb') as f: 4652 data = f.read() 4653 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'), 4654 data)
4655
4656 - def test_c14n2_with_text(self):
4657 tree = self.parse( 4658 b'<?xml version="1.0"?> <a> abc \n <b> btext </b> btail <c/> ctail </a> ') 4659 f = BytesIO() 4660 tree.write(f, method='c14n2') 4661 s = f.getvalue() 4662 self.assertEqual(b'<a> abc \n <b> btext </b> btail <c></c> ctail </a>', 4663 s) 4664 4665 f = BytesIO() 4666 tree.write(f, method='c14n2', strip_text=True) 4667 s = f.getvalue() 4668 self.assertEqual(b'<a>abc<b>btext</b>btail<c></c>ctail</a>', 4669 s)
4670
4671 - def test_c14n_with_comments(self):
4672 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4673 f = BytesIO() 4674 tree.write_c14n(f) 4675 s = f.getvalue() 4676 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4677 s) 4678 f = BytesIO() 4679 tree.write_c14n(f, with_comments=True) 4680 s = f.getvalue() 4681 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4682 s) 4683 f = BytesIO() 4684 tree.write_c14n(f, with_comments=False) 4685 s = f.getvalue() 4686 self.assertEqual(_bytes('<a><b></b></a>'), 4687 s)
4688
4689 - def test_c14n2_with_comments(self):
4690 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4691 f = BytesIO() 4692 tree.write(f, method='c14n2') 4693 s = f.getvalue() 4694 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4695 s) 4696 f = BytesIO() 4697 tree.write(f, method='c14n2', with_comments=True) 4698 s = f.getvalue() 4699 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4700 s) 4701 f = BytesIO() 4702 tree.write(f, method='c14n2', with_comments=False) 4703 s = f.getvalue() 4704 self.assertEqual(_bytes('<a><b></b></a>'), 4705 s)
4706
4708 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4709 s = etree.tostring(tree, method='c14n') 4710 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4711 s) 4712 s = etree.tostring(tree, method='c14n', with_comments=True) 4713 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'), 4714 s) 4715 s = etree.tostring(tree, method='c14n', with_comments=False) 4716 self.assertEqual(_bytes('<a><b></b></a>'), 4717 s)
4718
4720 tree = self.parse(b'<!--hi--><a><!--ho--><b/></a><!--hu-->') 4721 s = etree.tostring(tree, method='c14n2') 4722 self.assertEqual(b'<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->', 4723 s) 4724 s = etree.tostring(tree, method='c14n2', with_comments=True) 4725 self.assertEqual(b'<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->', 4726 s) 4727 s = etree.tostring(tree, method='c14n2', with_comments=False) 4728 self.assertEqual(b'<a><b></b></a>', 4729 s)
4730
4732 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->')) 4733 s = etree.tostring(tree.getroot(), method='c14n') 4734 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'), 4735 s) 4736 s = etree.tostring(tree.getroot(), method='c14n', with_comments=True) 4737 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'), 4738 s) 4739 s = etree.tostring(tree.getroot(), method='c14n', with_comments=False) 4740 self.assertEqual(_bytes('<a><b></b></a>'), 4741 s)
4742
4743 - def test_c14n_exclusive(self):
4744 tree = self.parse(_bytes( 4745 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4746 f = BytesIO() 4747 tree.write_c14n(f) 4748 s = f.getvalue() 4749 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4750 s) 4751 f = BytesIO() 4752 tree.write_c14n(f, exclusive=False) 4753 s = f.getvalue() 4754 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4755 s) 4756 f = BytesIO() 4757 tree.write_c14n(f, exclusive=True) 4758 s = f.getvalue() 4759 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'), 4760 s) 4761 4762 f = BytesIO() 4763 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z']) 4764 s = f.getvalue() 4765 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'), 4766 s)
4767
4769 tree = self.parse(_bytes( 4770 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4771 s = etree.tostring(tree, method='c14n') 4772 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4773 s) 4774 s = etree.tostring(tree, method='c14n', exclusive=False) 4775 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4776 s) 4777 s = etree.tostring(tree, method='c14n', exclusive=True) 4778 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'), 4779 s) 4780 4781 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y']) 4782 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'), 4783 s)
4784
4786 tree = self.parse(_bytes( 4787 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4788 s = etree.tostring(tree.getroot(), method='c14n') 4789 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4790 s) 4791 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False) 4792 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4793 s) 4794 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True) 4795 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'), 4796 s) 4797 4798 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False) 4799 self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'), 4800 s) 4801 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True) 4802 self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'), 4803 s) 4804 4805 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y']) 4806 self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'), 4807 s)
4808
4810 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)""" 4811 tree = self.parse(_bytes( 4812 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>')) 4813 4814 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z']) 4815 self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'), 4816 s)
4817 4818
4819 -class ETreeWriteTestCase(HelperTestCase):
4820 - def test_write(self):
4821 tree = self.parse(_bytes('<a><b/></a>')) 4822 f = BytesIO() 4823 tree.write(f) 4824 s = f.getvalue() 4825 self.assertEqual(_bytes('<a><b/></a>'), 4826 s)
4827
4828 - def test_write_doctype(self):
4829 tree = self.parse(_bytes('<a><b/></a>')) 4830 f = BytesIO() 4831 tree.write(f, doctype='HUHU') 4832 s = f.getvalue() 4833 self.assertEqual(_bytes('HUHU\n<a><b/></a>'), 4834 s)
4835
4836 - def test_write_gzip(self):
4837 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4838 f = BytesIO() 4839 tree.write(f, compression=9) 4840 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile: 4841 s = gzfile.read() 4842 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4843 s)
4844
4845 - def test_write_gzip_doctype(self):
4846 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4847 f = BytesIO() 4848 tree.write(f, compression=9, doctype='<!DOCTYPE a>') 4849 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile: 4850 s = gzfile.read() 4851 self.assertEqual(_bytes('<!DOCTYPE a>\n<a>'+'<b/>'*200+'</a>'), 4852 s)
4853
4854 - def test_write_gzip_level(self):
4855 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4856 f = BytesIO() 4857 tree.write(f, compression=0) 4858 s0 = f.getvalue() 4859 4860 f = BytesIO() 4861 tree.write(f) 4862 self.assertEqual(f.getvalue(), s0) 4863 4864 f = BytesIO() 4865 tree.write(f, compression=1) 4866 s = f.getvalue() 4867 self.assertTrue(len(s) <= len(s0)) 4868 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile: 4869 s1 = gzfile.read() 4870 4871 f = BytesIO() 4872 tree.write(f, compression=9) 4873 s = f.getvalue() 4874 self.assertTrue(len(s) <= len(s0)) 4875 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile: 4876 s9 = gzfile.read() 4877 4878 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4879 s0) 4880 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4881 s1) 4882 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4883 s9)
4884
4885 - def test_write_file(self):
4886 tree = self.parse(_bytes('<a><b/></a>')) 4887 with tmpfile() as filename: 4888 tree.write(filename) 4889 data = read_file(filename, 'rb') 4890 self.assertEqual(_bytes('<a><b/></a>'), 4891 data)
4892
4893 - def test_write_file_gzip(self):
4894 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4895 with tmpfile() as filename: 4896 tree.write(filename, compression=9) 4897 with gzip.open(filename, 'rb') as f: 4898 data = f.read() 4899 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4900 data)
4901
4902 - def test_write_file_gzip_parse(self):
4903 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4904 with tmpfile() as filename: 4905 tree.write(filename, compression=9) 4906 data = etree.tostring(etree.parse(filename)) 4907 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4908 data)
4909
4911 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>')) 4912 with tmpfile() as filename: 4913 tree.write(filename, compression=9) 4914 with gzip.GzipFile(filename) as f: 4915 data = etree.tostring(etree.parse(f)) 4916 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'), 4917 data)
4918
4919 - def test_write_file_url(self):
4920 xml = _bytes('<a>'+'<b/>'*200+'</a>') 4921 tree = self.parse(xml) 4922 with tmpfile(prefix="p+%20", suffix=".xml") as filename: 4923 url = 'file://' + (filename if sys.platform != 'win32' 4924 else '/' + filename.replace('\\', '/')) 4925 tree.write(url) 4926 data = read_file(filename, 'rb').replace(_bytes('\n'), _bytes('')) 4927 self.assertEqual(data, xml)
4928 4929
4930 -class ETreeErrorLogTest(HelperTestCase):
4931 etree = etree 4932
4933 - def test_parse_error_logging(self):
4934 parse = self.etree.parse 4935 f = BytesIO('<a><b></c></b></a>') 4936 self.etree.clear_error_log() 4937 try: 4938 parse(f) 4939 logs = None 4940 except SyntaxError: 4941 e = sys.exc_info()[1] 4942 logs = e.error_log 4943 f.close() 4944 self.assertTrue([ log for log in logs 4945 if 'mismatch' in log.message ]) 4946 self.assertTrue([ log for log in logs 4947 if 'PARSER' in log.domain_name]) 4948 self.assertTrue([ log for log in logs 4949 if 'ERR_TAG_NAME_MISMATCH' in log.type_name ]) 4950 self.assertTrue([ log for log in logs 4951 if 1 == log.line ]) 4952 self.assertTrue([ log for log in logs 4953 if 15 == log.column ])
4954
4955 - def _test_python_error_logging(self):
4956 """This can't really be tested as long as there isn't a way to 4957 reset the logging setup ... 4958 """ 4959 parse = self.etree.parse 4960 4961 messages = [] 4962 class Logger(self.etree.PyErrorLog): 4963 def log(self, entry, message, *args): 4964 messages.append(message)
4965 4966 self.etree.use_global_python_log(Logger()) 4967 f = BytesIO('<a><b></c></b></a>') 4968 try: 4969 parse(f) 4970 except SyntaxError: 4971 pass 4972 f.close() 4973 4974 self.assertTrue([ message for message in messages 4975 if 'mismatch' in message ]) 4976 self.assertTrue([ message for message in messages 4977 if ':PARSER:' in message]) 4978 self.assertTrue([ message for message in messages 4979 if ':ERR_TAG_NAME_MISMATCH:' in message ]) 4980 self.assertTrue([ message for message in messages 4981 if ':1:15:' in message ]) 4982 4983
4984 -class XMLPullParserTest(unittest.TestCase):
4985 etree = etree 4986
4987 - def assert_event_tags(self, events, expected):
4988 self.assertEqual([(action, elem.tag) for action, elem in events], 4989 expected)
4990
4992 class Target(object): 4993 def start(self, tag, attrib): 4994 return 'start(%s)' % tag
4995 def end(self, tag): 4996 return 'end(%s)' % tag
4997 def close(self): 4998 return 'close()' 4999 5000 parser = self.etree.XMLPullParser(target=Target()) 5001 events = parser.read_events() 5002 5003 parser.feed('<root><element>') 5004 self.assertFalse(list(events)) 5005 self.assertFalse(list(events)) 5006 parser.feed('</element><child>') 5007 self.assertEqual([('end', 'end(element)')], list(events)) 5008 parser.feed('</child>') 5009 self.assertEqual([('end', 'end(child)')], list(events)) 5010 parser.feed('</root>') 5011 self.assertEqual([('end', 'end(root)')], list(events)) 5012 self.assertFalse(list(events)) 5013 self.assertEqual('close()', parser.close()) 5014
5015 - def test_pull_from_simple_target_start_end(self):
5016 class Target(object): 5017 def start(self, tag, attrib): 5018 return 'start(%s)' % tag
5019 def end(self, tag): 5020 return 'end(%s)' % tag 5021 def close(self): 5022 return 'close()' 5023 5024 parser = self.etree.XMLPullParser( 5025 ['start', 'end'], target=Target()) 5026 events = parser.read_events() 5027 5028 parser.feed('<root><element>') 5029 self.assertEqual( 5030 [('start', 'start(root)'), ('start', 'start(element)')], 5031 list(events)) 5032 self.assertFalse(list(events)) 5033 parser.feed('</element><child>') 5034 self.assertEqual( 5035 [('end', 'end(element)'), ('start', 'start(child)')], 5036 list(events)) 5037 parser.feed('</child>') 5038 self.assertEqual( 5039 [('end', 'end(child)')], 5040 list(events)) 5041 parser.feed('</root>') 5042 self.assertEqual( 5043 [('end', 'end(root)')], 5044 list(events)) 5045 self.assertFalse(list(events)) 5046 self.assertEqual('close()', parser.close()) 5047
5048 - def test_pull_from_tree_builder(self):
5049 parser = self.etree.XMLPullParser( 5050 ['start', 'end'], target=etree.TreeBuilder()) 5051 events = parser.read_events() 5052 5053 parser.feed('<root><element>') 5054 self.assert_event_tags( 5055 events, [('start', 'root'), ('start', 'element')]) 5056 self.assertFalse(list(events)) 5057 parser.feed('</element><child>') 5058 self.assert_event_tags( 5059 events, [('end', 'element'), ('start', 'child')]) 5060 parser.feed('</child>') 5061 self.assert_event_tags( 5062 events, [('end', 'child')]) 5063 parser.feed('</root>') 5064 self.assert_event_tags( 5065 events, [('end', 'root')]) 5066 self.assertFalse(list(events)) 5067 root = parser.close() 5068 self.assertEqual('root', root.tag)
5069
5070 - def test_pull_from_tree_builder_subclass(self):
5071 class Target(etree.TreeBuilder): 5072 def end(self, tag): 5073 el = super(Target, self).end(tag) 5074 el.tag += '-huhu' 5075 return el
5076 5077 parser = self.etree.XMLPullParser( 5078 ['start', 'end'], target=Target()) 5079 events = parser.read_events() 5080 5081 parser.feed('<root><element>') 5082 self.assert_event_tags( 5083 events, [('start', 'root'), ('start', 'element')]) 5084 self.assertFalse(list(events)) 5085 parser.feed('</element><child>') 5086 self.assert_event_tags( 5087 events, [('end', 'element-huhu'), ('start', 'child')]) 5088 parser.feed('</child>') 5089 self.assert_event_tags( 5090 events, [('end', 'child-huhu')]) 5091 parser.feed('</root>') 5092 self.assert_event_tags( 5093 events, [('end', 'root-huhu')]) 5094 self.assertFalse(list(events)) 5095 root = parser.close() 5096 self.assertEqual('root-huhu', root.tag) 5097 5098
5099 -def test_suite():
5100 suite = unittest.TestSuite() 5101 suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)]) 5102 suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)]) 5103 suite.addTests([unittest.makeSuite(ElementIncludeTestCase)]) 5104 suite.addTests([unittest.makeSuite(ETreeC14NTestCase)]) 5105 suite.addTests([unittest.makeSuite(ETreeWriteTestCase)]) 5106 suite.addTests([unittest.makeSuite(ETreeErrorLogTest)]) 5107 suite.addTests([unittest.makeSuite(XMLPullParserTest)]) 5108 5109 # add original doctests from ElementTree selftest modules 5110 from . import selftest, selftest2 5111 suite.addTests(doctest.DocTestSuite(selftest)) 5112 suite.addTests(doctest.DocTestSuite(selftest2)) 5113 5114 # add doctests 5115 suite.addTests(doctest.DocTestSuite(etree)) 5116 suite.addTests( 5117 [make_doctest('../../../doc/tutorial.txt')]) 5118 suite.addTests( 5119 [make_doctest('../../../doc/api.txt')]) 5120 suite.addTests( 5121 [make_doctest('../../../doc/FAQ.txt')]) 5122 suite.addTests( 5123 [make_doctest('../../../doc/parsing.txt')]) 5124 suite.addTests( 5125 [make_doctest('../../../doc/resolvers.txt')]) 5126 return suite
5127 5128 5129 if __name__ == '__main__': 5130 print('to test use test.py %s' % __file__) 5131