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