Home | Trees | Indices | Help |
|
---|
|
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 import os.path 11 import unittest 12 import copy 13 import sys 14 import re 15 import gc 16 import operator 17 import tempfile 18 import textwrap 19 import zlib 20 import gzip 21 22 this_dir = os.path.dirname(__file__) 23 if this_dir not in sys.path: 24 sys.path.insert(0, this_dir) # needed for Py3 25 26 from common_imports import etree, StringIO, BytesIO, HelperTestCase 27 from common_imports import fileInTestDir, fileUrlInTestDir, read_file, path2url 28 from common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest 29 from common_imports import canonicalize, sorted, _str, _bytes 30 31 print("") 32 print("TESTED VERSION: %s" % etree.__version__) 33 print(" Python: " + repr(sys.version_info)) 34 print(" lxml.etree: " + repr(etree.LXML_VERSION)) 35 print(" libxml used: " + repr(etree.LIBXML_VERSION)) 36 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION)) 37 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION)) 38 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION)) 39 print("") 40 41 try: 42 _unicode = unicode 43 except NameError: 44 # Python 3 45 _unicode = str 4648 """Tests only for etree, not ElementTree""" 49 etree = etree 5064852 self.assertTrue(isinstance(etree.__version__, _unicode)) 53 self.assertTrue(isinstance(etree.LXML_VERSION, tuple)) 54 self.assertEqual(len(etree.LXML_VERSION), 4) 55 self.assertTrue(isinstance(etree.LXML_VERSION[0], int)) 56 self.assertTrue(isinstance(etree.LXML_VERSION[1], int)) 57 self.assertTrue(isinstance(etree.LXML_VERSION[2], int)) 58 self.assertTrue(isinstance(etree.LXML_VERSION[3], int)) 59 self.assertTrue(etree.__version__.startswith( 60 str(etree.LXML_VERSION[0])))6163 if hasattr(self.etree, '__pyx_capi__'): 64 # newer Pyrex compatible C-API 65 self.assertTrue(isinstance(self.etree.__pyx_capi__, dict)) 66 self.assertTrue(len(self.etree.__pyx_capi__) > 0) 67 else: 68 # older C-API mechanism 69 self.assertTrue(hasattr(self.etree, '_import_c_api'))7072 Element = self.etree.Element 73 el = Element('name') 74 self.assertEqual(el.tag, 'name') 75 el = Element('{}name') 76 self.assertEqual(el.tag, 'name')7779 Element = self.etree.Element 80 el = Element('name') 81 self.assertRaises(ValueError, Element, '{}') 82 self.assertRaises(ValueError, setattr, el, 'tag', '{}') 83 84 self.assertRaises(ValueError, Element, '{test}') 85 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')8688 Element = self.etree.Element 89 self.assertRaises(ValueError, Element, 'p:name') 90 self.assertRaises(ValueError, Element, '{test}p:name') 91 92 el = Element('name') 93 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')9496 Element = self.etree.Element 97 self.assertRaises(ValueError, Element, "p'name") 98 self.assertRaises(ValueError, Element, 'p"name') 99 100 self.assertRaises(ValueError, Element, "{test}p'name") 101 self.assertRaises(ValueError, Element, '{test}p"name') 102 103 el = Element('name') 104 self.assertRaises(ValueError, setattr, el, 'tag', "p'name") 105 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')106108 Element = self.etree.Element 109 self.assertRaises(ValueError, Element, ' name ') 110 self.assertRaises(ValueError, Element, 'na me') 111 self.assertRaises(ValueError, Element, '{test} name') 112 113 el = Element('name') 114 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')115117 Element = self.etree.Element 118 SubElement = self.etree.SubElement 119 120 el = Element('name') 121 self.assertRaises(ValueError, SubElement, el, '{}') 122 self.assertRaises(ValueError, SubElement, el, '{test}')123125 Element = self.etree.Element 126 SubElement = self.etree.SubElement 127 128 el = Element('name') 129 self.assertRaises(ValueError, SubElement, el, 'p:name') 130 self.assertRaises(ValueError, SubElement, el, '{test}p:name')131133 Element = self.etree.Element 134 SubElement = self.etree.SubElement 135 136 el = Element('name') 137 self.assertRaises(ValueError, SubElement, el, "p'name") 138 self.assertRaises(ValueError, SubElement, el, "{test}p'name") 139 140 self.assertRaises(ValueError, SubElement, el, 'p"name') 141 self.assertRaises(ValueError, SubElement, el, '{test}p"name')142144 Element = self.etree.Element 145 SubElement = self.etree.SubElement 146 147 el = Element('name') 148 self.assertRaises(ValueError, SubElement, el, ' name ') 149 self.assertRaises(ValueError, SubElement, el, 'na me') 150 self.assertRaises(ValueError, SubElement, el, '{test} name')151153 Element = self.etree.Element 154 SubElement = self.etree.SubElement 155 156 el = Element('name') 157 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'}) 158 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'}) 159 self.assertEqual(0, len(el))160162 QName = self.etree.QName 163 self.assertRaises(ValueError, QName, '') 164 self.assertRaises(ValueError, QName, 'test', '')165167 QName = self.etree.QName 168 self.assertRaises(ValueError, QName, 'p:name') 169 self.assertRaises(ValueError, QName, 'test', 'p:name')170172 QName = self.etree.QName 173 self.assertRaises(ValueError, QName, ' name ') 174 self.assertRaises(ValueError, QName, 'na me') 175 self.assertRaises(ValueError, QName, 'test', ' name')176178 # ET doesn't have namespace/localname properties on QNames 179 QName = self.etree.QName 180 namespace, localname = 'http://myns', 'a' 181 qname = QName(namespace, localname) 182 self.assertEqual(namespace, qname.namespace) 183 self.assertEqual(localname, qname.localname)184186 # ET doesn't have namespace/localname properties on QNames 187 QName = self.etree.QName 188 qname1 = QName('http://myns', 'a') 189 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'}) 190 191 qname2 = QName(a) 192 self.assertEqual(a.tag, qname1.text) 193 self.assertEqual(qname1.text, qname2.text) 194 self.assertEqual(qname1, qname2)195197 # ET doesn't resove QNames as text values 198 etree = self.etree 199 qname = etree.QName('http://myns', 'a') 200 a = etree.Element(qname, nsmap={'p' : 'http://myns'}) 201 a.text = qname 202 203 self.assertEqual("p:a", a.text)204206 etree = self.etree 207 self.assertRaises(ValueError, 208 etree.Element, "root", nsmap={'"' : 'testns'}) 209 self.assertRaises(ValueError, 210 etree.Element, "root", nsmap={'&' : 'testns'}) 211 self.assertRaises(ValueError, 212 etree.Element, "root", nsmap={'a:b' : 'testns'})213215 # ET in Py 3.x has no "attrib.has_key()" method 216 XML = self.etree.XML 217 218 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />')) 219 self.assertEqual( 220 True, root.attrib.has_key('bar')) 221 self.assertEqual( 222 False, root.attrib.has_key('baz')) 223 self.assertEqual( 224 False, root.attrib.has_key('hah')) 225 self.assertEqual( 226 True, 227 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))228230 Element = self.etree.Element 231 root = Element("root") 232 root.set("attr", "TEST") 233 self.assertEqual("TEST", root.get("attr"))234236 # ElementTree accepts arbitrary attribute values 237 # lxml.etree allows only strings 238 Element = self.etree.Element 239 240 root = Element("root") 241 root.set("attr", "TEST") 242 self.assertEqual("TEST", root.get("attr")) 243 self.assertRaises(TypeError, root.set, "newattr", 5)244246 Element = self.etree.Element 247 248 root = Element("root") 249 root.set("attr", "TEST") 250 self.assertEqual("TEST", root.attrib["attr"]) 251 252 root2 = Element("root2", root.attrib, attr2='TOAST') 253 self.assertEqual("TEST", root2.attrib["attr"]) 254 self.assertEqual("TOAST", root2.attrib["attr2"]) 255 self.assertEqual(None, root.attrib.get("attr2"))256258 Element = self.etree.Element 259 260 keys = ["attr%d" % i for i in range(10)] 261 values = ["TEST-%d" % i for i in range(10)] 262 items = list(zip(keys, values)) 263 264 root = Element("root") 265 for key, value in items: 266 root.set(key, value) 267 self.assertEqual(keys, root.attrib.keys()) 268 self.assertEqual(values, root.attrib.values()) 269 270 root2 = Element("root2", root.attrib, 271 attr_99='TOAST-1', attr_98='TOAST-2') 272 self.assertEqual(['attr_98', 'attr_99'] + keys, 273 root2.attrib.keys()) 274 self.assertEqual(['TOAST-2', 'TOAST-1'] + values, 275 root2.attrib.values()) 276 277 self.assertEqual(keys, root.attrib.keys()) 278 self.assertEqual(values, root.attrib.values())279281 # ElementTree accepts arbitrary attribute values 282 # lxml.etree allows only strings 283 Element = self.etree.Element 284 root = Element("root") 285 self.assertRaises(TypeError, root.set, "newattr", 5) 286 self.assertRaises(TypeError, root.set, "newattr", None)287289 XML = self.etree.XML 290 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>') 291 292 root = XML(xml) 293 self.etree.strip_attributes(root, 'a') 294 self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'), 295 self._writeElement(root)) 296 297 root = XML(xml) 298 self.etree.strip_attributes(root, 'b', 'c') 299 self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'), 300 self._writeElement(root))301303 XML = self.etree.XML 304 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>') 305 306 root = XML(xml) 307 self.etree.strip_attributes(root, 'a') 308 self.assertEqual( 309 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'), 310 self._writeElement(root)) 311 312 root = XML(xml) 313 self.etree.strip_attributes(root, '{http://test/ns}a', 'c') 314 self.assertEqual( 315 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'), 316 self._writeElement(root)) 317 318 root = XML(xml) 319 self.etree.strip_attributes(root, '{http://test/ns}*') 320 self.assertEqual( 321 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'), 322 self._writeElement(root))323325 XML = self.etree.XML 326 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>') 327 328 root = XML(xml) 329 self.etree.strip_elements(root, 'a') 330 self.assertEqual(_bytes('<test><x></x></test>'), 331 self._writeElement(root)) 332 333 root = XML(xml) 334 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z') 335 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'), 336 self._writeElement(root)) 337 338 root = XML(xml) 339 self.etree.strip_elements(root, 'c') 340 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'), 341 self._writeElement(root))342344 XML = self.etree.XML 345 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>') 346 347 root = XML(xml) 348 self.etree.strip_elements(root, 'a') 349 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>'), 350 self._writeElement(root)) 351 352 root = XML(xml) 353 self.etree.strip_elements(root, '{urn:a}b', 'c') 354 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>'), 355 self._writeElement(root)) 356 357 root = XML(xml) 358 self.etree.strip_elements(root, '{urn:a}*', 'c') 359 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 360 self._writeElement(root)) 361 362 root = XML(xml) 363 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False) 364 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 365 self._writeElement(root))366 385 411 438 465 484 497499 # lxml.etree separates target and text 500 Element = self.etree.Element 501 SubElement = self.etree.SubElement 502 ProcessingInstruction = self.etree.ProcessingInstruction 503 504 a = Element('a') 505 a.append(ProcessingInstruction('foo', 'some more text')) 506 self.assertEqual(a[0].target, 'foo') 507 self.assertEqual(a[0].text, 'some more text')508510 XML = self.etree.XML 511 root = XML(_bytes("<test><?mypi my test ?></test>")) 512 self.assertEqual(root[0].target, "mypi") 513 self.assertEqual(root[0].text, "my test ")514516 XML = self.etree.XML 517 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 518 self.assertEqual(root[0].target, "mypi") 519 self.assertEqual(root[0].get('my'), "1") 520 self.assertEqual(root[0].get('test'), " abc ") 521 self.assertEqual(root[0].get('quotes'), "' '") 522 self.assertEqual(root[0].get('only'), None) 523 self.assertEqual(root[0].get('names'), None) 524 self.assertEqual(root[0].get('nope'), None)525527 XML = self.etree.XML 528 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 529 self.assertEqual(root[0].target, "mypi") 530 self.assertEqual(root[0].attrib['my'], "1") 531 self.assertEqual(root[0].attrib['test'], " abc ") 532 self.assertEqual(root[0].attrib['quotes'], "' '") 533 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only') 534 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names') 535 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')536538 # previously caused a crash 539 ProcessingInstruction = self.etree.ProcessingInstruction 540 541 a = ProcessingInstruction("PI", "ONE") 542 b = copy.deepcopy(a) 543 b.text = "ANOTHER" 544 545 self.assertEqual('ONE', a.text) 546 self.assertEqual('ANOTHER', b.text)547549 XML = self.etree.XML 550 tostring = self.etree.tostring 551 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->")) 552 tree1 = self.etree.ElementTree(root) 553 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 554 tostring(tree1)) 555 556 tree2 = copy.deepcopy(tree1) 557 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 558 tostring(tree2)) 559 560 root2 = copy.deepcopy(tree1.getroot()) 561 self.assertEqual(_bytes("<test/>"), 562 tostring(root2))563565 XML = self.etree.XML 566 tostring = self.etree.tostring 567 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>') 568 root = XML(xml) 569 tree1 = self.etree.ElementTree(root) 570 self.assertEqual(xml, tostring(tree1)) 571 572 tree2 = copy.deepcopy(tree1) 573 self.assertEqual(xml, tostring(tree2)) 574 575 root2 = copy.deepcopy(tree1.getroot()) 576 self.assertEqual(_bytes("<test/>"), 577 tostring(root2))578580 fromstring = self.etree.fromstring 581 tostring = self.etree.tostring 582 XMLParser = self.etree.XMLParser 583 584 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 585 parser = XMLParser(remove_comments=True) 586 root = fromstring(xml, parser) 587 self.assertEqual( 588 _bytes('<a><b><c/></b></a>'), 589 tostring(root))590592 parse = self.etree.parse 593 tostring = self.etree.tostring 594 XMLParser = self.etree.XMLParser 595 596 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>') 597 598 f = BytesIO(xml) 599 tree = parse(f) 600 self.assertEqual( 601 xml, 602 tostring(tree)) 603 604 parser = XMLParser(remove_pis=True) 605 tree = parse(f, parser) 606 self.assertEqual( 607 _bytes('<a><b><c/></b></a>'), 608 tostring(tree))609611 # ET raises IOError only 612 parse = self.etree.parse 613 self.assertRaises(TypeError, parse, 'notthere.xml', object())614616 # ET removes comments 617 iterparse = self.etree.iterparse 618 tostring = self.etree.tostring 619 620 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 621 events = list(iterparse(f)) 622 root = events[-1][1] 623 self.assertEqual(3, len(events)) 624 self.assertEqual( 625 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 626 tostring(root))627629 # ET removes comments 630 iterparse = self.etree.iterparse 631 tostring = self.etree.tostring 632 633 def name(event, el): 634 if event == 'comment': 635 return el.text 636 else: 637 return el.tag638 639 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 640 events = list(iterparse(f, events=('end', 'comment'))) 641 root = events[-1][1] 642 self.assertEqual(6, len(events)) 643 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'], 644 [ name(*item) for item in events ]) 645 self.assertEqual( 646 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 647 tostring(root))650 # ET removes pis 651 iterparse = self.etree.iterparse 652 tostring = self.etree.tostring 653 ElementTree = self.etree.ElementTree 654 655 def name(event, el): 656 if event == 'pi': 657 return (el.target, el.text) 658 else: 659 return el.tag660 661 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>') 662 events = list(iterparse(f, events=('end', 'pi'))) 663 root = events[-2][1] 664 self.assertEqual(8, len(events)) 665 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b', 666 ('pid','d'), 'a', ('pie','e')], 667 [ name(*item) for item in events ]) 668 self.assertEqual( 669 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'), 670 tostring(ElementTree(root))) 671673 iterparse = self.etree.iterparse 674 tostring = self.etree.tostring 675 676 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 677 events = list(iterparse(f, remove_comments=True, 678 events=('end', 'comment'))) 679 root = events[-1][1] 680 self.assertEqual(3, len(events)) 681 self.assertEqual(['c', 'b', 'a'], 682 [ el.tag for (event, el) in events ]) 683 self.assertEqual( 684 _bytes('<a><b><c/></b></a>'), 685 tostring(root))686688 iterparse = self.etree.iterparse 689 f = BytesIO('<a><b><c/></a>') 690 # ET raises ExpatError, lxml raises XMLSyntaxError 691 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))692694 iterparse = self.etree.iterparse 695 f = BytesIO('<a><b><c/></a>') 696 it = iterparse(f, events=('start', 'end'), recover=True) 697 events = [(ev, el.tag) for ev, el in it] 698 root = it.root 699 self.assertTrue(root is not None) 700 701 self.assertEqual(1, events.count(('start', 'a'))) 702 self.assertEqual(1, events.count(('end', 'a'))) 703 704 self.assertEqual(1, events.count(('start', 'b'))) 705 self.assertEqual(1, events.count(('end', 'b'))) 706 707 self.assertEqual(1, events.count(('start', 'c'))) 708 self.assertEqual(1, events.count(('end', 'c')))709711 iterparse = self.etree.iterparse 712 f = BytesIO('<a><b><c/></d><b><c/></a></b>') 713 it = iterparse(f, events=('start', 'end'), recover=True) 714 events = [(ev, el.tag) for ev, el in it] 715 root = it.root 716 self.assertTrue(root is not None) 717 718 self.assertEqual(1, events.count(('start', 'a'))) 719 self.assertEqual(1, events.count(('end', 'a'))) 720 721 self.assertEqual(2, events.count(('start', 'b'))) 722 self.assertEqual(2, events.count(('end', 'b'))) 723 724 self.assertEqual(2, events.count(('start', 'c'))) 725 self.assertEqual(2, events.count(('end', 'c')))726728 iterparse = self.etree.iterparse 729 f = BytesIO(""" 730 <a> \n \n <b> b test </b> \n 731 732 \n\t <c> \n </c> </a> \n """) 733 iterator = iterparse(f, remove_blank_text=True) 734 text = [ (element.text, element.tail) 735 for event, element in iterator ] 736 self.assertEqual( 737 [(" b test ", None), (" \n ", None), (None, None)], 738 text)739741 iterparse = self.etree.iterparse 742 f = BytesIO('<a><b><d/></b><c/></a>') 743 744 iterator = iterparse(f, tag="b", events=('start', 'end')) 745 events = list(iterator) 746 root = iterator.root 747 self.assertEqual( 748 [('start', root[0]), ('end', root[0])], 749 events)750752 iterparse = self.etree.iterparse 753 f = BytesIO('<a><b><d/></b><c/></a>') 754 755 iterator = iterparse(f, tag="*", events=('start', 'end')) 756 events = list(iterator) 757 self.assertEqual( 758 8, 759 len(events))760762 iterparse = self.etree.iterparse 763 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 764 765 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end')) 766 events = list(iterator) 767 root = iterator.root 768 self.assertEqual( 769 [('start', root[0]), ('end', root[0])], 770 events)771773 iterparse = self.etree.iterparse 774 f = BytesIO('<a><b><d/></b><c/></a>') 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 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 783 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 784 events = list(iterator) 785 root = iterator.root 786 self.assertEqual([], events)787789 iterparse = self.etree.iterparse 790 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 791 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end')) 792 events = list(iterator) 793 self.assertEqual(8, len(events))794796 iterparse = self.etree.iterparse 797 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 798 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 799 events = list(iterator) 800 self.assertEqual([], events) 801 802 f = BytesIO('<a><b><d/></b><c/></a>') 803 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 804 events = list(iterator) 805 self.assertEqual(8, len(events))806808 text = _str('Søk på nettet') 809 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 810 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 811 ).encode('iso-8859-1') 812 813 self.assertRaises(self.etree.ParseError, 814 list, self.etree.iterparse(BytesIO(xml_latin1)))815817 text = _str('Søk på nettet', encoding="UTF-8") 818 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 819 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 820 ).encode('iso-8859-1') 821 822 iterator = self.etree.iterparse(BytesIO(xml_latin1), 823 encoding="iso-8859-1") 824 self.assertEqual(1, len(list(iterator))) 825 826 a = iterator.root 827 self.assertEqual(a.text, text)828830 tostring = self.etree.tostring 831 f = BytesIO('<root><![CDATA[test]]></root>') 832 context = self.etree.iterparse(f, strip_cdata=False) 833 content = [ el.text for event,el in context ] 834 835 self.assertEqual(['test'], content) 836 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 837 tostring(context.root))838 842844 self.etree.XMLParser(encoding="ascii") 845 self.etree.XMLParser(encoding="utf-8") 846 self.etree.XMLParser(encoding="iso-8859-1")847849 parser = self.etree.XMLParser(recover=True) 850 851 parser.feed('<?xml version=') 852 parser.feed('"1.0"?><ro') 853 parser.feed('ot><') 854 parser.feed('a test="works"') 855 parser.feed('><othertag/></root') # <a> not closed! 856 parser.feed('>') 857 858 root = parser.close() 859 860 self.assertEqual(root.tag, "root") 861 self.assertEqual(len(root), 1) 862 self.assertEqual(root[0].tag, "a") 863 self.assertEqual(root[0].get("test"), "works") 864 self.assertEqual(len(root[0]), 1) 865 self.assertEqual(root[0][0].tag, "othertag")866 # FIXME: would be nice to get some errors logged ... 867 #self.assertTrue(len(parser.error_log) > 0, "error log is empty") 868870 # test that recover mode plays nicely with the no-id-dict setup 871 parser = self.etree.XMLParser(recover=True, collect_ids=False) 872 873 parser.feed('<?xml version=') 874 parser.feed('"1.0"?><ro') 875 parser.feed('ot xml:id="123"><') 876 parser.feed('a test="works" xml:id=') 877 parser.feed('"321"><othertag/></root') # <a> not closed! 878 parser.feed('>') 879 880 root = parser.close() 881 882 self.assertEqual(root.tag, "root") 883 self.assertEqual(len(root), 1) 884 self.assertEqual(root[0].tag, "a") 885 self.assertEqual(root[0].get("test"), "works") 886 self.assertEqual(root[0].attrib, { 887 'test': 'works', 888 '{http://www.w3.org/XML/1998/namespace}id': '321'}) 889 self.assertEqual(len(root[0]), 1) 890 self.assertEqual(root[0][0].tag, "othertag")891 # FIXME: would be nice to get some errors logged ... 892 #self.assertTrue(len(parser.error_log) > 0, "error log is empty") 893895 assertEqual = self.assertEqual 896 assertFalse = self.assertFalse 897 898 events = [] 899 class Target(object): 900 def start(self, tag, attrib): 901 events.append("start") 902 assertFalse(attrib) 903 assertEqual("TAG", tag)904 def end(self, tag): 905 events.append("end") 906 assertEqual("TAG", tag) 907 def close(self): 908 return "DONE" # no Element! 909 910 parser = self.etree.XMLParser(target=Target()) 911 tree = self.etree.ElementTree() 912 913 self.assertRaises(TypeError, 914 tree.parse, BytesIO("<TAG/>"), parser=parser) 915 self.assertEqual(["start", "end"], events) 916918 # ET doesn't call .close() on errors 919 events = [] 920 class Target(object): 921 def start(self, tag, attrib): 922 events.append("start-" + tag)923 def end(self, tag): 924 events.append("end-" + tag) 925 if tag == 'a': 926 raise ValueError("dead and gone") 927 def data(self, data): 928 events.append("data-" + data) 929 def close(self): 930 events.append("close") 931 return "DONE" 932 933 parser = self.etree.XMLParser(target=Target()) 934 935 try: 936 parser.feed(_bytes('<root>A<a>ca</a>B</root>')) 937 done = parser.close() 938 self.fail("error expected, but parsing succeeded") 939 except ValueError: 940 done = 'value error received as expected' 941 942 self.assertEqual(["start-root", "data-A", "start-a", 943 "data-ca", "end-a", "close"], 944 events) 945947 # ET doesn't call .close() on errors 948 events = [] 949 class Target(object): 950 def start(self, tag, attrib): 951 events.append("start-" + tag)952 def end(self, tag): 953 events.append("end-" + tag) 954 if tag == 'a': 955 raise ValueError("dead and gone") 956 def data(self, data): 957 events.append("data-" + data) 958 def close(self): 959 events.append("close") 960 return "DONE" 961 962 parser = self.etree.XMLParser(target=Target()) 963 964 try: 965 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'), 966 parser=parser) 967 self.fail("error expected, but parsing succeeded") 968 except ValueError: 969 done = 'value error received as expected' 970 971 self.assertEqual(["start-root", "data-A", "start-a", 972 "data-ca", "end-a", "close"], 973 events) 974976 # test that target parsing works nicely with the no-id-hash setup 977 events = [] 978 class Target(object): 979 def start(self, tag, attrib): 980 events.append("start-" + tag)981 def end(self, tag): 982 events.append("end-" + tag) 983 def data(self, data): 984 events.append("data-" + data) 985 def comment(self, text): 986 events.append("comment-" + text) 987 def close(self): 988 return "DONE" 989 990 parser = self.etree.XMLParser(target=Target(), collect_ids=False) 991 992 parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->')) 993 parser.feed(_bytes('<sub xml:id="321"/>B</root>')) 994 done = parser.close() 995 996 self.assertEqual("DONE", done) 997 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b", 998 "start-sub", "end-sub", "data-B", "end-root"], 999 events) 10001002 events = [] 1003 class Target(object): 1004 def start(self, tag, attrib): 1005 events.append("start-" + tag)1006 def end(self, tag): 1007 events.append("end-" + tag) 1008 def data(self, data): 1009 events.append("data-" + data) 1010 def comment(self, text): 1011 events.append("comment-" + text) 1012 def close(self): 1013 return "DONE" 1014 1015 parser = self.etree.XMLParser(target=Target()) 1016 1017 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->')) 1018 done = parser.close() 1019 1020 self.assertEqual("DONE", done) 1021 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b", 1022 "start-sub", "end-sub", "comment-c", "data-B", 1023 "end-root", "comment-d"], 1024 events) 10251027 events = [] 1028 class Target(object): 1029 def start(self, tag, attrib): 1030 events.append("start-" + tag)1031 def end(self, tag): 1032 events.append("end-" + tag) 1033 def data(self, data): 1034 events.append("data-" + data) 1035 def pi(self, target, data): 1036 events.append("pi-" + target + "-" + data) 1037 def close(self): 1038 return "DONE" 1039 1040 parser = self.etree.XMLParser(target=Target()) 1041 1042 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>')) 1043 done = parser.close() 1044 1045 self.assertEqual("DONE", done) 1046 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b", 1047 "data-B", "end-root", "pi-test-c"], 1048 events) 10491051 events = [] 1052 class Target(object): 1053 def start(self, tag, attrib): 1054 events.append("start-" + tag)1055 def end(self, tag): 1056 events.append("end-" + tag) 1057 def data(self, data): 1058 events.append("data-" + data) 1059 def close(self): 1060 return "DONE" 1061 1062 parser = self.etree.XMLParser(target=Target(), 1063 strip_cdata=False) 1064 1065 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>')) 1066 done = parser.close() 1067 1068 self.assertEqual("DONE", done) 1069 self.assertEqual(["start-root", "data-A", "start-a", 1070 "data-ca", "end-a", "data-B", "end-root"], 1071 events) 10721074 events = [] 1075 class Target(object): 1076 def start(self, tag, attrib): 1077 events.append("start-" + tag)1078 def end(self, tag): 1079 events.append("end-" + tag) 1080 def data(self, data): 1081 events.append("data-" + data) 1082 def close(self): 1083 events.append("close") 1084 return "DONE" 1085 1086 parser = self.etree.XMLParser(target=Target(), 1087 recover=True) 1088 1089 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>')) 1090 done = parser.close() 1091 1092 self.assertEqual("DONE", done) 1093 self.assertEqual(["start-root", "data-A", "start-a", 1094 "data-ca", "end-a", "data-B", 1095 "end-root", "close"], 1096 events) 10971099 iterwalk = self.etree.iterwalk 1100 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1101 1102 iterator = iterwalk(root, tag="b", events=('start', 'end')) 1103 events = list(iterator) 1104 self.assertEqual( 1105 [('start', root[0]), ('end', root[0])], 1106 events)11071109 iterwalk = self.etree.iterwalk 1110 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1111 1112 iterator = iterwalk(root, tag="*", events=('start', 'end')) 1113 events = list(iterator) 1114 self.assertEqual( 1115 8, 1116 len(events))11171119 iterwalk = self.etree.iterwalk 1120 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1121 1122 events = list(iterwalk(root)) 1123 self.assertEqual( 1124 [('end', root[0]), ('end', root[1]), ('end', root)], 1125 events)11261128 iterwalk = self.etree.iterwalk 1129 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1130 1131 iterator = iterwalk(root, events=('start',)) 1132 events = list(iterator) 1133 self.assertEqual( 1134 [('start', root), ('start', root[0]), ('start', root[1])], 1135 events)11361138 iterwalk = self.etree.iterwalk 1139 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1140 1141 iterator = iterwalk(root, events=('start','end')) 1142 events = list(iterator) 1143 self.assertEqual( 1144 [('start', root), ('start', root[0]), ('end', root[0]), 1145 ('start', root[1]), ('end', root[1]), ('end', root)], 1146 events)11471149 iterwalk = self.etree.iterwalk 1150 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1151 1152 iterator = iterwalk(root) 1153 for event, elem in iterator: 1154 elem.clear() 1155 1156 self.assertEqual(0, 1157 len(root))11581160 iterwalk = self.etree.iterwalk 1161 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>')) 1162 1163 attr_name = '{testns}bla' 1164 events = [] 1165 iterator = iterwalk(root, events=('start','end','start-ns','end-ns')) 1166 for event, elem in iterator: 1167 events.append(event) 1168 if event == 'start': 1169 if elem.tag != '{ns1}a': 1170 elem.set(attr_name, 'value') 1171 1172 self.assertEqual( 1173 ['start-ns', 'start', 'start', 'start-ns', 'start', 1174 'end', 'end-ns', 'end', 'end', 'end-ns'], 1175 events) 1176 1177 self.assertEqual( 1178 None, 1179 root.get(attr_name)) 1180 self.assertEqual( 1181 'value', 1182 root[0].get(attr_name))11831185 iterwalk = self.etree.iterwalk 1186 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1187 1188 counts = [] 1189 for event, elem in iterwalk(root): 1190 counts.append(len(list(elem.getiterator()))) 1191 self.assertEqual( 1192 [1,2,1,4], 1193 counts)11941196 parse = self.etree.parse 1197 parser = self.etree.XMLParser(dtd_validation=True) 1198 assertEqual = self.assertEqual 1199 test_url = _str("__nosuch.dtd") 1200 1201 class MyResolver(self.etree.Resolver): 1202 def resolve(self, url, id, context): 1203 assertEqual(url, test_url) 1204 return self.resolve_string( 1205 _str('''<!ENTITY myentity "%s"> 1206 <!ELEMENT doc ANY>''') % url, context)1207 1208 parser.resolvers.add(MyResolver()) 1209 1210 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1211 tree = parse(StringIO(xml), parser) 1212 root = tree.getroot() 1213 self.assertEqual(root.text, test_url) 12141216 parse = self.etree.parse 1217 parser = self.etree.XMLParser(dtd_validation=True) 1218 assertEqual = self.assertEqual 1219 test_url = _str("__nosuch.dtd") 1220 1221 class MyResolver(self.etree.Resolver): 1222 def resolve(self, url, id, context): 1223 assertEqual(url, test_url) 1224 return self.resolve_string( 1225 (_str('''<!ENTITY myentity "%s"> 1226 <!ELEMENT doc ANY>''') % url).encode('utf-8'), 1227 context)1228 1229 parser.resolvers.add(MyResolver()) 1230 1231 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1232 tree = parse(StringIO(xml), parser) 1233 root = tree.getroot() 1234 self.assertEqual(root.text, test_url) 12351237 parse = self.etree.parse 1238 parser = self.etree.XMLParser(dtd_validation=True) 1239 assertEqual = self.assertEqual 1240 test_url = _str("__nosuch.dtd") 1241 1242 class MyResolver(self.etree.Resolver): 1243 def resolve(self, url, id, context): 1244 assertEqual(url, test_url) 1245 return self.resolve_file( 1246 SillyFileLike( 1247 _str('''<!ENTITY myentity "%s"> 1248 <!ELEMENT doc ANY>''') % url), context)1249 1250 parser.resolvers.add(MyResolver()) 1251 1252 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1253 tree = parse(StringIO(xml), parser) 1254 root = tree.getroot() 1255 self.assertEqual(root.text, test_url) 12561258 parse = self.etree.parse 1259 parser = self.etree.XMLParser(attribute_defaults=True) 1260 assertEqual = self.assertEqual 1261 test_url = _str("__nosuch.dtd") 1262 1263 class MyResolver(self.etree.Resolver): 1264 def resolve(self, url, id, context): 1265 assertEqual(url, test_url) 1266 return self.resolve_filename( 1267 fileInTestDir('test.dtd'), context)1268 1269 parser.resolvers.add(MyResolver()) 1270 1271 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1272 tree = parse(StringIO(xml), parser) 1273 root = tree.getroot() 1274 self.assertEqual( 1275 root.attrib, {'default': 'valueA'}) 1276 self.assertEqual( 1277 root[0].attrib, {'default': 'valueB'}) 12781280 parse = self.etree.parse 1281 parser = self.etree.XMLParser(attribute_defaults=True) 1282 assertEqual = self.assertEqual 1283 test_url = _str("__nosuch.dtd") 1284 1285 class MyResolver(self.etree.Resolver): 1286 def resolve(self, url, id, context): 1287 expected = fileUrlInTestDir(test_url) 1288 url = url.replace('file://', 'file:') # depends on libxml2 version 1289 expected = expected.replace('file://', 'file:') 1290 assertEqual(url, expected) 1291 return self.resolve_filename( 1292 fileUrlInTestDir('test.dtd'), context)1293 1294 parser.resolvers.add(MyResolver()) 1295 1296 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1297 tree = parse(StringIO(xml), parser, 1298 base_url=fileUrlInTestDir('__test.xml')) 1299 root = tree.getroot() 1300 self.assertEqual( 1301 root.attrib, {'default': 'valueA'}) 1302 self.assertEqual( 1303 root[0].attrib, {'default': 'valueB'}) 13041306 parse = self.etree.parse 1307 parser = self.etree.XMLParser(attribute_defaults=True) 1308 assertEqual = self.assertEqual 1309 test_url = _str("__nosuch.dtd") 1310 1311 class MyResolver(self.etree.Resolver): 1312 def resolve(self, url, id, context): 1313 assertEqual(url, test_url) 1314 return self.resolve_file( 1315 open(fileInTestDir('test.dtd'), 'rb'), context)1316 1317 parser.resolvers.add(MyResolver()) 1318 1319 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1320 tree = parse(StringIO(xml), parser) 1321 root = tree.getroot() 1322 self.assertEqual( 1323 root.attrib, {'default': 'valueA'}) 1324 self.assertEqual( 1325 root[0].attrib, {'default': 'valueB'}) 13261328 parse = self.etree.parse 1329 parser = self.etree.XMLParser(load_dtd=True) 1330 assertEqual = self.assertEqual 1331 test_url = _str("__nosuch.dtd") 1332 1333 class check(object): 1334 resolved = False1335 1336 class MyResolver(self.etree.Resolver): 1337 def resolve(self, url, id, context): 1338 assertEqual(url, test_url) 1339 check.resolved = True 1340 return self.resolve_empty(context) 1341 1342 parser.resolvers.add(MyResolver()) 1343 1344 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1345 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser) 1346 self.assertTrue(check.resolved) 13471349 parse = self.etree.parse 1350 parser = self.etree.XMLParser(dtd_validation=True) 1351 1352 class _LocalException(Exception): 1353 pass1354 1355 class MyResolver(self.etree.Resolver): 1356 def resolve(self, url, id, context): 1357 raise _LocalException 1358 1359 parser.resolvers.add(MyResolver()) 1360 1361 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>' 1362 self.assertRaises(_LocalException, parse, BytesIO(xml), parser) 1363 1364 if etree.LIBXML_VERSION > (2,6,20):1366 parse = self.etree.parse 1367 tostring = self.etree.tostring 1368 parser = self.etree.XMLParser(resolve_entities=False) 1369 Entity = self.etree.Entity 1370 1371 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>') 1372 tree = parse(BytesIO(xml), parser) 1373 root = tree.getroot() 1374 self.assertEqual(root[0].tag, Entity) 1375 self.assertEqual(root[0].text, "&myentity;") 1376 self.assertEqual(root[0].tail, None) 1377 self.assertEqual(root[0].name, "myentity") 1378 1379 self.assertEqual(_bytes('<doc>&myentity;</doc>'), 1380 tostring(root))13811383 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]> 1384 <root> 1385 <child1/> 1386 <child2/> 1387 <child3> </child3> 1388 </root>''') 1389 1390 parser = self.etree.XMLParser(resolve_entities=False) 1391 root = etree.fromstring(xml, parser) 1392 self.assertEqual([ el.tag for el in root ], 1393 ['child1', 'child2', 'child3']) 1394 1395 root[0] = root[-1] 1396 self.assertEqual([ el.tag for el in root ], 1397 ['child3', 'child2']) 1398 self.assertEqual(root[0][0].text, ' ') 1399 self.assertEqual(root[0][0].name, 'nbsp')14001402 Entity = self.etree.Entity 1403 Element = self.etree.Element 1404 tostring = self.etree.tostring 1405 1406 root = Element("root") 1407 root.append( Entity("test") ) 1408 1409 self.assertEqual(root[0].tag, Entity) 1410 self.assertEqual(root[0].text, "&test;") 1411 self.assertEqual(root[0].tail, None) 1412 self.assertEqual(root[0].name, "test") 1413 1414 self.assertEqual(_bytes('<root>&test;</root>'), 1415 tostring(root))14161418 Entity = self.etree.Entity 1419 self.assertEqual(Entity("test").text, '&test;') 1420 self.assertEqual(Entity("#17683").text, '䔓') 1421 self.assertEqual(Entity("#x1768").text, 'ᝨ') 1422 self.assertEqual(Entity("#x98AF").text, '颯')14231425 Entity = self.etree.Entity 1426 self.assertRaises(ValueError, Entity, 'a b c') 1427 self.assertRaises(ValueError, Entity, 'a,b') 1428 self.assertRaises(ValueError, Entity, 'a\0b') 1429 self.assertRaises(ValueError, Entity, '#abc') 1430 self.assertRaises(ValueError, Entity, '#xxyz')14311433 CDATA = self.etree.CDATA 1434 Element = self.etree.Element 1435 tostring = self.etree.tostring 1436 1437 root = Element("root") 1438 root.text = CDATA('test') 1439 1440 self.assertEqual('test', 1441 root.text) 1442 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1443 tostring(root))14441446 CDATA = self.etree.CDATA 1447 Element = self.etree.Element 1448 SubElement = self.etree.SubElement 1449 tostring = self.etree.tostring 1450 1451 root = Element("root") 1452 child = SubElement(root, 'child') 1453 child.tail = CDATA('test') 1454 1455 self.assertEqual('test', child.tail) 1456 self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'), 1457 tostring(root)) 1458 1459 root = Element("root") 1460 root.tail = CDATA('test') 1461 1462 self.assertEqual('test', root.tail) 1463 self.assertEqual(_bytes('<root/><![CDATA[test]]>'), 1464 tostring(root))14651467 CDATA = self.etree.CDATA 1468 Element = self.etree.Element 1469 root = Element("root") 1470 1471 root.text = CDATA("test") 1472 self.assertEqual('test', root.text) 1473 1474 root.text = CDATA(_str("test")) 1475 self.assertEqual('test', root.text) 1476 1477 self.assertRaises(TypeError, CDATA, 1)14781480 CDATA = self.etree.CDATA 1481 Element = self.etree.Element 1482 1483 root = Element("root") 1484 cdata = CDATA('test') 1485 1486 self.assertRaises(TypeError, 1487 root.set, 'attr', cdata) 1488 self.assertRaises(TypeError, 1489 operator.setitem, root.attrib, 'attr', cdata)14901492 tostring = self.etree.tostring 1493 parser = self.etree.XMLParser(strip_cdata=False) 1494 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1495 1496 self.assertEqual('test', root.text) 1497 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1498 tostring(root))14991501 tostring = self.etree.tostring 1502 parser = self.etree.XMLParser(strip_cdata=False) 1503 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1504 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1505 tostring(root)) 1506 1507 self.assertEqual(['test'], root.xpath('//text()'))1508 1509 # TypeError in etree, AssertionError in ElementTree;1511 Element = self.etree.Element 1512 SubElement = self.etree.SubElement 1513 1514 a = Element('a') 1515 b = SubElement(a, 'b') 1516 1517 self.assertRaises(TypeError, 1518 a.__setitem__, 0, 'foo')15191521 Element = self.etree.Element 1522 root = Element('root') 1523 # raises AssertionError in ElementTree 1524 self.assertRaises(TypeError, root.append, None) 1525 self.assertRaises(TypeError, root.extend, [None]) 1526 self.assertRaises(TypeError, root.extend, [Element('one'), None]) 1527 self.assertEqual('one', root[0].tag)15281530 Element = self.etree.Element 1531 SubElement = self.etree.SubElement 1532 root = Element('root') 1533 self.assertRaises(ValueError, root.append, root) 1534 child = SubElement(root, 'child') 1535 self.assertRaises(ValueError, child.append, root) 1536 child2 = SubElement(child, 'child2') 1537 self.assertRaises(ValueError, child2.append, root) 1538 self.assertRaises(ValueError, child2.append, child) 1539 self.assertEqual('child2', root[0][0].tag)15401542 Element = self.etree.Element 1543 SubElement = self.etree.SubElement 1544 root = Element('root') 1545 SubElement(root, 'a') 1546 SubElement(root, 'b') 1547 1548 self.assertEqual(['a', 'b'], 1549 [c.tag for c in root]) 1550 root[1].addnext(root[0]) 1551 self.assertEqual(['b', 'a'], 1552 [c.tag for c in root])15531555 Element = self.etree.Element 1556 SubElement = self.etree.SubElement 1557 root = Element('root') 1558 SubElement(root, 'a') 1559 SubElement(root, 'b') 1560 1561 self.assertEqual(['a', 'b'], 1562 [c.tag for c in root]) 1563 root[0].addprevious(root[1]) 1564 self.assertEqual(['b', 'a'], 1565 [c.tag for c in root])15661568 Element = self.etree.Element 1569 SubElement = self.etree.SubElement 1570 root = Element('root') 1571 a = SubElement(root, 'a') 1572 b = SubElement(a, 'b') 1573 # appending parent as sibling is forbidden 1574 self.assertRaises(ValueError, b.addnext, a) 1575 self.assertEqual(['a'], [c.tag for c in root]) 1576 self.assertEqual(['b'], [c.tag for c in a])15771579 Element = self.etree.Element 1580 SubElement = self.etree.SubElement 1581 root = Element('root') 1582 a = SubElement(root, 'a') 1583 b = SubElement(a, 'b') 1584 # appending parent as sibling is forbidden 1585 self.assertRaises(ValueError, b.addprevious, a) 1586 self.assertEqual(['a'], [c.tag for c in root]) 1587 self.assertEqual(['b'], [c.tag for c in a])15881590 Element = self.etree.Element 1591 SubElement = self.etree.SubElement 1592 root = Element('root') 1593 a = SubElement(root, 'a') 1594 b = SubElement(a, 'b') 1595 c = SubElement(b, 'c') 1596 # appending parent as sibling is forbidden 1597 self.assertRaises(ValueError, c.addnext, a)15981600 Element = self.etree.Element 1601 SubElement = self.etree.SubElement 1602 root = Element('root') 1603 a = SubElement(root, 'a') 1604 b = SubElement(a, 'b') 1605 c = SubElement(b, 'c') 1606 # appending parent as sibling is forbidden 1607 self.assertRaises(ValueError, c.addprevious, a)16081610 Element = self.etree.Element 1611 SubElement = self.etree.SubElement 1612 root = Element('root') 1613 a = SubElement(root, 'a') 1614 b = SubElement(root, 'b') 1615 a.addprevious(a) 1616 self.assertEqual('a', root[0].tag) 1617 self.assertEqual('b', root[1].tag) 1618 b.addprevious(b) 1619 self.assertEqual('a', root[0].tag) 1620 self.assertEqual('b', root[1].tag) 1621 b.addprevious(a) 1622 self.assertEqual('a', root[0].tag) 1623 self.assertEqual('b', root[1].tag)16241626 Element = self.etree.Element 1627 SubElement = self.etree.SubElement 1628 root = Element('root') 1629 a = SubElement(root, 'a') 1630 b = SubElement(root, 'b') 1631 a.addnext(a) 1632 self.assertEqual('a', root[0].tag) 1633 self.assertEqual('b', root[1].tag) 1634 b.addnext(b) 1635 self.assertEqual('a', root[0].tag) 1636 self.assertEqual('b', root[1].tag) 1637 a.addnext(b) 1638 self.assertEqual('a', root[0].tag) 1639 self.assertEqual('b', root[1].tag)16401642 Element = self.etree.Element 1643 a = Element('a') 1644 b = Element('b') 1645 self.assertRaises(TypeError, a.addnext, b)16461648 Element = self.etree.Element 1649 SubElement = self.etree.SubElement 1650 PI = self.etree.PI 1651 root = Element('root') 1652 SubElement(root, 'a') 1653 pi = PI('TARGET', 'TEXT') 1654 pi.tail = "TAIL" 1655 1656 self.assertEqual(_bytes('<root><a></a></root>'), 1657 self._writeElement(root)) 1658 root[0].addprevious(pi) 1659 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'), 1660 self._writeElement(root))16611663 Element = self.etree.Element 1664 PI = self.etree.PI 1665 root = Element('root') 1666 pi = PI('TARGET', 'TEXT') 1667 pi.tail = "TAIL" 1668 1669 self.assertEqual(_bytes('<root></root>'), 1670 self._writeElement(root)) 1671 root.addprevious(pi) 1672 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'), 1673 self._writeElement(root))16741676 Element = self.etree.Element 1677 SubElement = self.etree.SubElement 1678 PI = self.etree.PI 1679 root = Element('root') 1680 SubElement(root, 'a') 1681 pi = PI('TARGET', 'TEXT') 1682 pi.tail = "TAIL" 1683 1684 self.assertEqual(_bytes('<root><a></a></root>'), 1685 self._writeElement(root)) 1686 root[0].addnext(pi) 1687 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'), 1688 self._writeElement(root))16891691 Element = self.etree.Element 1692 PI = self.etree.PI 1693 root = Element('root') 1694 pi = PI('TARGET', 'TEXT') 1695 pi.tail = "TAIL" 1696 1697 self.assertEqual(_bytes('<root></root>'), 1698 self._writeElement(root)) 1699 root.addnext(pi) 1700 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'), 1701 self._writeElement(root))17021704 Element = self.etree.Element 1705 SubElement = self.etree.SubElement 1706 Comment = self.etree.Comment 1707 root = Element('root') 1708 SubElement(root, 'a') 1709 comment = Comment('TEXT ') 1710 comment.tail = "TAIL" 1711 1712 self.assertEqual(_bytes('<root><a></a></root>'), 1713 self._writeElement(root)) 1714 root[0].addnext(comment) 1715 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'), 1716 self._writeElement(root))17171719 Element = self.etree.Element 1720 Comment = self.etree.Comment 1721 root = Element('root') 1722 comment = Comment('TEXT ') 1723 comment.tail = "TAIL" 1724 1725 self.assertEqual(_bytes('<root></root>'), 1726 self._writeElement(root)) 1727 root.addnext(comment) 1728 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'), 1729 self._writeElement(root))17301732 Element = self.etree.Element 1733 SubElement = self.etree.SubElement 1734 Comment = self.etree.Comment 1735 root = Element('root') 1736 SubElement(root, 'a') 1737 comment = Comment('TEXT ') 1738 comment.tail = "TAIL" 1739 1740 self.assertEqual(_bytes('<root><a></a></root>'), 1741 self._writeElement(root)) 1742 root[0].addprevious(comment) 1743 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'), 1744 self._writeElement(root))17451747 Element = self.etree.Element 1748 Comment = self.etree.Comment 1749 root = Element('root') 1750 comment = Comment('TEXT ') 1751 comment.tail = "TAIL" 1752 1753 self.assertEqual(_bytes('<root></root>'), 1754 self._writeElement(root)) 1755 root.addprevious(comment) 1756 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'), 1757 self._writeElement(root))1758 1759 # ET's Elements have items() and key(), but not values()1761 XML = self.etree.XML 1762 1763 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>')) 1764 values = root.values() 1765 values.sort() 1766 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)1767 1768 # gives error in ElementTree1770 Element = self.etree.Element 1771 Comment = self.etree.Comment 1772 1773 a = Element('a') 1774 a.append(Comment()) 1775 self.assertEqual( 1776 _bytes('<a><!----></a>'), 1777 self._writeElement(a))1778 1779 # ElementTree ignores comments1781 ElementTree = self.etree.ElementTree 1782 tostring = self.etree.tostring 1783 1784 xml = _bytes('<a><b/><!----><c/></a>') 1785 f = BytesIO(xml) 1786 doc = ElementTree(file=f) 1787 a = doc.getroot() 1788 self.assertEqual( 1789 '', 1790 a[1].text) 1791 self.assertEqual( 1792 xml, 1793 tostring(a))1794 1795 # ElementTree ignores comments1797 ElementTree = self.etree.ElementTree 1798 1799 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>') 1800 doc = ElementTree(file=f) 1801 a = doc.getroot() 1802 self.assertEqual( 1803 ' hoi ', 1804 a[1].text)1805 1806 # does not raise an exception in ElementTree1808 Element = self.etree.Element 1809 Comment = self.etree.Comment 1810 1811 c = Comment() 1812 el = Element('myel') 1813 1814 self.assertRaises(TypeError, c.append, el) 1815 self.assertRaises(TypeError, c.insert, 0, el) 1816 self.assertRaises(TypeError, c.set, "myattr", "test")18171819 c = self.etree.Comment() 1820 self.assertEqual(0, len(c.attrib)) 1821 1822 self.assertFalse(c.attrib.__contains__('nope')) 1823 self.assertFalse('nope' in c.attrib) 1824 self.assertFalse('nope' in c.attrib.keys()) 1825 self.assertFalse('nope' in c.attrib.values()) 1826 self.assertFalse(('nope', 'huhu') in c.attrib.items()) 1827 1828 self.assertEqual([], list(c.attrib)) 1829 self.assertEqual([], list(c.attrib.keys())) 1830 self.assertEqual([], list(c.attrib.items())) 1831 self.assertEqual([], list(c.attrib.values())) 1832 self.assertEqual([], list(c.attrib.iterkeys())) 1833 self.assertEqual([], list(c.attrib.iteritems())) 1834 self.assertEqual([], list(c.attrib.itervalues())) 1835 1836 self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU')) 1837 self.assertRaises(KeyError, c.attrib.pop, 'nope') 1838 1839 self.assertRaises(KeyError, c.attrib.__getitem__, 'only') 1840 self.assertRaises(KeyError, c