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