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