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