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