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 zlib 19 import gzip 20 21 this_dir = os.path.dirname(__file__) 22 if this_dir not in sys.path: 23 sys.path.insert(0, this_dir) # needed for Py3 24 25 from common_imports import etree, StringIO, BytesIO, HelperTestCase, fileInTestDir, read_file 26 from common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest 27 from common_imports import canonicalize, sorted, _str, _bytes 28 29 print("") 30 print("TESTED VERSION: %s" % etree.__version__) 31 print(" Python: " + repr(sys.version_info)) 32 print(" lxml.etree: " + repr(etree.LXML_VERSION)) 33 print(" libxml used: " + repr(etree.LIBXML_VERSION)) 34 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION)) 35 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION)) 36 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION)) 37 print("") 38 39 try: 40 _unicode = unicode 41 except NameError: 42 # Python 3 43 _unicode = str 4446 """Tests only for etree, not ElementTree""" 47 etree = etree 4861150 self.assertTrue(isinstance(etree.__version__, _unicode)) 51 self.assertTrue(isinstance(etree.LXML_VERSION, tuple)) 52 self.assertEqual(len(etree.LXML_VERSION), 4) 53 self.assertTrue(isinstance(etree.LXML_VERSION[0], int)) 54 self.assertTrue(isinstance(etree.LXML_VERSION[1], int)) 55 self.assertTrue(isinstance(etree.LXML_VERSION[2], int)) 56 self.assertTrue(isinstance(etree.LXML_VERSION[3], int)) 57 self.assertTrue(etree.__version__.startswith( 58 str(etree.LXML_VERSION[0])))5961 if hasattr(self.etree, '__pyx_capi__'): 62 # newer Pyrex compatible C-API 63 self.assertTrue(isinstance(self.etree.__pyx_capi__, dict)) 64 self.assertTrue(len(self.etree.__pyx_capi__) > 0) 65 else: 66 # older C-API mechanism 67 self.assertTrue(hasattr(self.etree, '_import_c_api'))6870 Element = self.etree.Element 71 el = Element('name') 72 self.assertEqual(el.tag, 'name') 73 el = Element('{}name') 74 self.assertEqual(el.tag, 'name')7577 Element = self.etree.Element 78 el = Element('name') 79 self.assertRaises(ValueError, Element, '{}') 80 self.assertRaises(ValueError, setattr, el, 'tag', '{}') 81 82 self.assertRaises(ValueError, Element, '{test}') 83 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')8486 Element = self.etree.Element 87 self.assertRaises(ValueError, Element, 'p:name') 88 self.assertRaises(ValueError, Element, '{test}p:name') 89 90 el = Element('name') 91 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')9294 Element = self.etree.Element 95 self.assertRaises(ValueError, Element, "p'name") 96 self.assertRaises(ValueError, Element, 'p"name') 97 98 self.assertRaises(ValueError, Element, "{test}p'name") 99 self.assertRaises(ValueError, Element, '{test}p"name') 100 101 el = Element('name') 102 self.assertRaises(ValueError, setattr, el, 'tag', "p'name") 103 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')104106 Element = self.etree.Element 107 self.assertRaises(ValueError, Element, ' name ') 108 self.assertRaises(ValueError, Element, 'na me') 109 self.assertRaises(ValueError, Element, '{test} name') 110 111 el = Element('name') 112 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')113115 Element = self.etree.Element 116 SubElement = self.etree.SubElement 117 118 el = Element('name') 119 self.assertRaises(ValueError, SubElement, el, '{}') 120 self.assertRaises(ValueError, SubElement, el, '{test}')121123 Element = self.etree.Element 124 SubElement = self.etree.SubElement 125 126 el = Element('name') 127 self.assertRaises(ValueError, SubElement, el, 'p:name') 128 self.assertRaises(ValueError, SubElement, el, '{test}p:name')129131 Element = self.etree.Element 132 SubElement = self.etree.SubElement 133 134 el = Element('name') 135 self.assertRaises(ValueError, SubElement, el, "p'name") 136 self.assertRaises(ValueError, SubElement, el, "{test}p'name") 137 138 self.assertRaises(ValueError, SubElement, el, 'p"name') 139 self.assertRaises(ValueError, SubElement, el, '{test}p"name')140142 Element = self.etree.Element 143 SubElement = self.etree.SubElement 144 145 el = Element('name') 146 self.assertRaises(ValueError, SubElement, el, ' name ') 147 self.assertRaises(ValueError, SubElement, el, 'na me') 148 self.assertRaises(ValueError, SubElement, el, '{test} name')149151 Element = self.etree.Element 152 SubElement = self.etree.SubElement 153 154 el = Element('name') 155 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'}) 156 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'}) 157 self.assertEqual(0, len(el))158160 QName = self.etree.QName 161 self.assertRaises(ValueError, QName, '') 162 self.assertRaises(ValueError, QName, 'test', '')163165 QName = self.etree.QName 166 self.assertRaises(ValueError, QName, 'p:name') 167 self.assertRaises(ValueError, QName, 'test', 'p:name')168170 QName = self.etree.QName 171 self.assertRaises(ValueError, QName, ' name ') 172 self.assertRaises(ValueError, QName, 'na me') 173 self.assertRaises(ValueError, QName, 'test', ' name')174176 # ET doesn't have namespace/localname properties on QNames 177 QName = self.etree.QName 178 namespace, localname = 'http://myns', 'a' 179 qname = QName(namespace, localname) 180 self.assertEqual(namespace, qname.namespace) 181 self.assertEqual(localname, qname.localname)182184 # ET doesn't have namespace/localname properties on QNames 185 QName = self.etree.QName 186 qname1 = QName('http://myns', 'a') 187 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'}) 188 189 qname2 = QName(a) 190 self.assertEqual(a.tag, qname1.text) 191 self.assertEqual(qname1.text, qname2.text) 192 self.assertEqual(qname1, qname2)193195 # ET doesn't resove QNames as text values 196 etree = self.etree 197 qname = etree.QName('http://myns', 'a') 198 a = etree.Element(qname, nsmap={'p' : 'http://myns'}) 199 a.text = qname 200 201 self.assertEqual("p:a", a.text)202204 etree = self.etree 205 self.assertRaises(ValueError, 206 etree.Element, "root", nsmap={'"' : 'testns'}) 207 self.assertRaises(ValueError, 208 etree.Element, "root", nsmap={'&' : 'testns'}) 209 self.assertRaises(ValueError, 210 etree.Element, "root", nsmap={'a:b' : 'testns'})211213 # ET in Py 3.x has no "attrib.has_key()" method 214 XML = self.etree.XML 215 216 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />')) 217 self.assertEqual( 218 True, root.attrib.has_key('bar')) 219 self.assertEqual( 220 False, root.attrib.has_key('baz')) 221 self.assertEqual( 222 False, root.attrib.has_key('hah')) 223 self.assertEqual( 224 True, 225 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))226228 Element = self.etree.Element 229 root = Element("root") 230 root.set("attr", "TEST") 231 self.assertEqual("TEST", root.get("attr"))232234 # ElementTree accepts arbitrary attribute values 235 # lxml.etree allows only strings 236 Element = self.etree.Element 237 root = Element("root") 238 self.assertRaises(TypeError, root.set, "newattr", 5) 239 self.assertRaises(TypeError, root.set, "newattr", None)240242 XML = self.etree.XML 243 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>') 244 245 root = XML(xml) 246 self.etree.strip_attributes(root, 'a') 247 self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'), 248 self._writeElement(root)) 249 250 root = XML(xml) 251 self.etree.strip_attributes(root, 'b', 'c') 252 self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'), 253 self._writeElement(root))254256 XML = self.etree.XML 257 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>') 258 259 root = XML(xml) 260 self.etree.strip_attributes(root, 'a') 261 self.assertEqual( 262 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'), 263 self._writeElement(root)) 264 265 root = XML(xml) 266 self.etree.strip_attributes(root, '{http://test/ns}a', 'c') 267 self.assertEqual( 268 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'), 269 self._writeElement(root)) 270 271 root = XML(xml) 272 self.etree.strip_attributes(root, '{http://test/ns}*') 273 self.assertEqual( 274 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'), 275 self._writeElement(root))276278 XML = self.etree.XML 279 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>') 280 281 root = XML(xml) 282 self.etree.strip_elements(root, 'a') 283 self.assertEqual(_bytes('<test><x></x></test>'), 284 self._writeElement(root)) 285 286 root = XML(xml) 287 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z') 288 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'), 289 self._writeElement(root)) 290 291 root = XML(xml) 292 self.etree.strip_elements(root, 'c') 293 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'), 294 self._writeElement(root))295297 XML = self.etree.XML 298 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>') 299 300 root = XML(xml) 301 self.etree.strip_elements(root, 'a') 302 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>'), 303 self._writeElement(root)) 304 305 root = XML(xml) 306 self.etree.strip_elements(root, '{urn:a}b', 'c') 307 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>'), 308 self._writeElement(root)) 309 310 root = XML(xml) 311 self.etree.strip_elements(root, '{urn:a}*', 'c') 312 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 313 self._writeElement(root)) 314 315 root = XML(xml) 316 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False) 317 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 318 self._writeElement(root))319 338 364 391 418 437 450452 # lxml.etree separates target and text 453 Element = self.etree.Element 454 SubElement = self.etree.SubElement 455 ProcessingInstruction = self.etree.ProcessingInstruction 456 457 a = Element('a') 458 a.append(ProcessingInstruction('foo', 'some more text')) 459 self.assertEqual(a[0].target, 'foo') 460 self.assertEqual(a[0].text, 'some more text')461463 XML = self.etree.XML 464 root = XML(_bytes("<test><?mypi my test ?></test>")) 465 self.assertEqual(root[0].target, "mypi") 466 self.assertEqual(root[0].text, "my test ")467469 XML = self.etree.XML 470 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 471 self.assertEqual(root[0].target, "mypi") 472 self.assertEqual(root[0].get('my'), "1") 473 self.assertEqual(root[0].get('test'), " abc ") 474 self.assertEqual(root[0].get('quotes'), "' '") 475 self.assertEqual(root[0].get('only'), None) 476 self.assertEqual(root[0].get('names'), None) 477 self.assertEqual(root[0].get('nope'), None)478480 XML = self.etree.XML 481 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 482 self.assertEqual(root[0].target, "mypi") 483 self.assertEqual(root[0].attrib['my'], "1") 484 self.assertEqual(root[0].attrib['test'], " abc ") 485 self.assertEqual(root[0].attrib['quotes'], "' '") 486 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only') 487 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names') 488 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')489491 # previously caused a crash 492 ProcessingInstruction = self.etree.ProcessingInstruction 493 494 a = ProcessingInstruction("PI", "ONE") 495 b = copy.deepcopy(a) 496 b.text = "ANOTHER" 497 498 self.assertEqual('ONE', a.text) 499 self.assertEqual('ANOTHER', b.text)500502 XML = self.etree.XML 503 tostring = self.etree.tostring 504 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->")) 505 tree1 = self.etree.ElementTree(root) 506 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 507 tostring(tree1)) 508 509 tree2 = copy.deepcopy(tree1) 510 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 511 tostring(tree2)) 512 513 root2 = copy.deepcopy(tree1.getroot()) 514 self.assertEqual(_bytes("<test/>"), 515 tostring(root2))516518 XML = self.etree.XML 519 tostring = self.etree.tostring 520 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>') 521 root = XML(xml) 522 tree1 = self.etree.ElementTree(root) 523 self.assertEqual(xml, tostring(tree1)) 524 525 tree2 = copy.deepcopy(tree1) 526 self.assertEqual(xml, tostring(tree2)) 527 528 root2 = copy.deepcopy(tree1.getroot()) 529 self.assertEqual(_bytes("<test/>"), 530 tostring(root2))531533 # ElementTree accepts arbitrary attribute values 534 # lxml.etree allows only strings 535 Element = self.etree.Element 536 537 root = Element("root") 538 root.set("attr", "TEST") 539 self.assertEqual("TEST", root.get("attr")) 540 self.assertRaises(TypeError, root.set, "newattr", 5)541543 fromstring = self.etree.fromstring 544 tostring = self.etree.tostring 545 XMLParser = self.etree.XMLParser 546 547 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 548 parser = XMLParser(remove_comments=True) 549 root = fromstring(xml, parser) 550 self.assertEqual( 551 _bytes('<a><b><c/></b></a>'), 552 tostring(root))553555 parse = self.etree.parse 556 tostring = self.etree.tostring 557 XMLParser = self.etree.XMLParser 558 559 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>') 560 561 f = BytesIO(xml) 562 tree = parse(f) 563 self.assertEqual( 564 xml, 565 tostring(tree)) 566 567 parser = XMLParser(remove_pis=True) 568 tree = parse(f, parser) 569 self.assertEqual( 570 _bytes('<a><b><c/></b></a>'), 571 tostring(tree))572574 # ET raises IOError only 575 parse = self.etree.parse 576 self.assertRaises(TypeError, parse, 'notthere.xml', object())577579 # ET removes comments 580 iterparse = self.etree.iterparse 581 tostring = self.etree.tostring 582 583 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 584 events = list(iterparse(f)) 585 root = events[-1][1] 586 self.assertEqual(3, len(events)) 587 self.assertEqual( 588 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 589 tostring(root))590592 # ET removes comments 593 iterparse = self.etree.iterparse 594 tostring = self.etree.tostring 595 596 def name(event, el): 597 if event == 'comment': 598 return el.text 599 else: 600 return el.tag601 602 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 603 events = list(iterparse(f, events=('end', 'comment'))) 604 root = events[-1][1] 605 self.assertEqual(6, len(events)) 606 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'], 607 [ name(*item) for item in events ]) 608 self.assertEqual( 609 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 610 tostring(root))613 # ET removes pis 614 iterparse = self.etree.iterparse 615 tostring = self.etree.tostring 616 ElementTree = self.etree.ElementTree 617 618 def name(event, el): 619 if event == 'pi': 620 return (el.target, el.text) 621 else: 622 return el.tag623 624 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>') 625 events = list(iterparse(f, events=('end', 'pi'))) 626 root = events[-2][1] 627 self.assertEqual(8, len(events)) 628 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b', 629 ('pid','d'), 'a', ('pie','e')], 630 [ name(*item) for item in events ]) 631 self.assertEqual( 632 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'), 633 tostring(ElementTree(root))) 634636 iterparse = self.etree.iterparse 637 tostring = self.etree.tostring 638 639 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 640 events = list(iterparse(f, remove_comments=True, 641 events=('end', 'comment'))) 642 root = events[-1][1] 643 self.assertEqual(3, len(events)) 644 self.assertEqual(['c', 'b', 'a'], 645 [ el.tag for (event, el) in events ]) 646 self.assertEqual( 647 _bytes('<a><b><c/></b></a>'), 648 tostring(root))649651 iterparse = self.etree.iterparse 652 f = BytesIO('<a><b><c/></a>') 653 # ET raises ExpatError, lxml raises XMLSyntaxError 654 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))655657 iterparse = self.etree.iterparse 658 f = BytesIO(""" 659 <a> \n \n <b> b test </b> \n 660 661 \n\t <c> \n </c> </a> \n """) 662 iterator = iterparse(f, remove_blank_text=True) 663 text = [ (element.text, element.tail) 664 for event, element in iterator ] 665 self.assertEqual( 666 [(" b test ", None), (" \n ", None), (None, None)], 667 text)668670 iterparse = self.etree.iterparse 671 f = BytesIO('<a><b><d/></b><c/></a>') 672 673 iterator = iterparse(f, tag="b", events=('start', 'end')) 674 events = list(iterator) 675 root = iterator.root 676 self.assertEqual( 677 [('start', root[0]), ('end', root[0])], 678 events)679681 iterparse = self.etree.iterparse 682 f = BytesIO('<a><b><d/></b><c/></a>') 683 684 iterator = iterparse(f, tag="*", events=('start', 'end')) 685 events = list(iterator) 686 self.assertEqual( 687 8, 688 len(events))689691 iterparse = self.etree.iterparse 692 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 693 694 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end')) 695 events = list(iterator) 696 root = iterator.root 697 self.assertEqual( 698 [('start', root[0]), ('end', root[0])], 699 events)700702 iterparse = self.etree.iterparse 703 f = BytesIO('<a><b><d/></b><c/></a>') 704 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 705 events = list(iterator) 706 root = iterator.root 707 self.assertEqual( 708 [('start', root[0]), ('end', root[0])], 709 events) 710 711 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 712 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 713 events = list(iterator) 714 root = iterator.root 715 self.assertEqual([], events)716718 iterparse = self.etree.iterparse 719 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 720 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end')) 721 events = list(iterator) 722 self.assertEqual(8, len(events))723725 iterparse = self.etree.iterparse 726 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 727 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 728 events = list(iterator) 729 self.assertEqual([], events) 730 731 f = BytesIO('<a><b><d/></b><c/></a>') 732 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 733 events = list(iterator) 734 self.assertEqual(8, len(events))735737 text = _str('Søk på nettet') 738 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 739 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 740 ).encode('iso-8859-1') 741 742 self.assertRaises(self.etree.ParseError, 743 list, self.etree.iterparse(BytesIO(xml_latin1)))744746 text = _str('Søk på nettet', encoding="UTF-8") 747 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 748 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 749 ).encode('iso-8859-1') 750 751 iterator = self.etree.iterparse(BytesIO(xml_latin1), 752 encoding="iso-8859-1") 753 self.assertEqual(1, len(list(iterator))) 754 755 a = iterator.root 756 self.assertEqual(a.text, text)757759 tostring = self.etree.tostring 760 f = BytesIO('<root><![CDATA[test]]></root>') 761 context = self.etree.iterparse(f, strip_cdata=False) 762 content = [ el.text for event,el in context ] 763 764 self.assertEqual(['test'], content) 765 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 766 tostring(context.root))767 771773 self.etree.XMLParser(encoding="ascii") 774 self.etree.XMLParser(encoding="utf-8") 775 self.etree.XMLParser(encoding="iso-8859-1")776778 parser = self.etree.XMLParser(recover=True) 779 780 parser.feed('<?xml version=') 781 parser.feed('"1.0"?><ro') 782 parser.feed('ot><') 783 parser.feed('a test="works"') 784 parser.feed('><othertag/></root') # <a> not closed! 785 parser.feed('>') 786 787 root = parser.close() 788 789 self.assertEqual(root.tag, "root") 790 self.assertEqual(len(root), 1) 791 self.assertEqual(root[0].tag, "a") 792 self.assertEqual(root[0].get("test"), "works") 793 self.assertEqual(len(root[0]), 1) 794 self.assertEqual(root[0][0].tag, "othertag")795 # FIXME: would be nice to get some errors logged ... 796 #self.assertTrue(len(parser.error_log) > 0, "error log is empty") 797799 assertEqual = self.assertEqual 800 assertFalse = self.assertFalse 801 802 events = [] 803 class Target(object): 804 def start(self, tag, attrib): 805 events.append("start") 806 assertFalse(attrib) 807 assertEqual("TAG", tag)808 def end(self, tag): 809 events.append("end") 810 assertEqual("TAG", tag) 811 def close(self): 812 return "DONE" # no Element! 813 814 parser = self.etree.XMLParser(target=Target()) 815 tree = self.etree.ElementTree() 816 817 self.assertRaises(TypeError, 818 tree.parse, BytesIO("<TAG/>"), parser=parser) 819 self.assertEqual(["start", "end"], events) 820822 # ET doesn't call .close() on errors 823 events = [] 824 class Target(object): 825 def start(self, tag, attrib): 826 events.append("start-" + tag)827 def end(self, tag): 828 events.append("end-" + tag) 829 if tag == 'a': 830 raise ValueError("dead and gone") 831 def data(self, data): 832 events.append("data-" + data) 833 def close(self): 834 events.append("close") 835 return "DONE" 836 837 parser = self.etree.XMLParser(target=Target()) 838 839 try: 840 parser.feed(_bytes('<root>A<a>ca</a>B</root>')) 841 done = parser.close() 842 self.fail("error expected, but parsing succeeded") 843 except ValueError: 844 done = 'value error received as expected' 845 846 self.assertEqual(["start-root", "data-A", "start-a", 847 "data-ca", "end-a", "close"], 848 events) 849851 # ET doesn't call .close() on errors 852 events = [] 853 class Target(object): 854 def start(self, tag, attrib): 855 events.append("start-" + tag)856 def end(self, tag): 857 events.append("end-" + tag) 858 if tag == 'a': 859 raise ValueError("dead and gone") 860 def data(self, data): 861 events.append("data-" + data) 862 def close(self): 863 events.append("close") 864 return "DONE" 865 866 parser = self.etree.XMLParser(target=Target()) 867 868 try: 869 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'), 870 parser=parser) 871 self.fail("error expected, but parsing succeeded") 872 except ValueError: 873 done = 'value error received as expected' 874 875 self.assertEqual(["start-root", "data-A", "start-a", 876 "data-ca", "end-a", "close"], 877 events) 878880 events = [] 881 class Target(object): 882 def start(self, tag, attrib): 883 events.append("start-" + tag)884 def end(self, tag): 885 events.append("end-" + tag) 886 def data(self, data): 887 events.append("data-" + data) 888 def comment(self, text): 889 events.append("comment-" + text) 890 def close(self): 891 return "DONE" 892 893 parser = self.etree.XMLParser(target=Target()) 894 895 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->')) 896 done = parser.close() 897 898 self.assertEqual("DONE", done) 899 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b", 900 "start-sub", "end-sub", "comment-c", "data-B", 901 "end-root", "comment-d"], 902 events) 903905 events = [] 906 class Target(object): 907 def start(self, tag, attrib): 908 events.append("start-" + tag)909 def end(self, tag): 910 events.append("end-" + tag) 911 def data(self, data): 912 events.append("data-" + data) 913 def pi(self, target, data): 914 events.append("pi-" + target + "-" + data) 915 def close(self): 916 return "DONE" 917 918 parser = self.etree.XMLParser(target=Target()) 919 920 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>')) 921 done = parser.close() 922 923 self.assertEqual("DONE", done) 924 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b", 925 "data-B", "end-root", "pi-test-c"], 926 events) 927929 events = [] 930 class Target(object): 931 def start(self, tag, attrib): 932 events.append("start-" + tag)933 def end(self, tag): 934 events.append("end-" + tag) 935 def data(self, data): 936 events.append("data-" + data) 937 def close(self): 938 return "DONE" 939 940 parser = self.etree.XMLParser(target=Target(), 941 strip_cdata=False) 942 943 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>')) 944 done = parser.close() 945 946 self.assertEqual("DONE", done) 947 self.assertEqual(["start-root", "data-A", "start-a", 948 "data-ca", "end-a", "data-B", "end-root"], 949 events) 950952 events = [] 953 class Target(object): 954 def start(self, tag, attrib): 955 events.append("start-" + tag)956 def end(self, tag): 957 events.append("end-" + tag) 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 recover=True) 966 967 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>')) 968 done = parser.close() 969 970 self.assertEqual("DONE", done) 971 self.assertEqual(["start-root", "data-A", "start-a", 972 "data-ca", "end-a", "data-B", 973 "end-root", "close"], 974 events) 975977 iterwalk = self.etree.iterwalk 978 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 979 980 iterator = iterwalk(root, tag="b", events=('start', 'end')) 981 events = list(iterator) 982 self.assertEqual( 983 [('start', root[0]), ('end', root[0])], 984 events)985987 iterwalk = self.etree.iterwalk 988 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 989 990 iterator = iterwalk(root, tag="*", events=('start', 'end')) 991 events = list(iterator) 992 self.assertEqual( 993 8, 994 len(events))995997 iterwalk = self.etree.iterwalk 998 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 999 1000 events = list(iterwalk(root)) 1001 self.assertEqual( 1002 [('end', root[0]), ('end', root[1]), ('end', root)], 1003 events)10041006 iterwalk = self.etree.iterwalk 1007 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1008 1009 iterator = iterwalk(root, events=('start',)) 1010 events = list(iterator) 1011 self.assertEqual( 1012 [('start', root), ('start', root[0]), ('start', root[1])], 1013 events)10141016 iterwalk = self.etree.iterwalk 1017 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1018 1019 iterator = iterwalk(root, events=('start','end')) 1020 events = list(iterator) 1021 self.assertEqual( 1022 [('start', root), ('start', root[0]), ('end', root[0]), 1023 ('start', root[1]), ('end', root[1]), ('end', root)], 1024 events)10251027 iterwalk = self.etree.iterwalk 1028 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1029 1030 iterator = iterwalk(root) 1031 for event, elem in iterator: 1032 elem.clear() 1033 1034 self.assertEqual(0, 1035 len(root))10361038 iterwalk = self.etree.iterwalk 1039 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>')) 1040 1041 attr_name = '{testns}bla' 1042 events = [] 1043 iterator = iterwalk(root, events=('start','end','start-ns','end-ns')) 1044 for event, elem in iterator: 1045 events.append(event) 1046 if event == 'start': 1047 if elem.tag != '{ns1}a': 1048 elem.set(attr_name, 'value') 1049 1050 self.assertEqual( 1051 ['start-ns', 'start', 'start', 'start-ns', 'start', 1052 'end', 'end-ns', 'end', 'end', 'end-ns'], 1053 events) 1054 1055 self.assertEqual( 1056 None, 1057 root.get(attr_name)) 1058 self.assertEqual( 1059 'value', 1060 root[0].get(attr_name))10611063 iterwalk = self.etree.iterwalk 1064 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1065 1066 counts = [] 1067 for event, elem in iterwalk(root): 1068 counts.append(len(list(elem.getiterator()))) 1069 self.assertEqual( 1070 [1,2,1,4], 1071 counts)10721074 parse = self.etree.parse 1075 parser = self.etree.XMLParser(dtd_validation=True) 1076 assertEqual = self.assertEqual 1077 test_url = _str("__nosuch.dtd") 1078 1079 class MyResolver(self.etree.Resolver): 1080 def resolve(self, url, id, context): 1081 assertEqual(url, test_url) 1082 return self.resolve_string( 1083 _str('''<!ENTITY myentity "%s"> 1084 <!ELEMENT doc ANY>''') % url, context)1085 1086 parser.resolvers.add(MyResolver()) 1087 1088 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1089 tree = parse(StringIO(xml), parser) 1090 root = tree.getroot() 1091 self.assertEqual(root.text, test_url) 10921094 parse = self.etree.parse 1095 parser = self.etree.XMLParser(dtd_validation=True) 1096 assertEqual = self.assertEqual 1097 test_url = _str("__nosuch.dtd") 1098 1099 class MyResolver(self.etree.Resolver): 1100 def resolve(self, url, id, context): 1101 assertEqual(url, test_url) 1102 return self.resolve_string( 1103 (_str('''<!ENTITY myentity "%s"> 1104 <!ELEMENT doc ANY>''') % url).encode('utf-8'), 1105 context)1106 1107 parser.resolvers.add(MyResolver()) 1108 1109 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1110 tree = parse(StringIO(xml), parser) 1111 root = tree.getroot() 1112 self.assertEqual(root.text, test_url) 11131115 parse = self.etree.parse 1116 parser = self.etree.XMLParser(dtd_validation=True) 1117 assertEqual = self.assertEqual 1118 test_url = _str("__nosuch.dtd") 1119 1120 class MyResolver(self.etree.Resolver): 1121 def resolve(self, url, id, context): 1122 assertEqual(url, test_url) 1123 return self.resolve_file( 1124 SillyFileLike( 1125 _str('''<!ENTITY myentity "%s"> 1126 <!ELEMENT doc ANY>''') % url), context)1127 1128 parser.resolvers.add(MyResolver()) 1129 1130 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1131 tree = parse(StringIO(xml), parser) 1132 root = tree.getroot() 1133 self.assertEqual(root.text, test_url) 11341136 parse = self.etree.parse 1137 parser = self.etree.XMLParser(attribute_defaults=True) 1138 assertEqual = self.assertEqual 1139 test_url = _str("__nosuch.dtd") 1140 1141 class MyResolver(self.etree.Resolver): 1142 def resolve(self, url, id, context): 1143 assertEqual(url, test_url) 1144 return self.resolve_filename( 1145 fileInTestDir('test.dtd'), context)1146 1147 parser.resolvers.add(MyResolver()) 1148 1149 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1150 tree = parse(StringIO(xml), parser) 1151 root = tree.getroot() 1152 self.assertEqual( 1153 root.attrib, {'default': 'valueA'}) 1154 self.assertEqual( 1155 root[0].attrib, {'default': 'valueB'}) 11561158 parse = self.etree.parse 1159 parser = self.etree.XMLParser(attribute_defaults=True) 1160 assertEqual = self.assertEqual 1161 test_url = _str("__nosuch.dtd") 1162 1163 class MyResolver(self.etree.Resolver): 1164 def resolve(self, url, id, context): 1165 assertEqual(url, fileInTestDir(test_url)) 1166 return self.resolve_filename( 1167 fileInTestDir('test.dtd'), context)1168 1169 parser.resolvers.add(MyResolver()) 1170 1171 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1172 tree = parse(StringIO(xml), parser, 1173 base_url=fileInTestDir('__test.xml')) 1174 root = tree.getroot() 1175 self.assertEqual( 1176 root.attrib, {'default': 'valueA'}) 1177 self.assertEqual( 1178 root[0].attrib, {'default': 'valueB'}) 11791181 parse = self.etree.parse 1182 parser = self.etree.XMLParser(attribute_defaults=True) 1183 assertEqual = self.assertEqual 1184 test_url = _str("__nosuch.dtd") 1185 1186 class MyResolver(self.etree.Resolver): 1187 def resolve(self, url, id, context): 1188 assertEqual(url, test_url) 1189 return self.resolve_file( 1190 open(fileInTestDir('test.dtd'), 'rb'), context)1191 1192 parser.resolvers.add(MyResolver()) 1193 1194 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1195 tree = parse(StringIO(xml), parser) 1196 root = tree.getroot() 1197 self.assertEqual( 1198 root.attrib, {'default': 'valueA'}) 1199 self.assertEqual( 1200 root[0].attrib, {'default': 'valueB'}) 12011203 parse = self.etree.parse 1204 parser = self.etree.XMLParser(load_dtd=True) 1205 assertEqual = self.assertEqual 1206 test_url = _str("__nosuch.dtd") 1207 1208 class check(object): 1209 resolved = False1210 1211 class MyResolver(self.etree.Resolver): 1212 def resolve(self, url, id, context): 1213 assertEqual(url, test_url) 1214 check.resolved = True 1215 return self.resolve_empty(context) 1216 1217 parser.resolvers.add(MyResolver()) 1218 1219 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1220 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser) 1221 self.assertTrue(check.resolved) 12221224 parse = self.etree.parse 1225 parser = self.etree.XMLParser(dtd_validation=True) 1226 1227 class _LocalException(Exception): 1228 pass1229 1230 class MyResolver(self.etree.Resolver): 1231 def resolve(self, url, id, context): 1232 raise _LocalException 1233 1234 parser.resolvers.add(MyResolver()) 1235 1236 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>' 1237 self.assertRaises(_LocalException, parse, BytesIO(xml), parser) 1238 1239 if etree.LIBXML_VERSION > (2,6,20):1241 parse = self.etree.parse 1242 tostring = self.etree.tostring 1243 parser = self.etree.XMLParser(resolve_entities=False) 1244 Entity = self.etree.Entity 1245 1246 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>') 1247 tree = parse(BytesIO(xml), parser) 1248 root = tree.getroot() 1249 self.assertEqual(root[0].tag, Entity) 1250 self.assertEqual(root[0].text, "&myentity;") 1251 self.assertEqual(root[0].tail, None) 1252 self.assertEqual(root[0].name, "myentity") 1253 1254 self.assertEqual(_bytes('<doc>&myentity;</doc>'), 1255 tostring(root))12561258 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]> 1259 <root> 1260 <child1/> 1261 <child2/> 1262 <child3> </child3> 1263 </root>''') 1264 1265 parser = self.etree.XMLParser(resolve_entities=False) 1266 root = etree.fromstring(xml, parser) 1267 self.assertEqual([ el.tag for el in root ], 1268 ['child1', 'child2', 'child3']) 1269 1270 root[0] = root[-1] 1271 self.assertEqual([ el.tag for el in root ], 1272 ['child3', 'child2']) 1273 self.assertEqual(root[0][0].text, ' ') 1274 self.assertEqual(root[0][0].name, 'nbsp')12751277 Entity = self.etree.Entity 1278 Element = self.etree.Element 1279 tostring = self.etree.tostring 1280 1281 root = Element("root") 1282 root.append( Entity("test") ) 1283 1284 self.assertEqual(root[0].tag, Entity) 1285 self.assertEqual(root[0].text, "&test;") 1286 self.assertEqual(root[0].tail, None) 1287 self.assertEqual(root[0].name, "test") 1288 1289 self.assertEqual(_bytes('<root>&test;</root>'), 1290 tostring(root))12911293 Entity = self.etree.Entity 1294 self.assertEqual(Entity("test").text, '&test;') 1295 self.assertEqual(Entity("#17683").text, '䔓') 1296 self.assertEqual(Entity("#x1768").text, 'ᝨ') 1297 self.assertEqual(Entity("#x98AF").text, '颯')12981300 Entity = self.etree.Entity 1301 self.assertRaises(ValueError, Entity, 'a b c') 1302 self.assertRaises(ValueError, Entity, 'a,b') 1303 self.assertRaises(ValueError, Entity, 'a\0b') 1304 self.assertRaises(ValueError, Entity, '#abc') 1305 self.assertRaises(ValueError, Entity, '#xxyz')13061308 CDATA = self.etree.CDATA 1309 Element = self.etree.Element 1310 tostring = self.etree.tostring 1311 1312 root = Element("root") 1313 root.text = CDATA('test') 1314 1315 self.assertEqual('test', 1316 root.text) 1317 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1318 tostring(root))13191321 CDATA = self.etree.CDATA 1322 Element = self.etree.Element 1323 root = Element("root") 1324 1325 root.text = CDATA("test") 1326 self.assertEqual('test', root.text) 1327 1328 root.text = CDATA(_str("test")) 1329 self.assertEqual('test', root.text) 1330 1331 self.assertRaises(TypeError, CDATA, 1)13321334 CDATA = self.etree.CDATA 1335 Element = self.etree.Element 1336 1337 root = Element("root") 1338 cdata = CDATA('test') 1339 1340 self.assertRaises(TypeError, 1341 setattr, root, 'tail', cdata) 1342 self.assertRaises(TypeError, 1343 root.set, 'attr', cdata) 1344 self.assertRaises(TypeError, 1345 operator.setitem, root.attrib, 'attr', cdata)13461348 tostring = self.etree.tostring 1349 parser = self.etree.XMLParser(strip_cdata=False) 1350 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1351 1352 self.assertEqual('test', root.text) 1353 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1354 tostring(root))13551357 tostring = self.etree.tostring 1358 parser = self.etree.XMLParser(strip_cdata=False) 1359 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1360 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1361 tostring(root)) 1362 1363 self.assertEqual(['test'], root.xpath('//text()'))1364 1365 # TypeError in etree, AssertionError in ElementTree;1367 Element = self.etree.Element 1368 SubElement = self.etree.SubElement 1369 1370 a = Element('a') 1371 b = SubElement(a, 'b') 1372 1373 self.assertRaises(TypeError, 1374 a.__setitem__, 0, 'foo')13751377 Element = self.etree.Element 1378 root = Element('root') 1379 # raises AssertionError in ElementTree 1380 self.assertRaises(TypeError, root.append, None) 1381 self.assertRaises(TypeError, root.extend, [None]) 1382 self.assertRaises(TypeError, root.extend, [Element('one'), None]) 1383 self.assertEqual('one', root[0].tag)13841386 Element = self.etree.Element 1387 SubElement = self.etree.SubElement 1388 root = Element('root') 1389 self.assertRaises(ValueError, root.append, root) 1390 child = SubElement(root, 'child') 1391 self.assertRaises(ValueError, child.append, root) 1392 child2 = SubElement(child, 'child2') 1393 self.assertRaises(ValueError, child2.append, root) 1394 self.assertRaises(ValueError, child2.append, child) 1395 self.assertEqual('child2', root[0][0].tag)13961398 Element = self.etree.Element 1399 SubElement = self.etree.SubElement 1400 root = Element('root') 1401 SubElement(root, 'a') 1402 SubElement(root, 'b') 1403 1404 self.assertEqual(['a', 'b'], 1405 [c.tag for c in root]) 1406 root[1].addnext(root[0]) 1407 self.assertEqual(['b', 'a'], 1408 [c.tag for c in root])14091411 Element = self.etree.Element 1412 SubElement = self.etree.SubElement 1413 root = Element('root') 1414 SubElement(root, 'a') 1415 SubElement(root, 'b') 1416 1417 self.assertEqual(['a', 'b'], 1418 [c.tag for c in root]) 1419 root[0].addprevious(root[1]) 1420 self.assertEqual(['b', 'a'], 1421 [c.tag for c in root])14221424 Element = self.etree.Element 1425 SubElement = self.etree.SubElement 1426 root = Element('root') 1427 a = SubElement(root, 'a') 1428 b = SubElement(root, 'b') 1429 a.addprevious(a) 1430 self.assertEqual('a', root[0].tag) 1431 self.assertEqual('b', root[1].tag) 1432 b.addprevious(b) 1433 self.assertEqual('a', root[0].tag) 1434 self.assertEqual('b', root[1].tag) 1435 b.addprevious(a) 1436 self.assertEqual('a', root[0].tag) 1437 self.assertEqual('b', root[1].tag)14381440 Element = self.etree.Element 1441 SubElement = self.etree.SubElement 1442 root = Element('root') 1443 a = SubElement(root, 'a') 1444 b = SubElement(root, 'b') 1445 a.addnext(a) 1446 self.assertEqual('a', root[0].tag) 1447 self.assertEqual('b', root[1].tag) 1448 b.addnext(b) 1449 self.assertEqual('a', root[0].tag) 1450 self.assertEqual('b', root[1].tag) 1451 a.addnext(b) 1452 self.assertEqual('a', root[0].tag) 1453 self.assertEqual('b', root[1].tag)14541456 Element = self.etree.Element 1457 a = Element('a') 1458 b = Element('b') 1459 self.assertRaises(TypeError, a.addnext, b)14601462 Element = self.etree.Element 1463 SubElement = self.etree.SubElement 1464 PI = self.etree.PI 1465 root = Element('root') 1466 SubElement(root, 'a') 1467 pi = PI('TARGET', 'TEXT') 1468 pi.tail = "TAIL" 1469 1470 self.assertEqual(_bytes('<root><a></a></root>'), 1471 self._writeElement(root)) 1472 root[0].addprevious(pi) 1473 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'), 1474 self._writeElement(root))14751477 Element = self.etree.Element 1478 PI = self.etree.PI 1479 root = Element('root') 1480 pi = PI('TARGET', 'TEXT') 1481 pi.tail = "TAIL" 1482 1483 self.assertEqual(_bytes('<root></root>'), 1484 self._writeElement(root)) 1485 root.addprevious(pi) 1486 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'), 1487 self._writeElement(root))14881490 Element = self.etree.Element 1491 SubElement = self.etree.SubElement 1492 PI = self.etree.PI 1493 root = Element('root') 1494 SubElement(root, 'a') 1495 pi = PI('TARGET', 'TEXT') 1496 pi.tail = "TAIL" 1497 1498 self.assertEqual(_bytes('<root><a></a></root>'), 1499 self._writeElement(root)) 1500 root[0].addnext(pi) 1501 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'), 1502 self._writeElement(root))15031505 Element = self.etree.Element 1506 PI = self.etree.PI 1507 root = Element('root') 1508 pi = PI('TARGET', 'TEXT') 1509 pi.tail = "TAIL" 1510 1511 self.assertEqual(_bytes('<root></root>'), 1512 self._writeElement(root)) 1513 root.addnext(pi) 1514 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'), 1515 self._writeElement(root))15161518 Element = self.etree.Element 1519 SubElement = self.etree.SubElement 1520 Comment = self.etree.Comment 1521 root = Element('root') 1522 SubElement(root, 'a') 1523 comment = Comment('TEXT ') 1524 comment.tail = "TAIL" 1525 1526 self.assertEqual(_bytes('<root><a></a></root>'), 1527 self._writeElement(root)) 1528 root[0].addnext(comment) 1529 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'), 1530 self._writeElement(root))15311533 Element = self.etree.Element 1534 Comment = self.etree.Comment 1535 root = Element('root') 1536 comment = Comment('TEXT ') 1537 comment.tail = "TAIL" 1538 1539 self.assertEqual(_bytes('<root></root>'), 1540 self._writeElement(root)) 1541 root.addnext(comment) 1542 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'), 1543 self._writeElement(root))15441546 Element = self.etree.Element 1547 SubElement = self.etree.SubElement 1548 Comment = self.etree.Comment 1549 root = Element('root') 1550 SubElement(root, 'a') 1551 comment = Comment('TEXT ') 1552 comment.tail = "TAIL" 1553 1554 self.assertEqual(_bytes('<root><a></a></root>'), 1555 self._writeElement(root)) 1556 root[0].addprevious(comment) 1557 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'), 1558 self._writeElement(root))15591561 Element = self.etree.Element 1562 Comment = self.etree.Comment 1563 root = Element('root') 1564 comment = Comment('TEXT ') 1565 comment.tail = "TAIL" 1566 1567 self.assertEqual(_bytes('<root></root>'), 1568 self._writeElement(root)) 1569 root.addprevious(comment) 1570 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'), 1571 self._writeElement(root))1572 1573 # ET's Elements have items() and key(), but not values()1575 XML = self.etree.XML 1576 1577 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>')) 1578 values = root.values() 1579 values.sort() 1580 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)1581 1582 # gives error in ElementTree1584 Element = self.etree.Element 1585 Comment = self.etree.Comment 1586 1587 a = Element('a') 1588 a.append(Comment()) 1589 self.assertEqual( 1590 _bytes('<a><!----></a>'), 1591 self._writeElement(a))1592 1593 # ElementTree ignores comments1595 ElementTree = self.etree.ElementTree 1596 tostring = self.etree.tostring 1597 1598 xml = _bytes('<a><b/><!----><c/></a>') 1599 f = BytesIO(xml) 1600 doc = ElementTree(file=f) 1601 a = doc.getroot() 1602 self.assertEqual( 1603 '', 1604 a[1].text) 1605 self.assertEqual( 1606 xml, 1607 tostring(a))1608 1609 # ElementTree ignores comments1611 ElementTree = self.etree.ElementTree 1612 1613 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>') 1614 doc = ElementTree(file=f) 1615 a = doc.getroot() 1616 self.assertEqual( 1617 ' hoi ', 1618 a[1].text)1619 1620 # does not raise an exception in ElementTree1622 Element = self.etree.Element 1623 Comment = self.etree.Comment 1624 1625 c = Comment() 1626 el = Element('myel') 1627 1628 self.assertRaises(TypeError, c.append, el) 1629 self.assertRaises(TypeError, c.insert, 0, el) 1630 self.assertRaises(TypeError, c.set, "myattr", "test")1631 1632 # test passing 'None' to dump 16351637 ElementTree = self.etree.ElementTree 1638 1639 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>') 1640 doc = ElementTree(file=f) 1641 a = doc.getroot() 1642 self.assertEqual( 1643 None, 1644 a.prefix) 1645 self.assertEqual( 1646 'foo', 1647 a[0].prefix)16481650 ElementTree = self.etree.ElementTree 1651 1652 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>') 1653 doc = ElementTree(file=f) 1654 a = doc.getroot() 1655 self.assertEqual( 1656 None, 1657 a.prefix) 1658 self.assertEqual( 1659 None, 1660 a[0].prefix)16611663 Element = self.etree.Element 1664 SubElement = self.etree.SubElement 1665 1666 a = Element('a') 1667 b = SubElement(a, 'b') 1668 c = SubElement(a, 'c') 1669 d = SubElement(b, 'd') 1670 self.assertEqual( 1671 None, 1672 a.getparent()) 1673 self.assertEqual( 1674 a, 1675 b.getparent()) 1676 self.assertEqual( 1677 b.getparent(), 1678 c.getparent()) 1679 self.assertEqual( 1680 b, 1681 d.getparent())16821684 XML = self.etree.XML 1685 1686 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 1687 result = [] 1688 for el in root.iterchildren(): 1689 result.append(el.tag) 1690 self.assertEqual(['one', 'two', 'three'], result)16911693 XML = self.etree.XML 1694 1695 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 1696 result = [] 1697 for el in root.iterchildren(reversed=True): 1698 result.append(el.tag) 1699 self.assertEqual(['three', 'two', 'one'], result)17001702 XML = self.etree.XML 1703 1704 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 1705 result = [] 1706 for el in root.iterchildren(tag='two'): 1707 result.append(el.text) 1708 self.assertEqual(['Two', 'Bla'], result)17091711 XML = self.etree.XML 1712 1713 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 1714 result = [] 1715 for el in root.iterchildren(reversed=True, tag='two'): 1716 result.append(el.text) 1717 self.assertEqual(['Bla', 'Two'], result)17181720 XML = self.etree.XML 1721 1722 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 1723 result = [] 1724 for el in root.iterchildren(tag=['two', 'three']): 1725 result.append(el.text) 1726 self.assertEqual(['Two', 'Bla', None], result)17271729 XML = self.etree.XML 1730 1731 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 1732 result = [] 1733 for el in root.iterchildren(reversed=True, tag=['two', 'three']): 1734 result.append(el.text) 1735 self.assertEqual([None, 'Bla', 'Two'], result)17361738 Element = self.etree.Element 1739 SubElement = self.etree.SubElement 1740 1741 a = Element('a') 1742 b = SubElement(a, 'b') 1743 c = SubElement(a, 'c') 1744 d = SubElement(b, 'd') 1745 self.assertEqual( 1746 [], 1747 list(a.iterancestors())) 1748 self.assertEqual( 1749 [a], 1750 list(b.iterancestors())) 1751 self.assertEqual( 1752 [a], 1753 list(c.iterancestors())) 1754 self.assertEqual( 1755 [b, a], 1756 list(d.iterancestors()))17571759 Element = self.etree.Element 1760 SubElement = self.etree.SubElement 1761 1762 a = Element('a') 1763 b = SubElement(a, 'b') 1764 c = SubElement(a, 'c') 1765 d = SubElement(b, 'd') 1766 self.assertEqual( 1767 [a], 1768 list(d.iterancestors(tag='a'))) 1769 self.assertEqual( 1770 [b, a], 1771 list(d.iterancestors(tag='*')))17721774 Element = self.etree.Element 1775 SubElement = self.etree.SubElement 1776 1777 a = Element('a') 1778 b = SubElement(a, 'b') 1779 c = SubElement(a, 'c') 1780 d = SubElement(b, 'd') 1781 self.assertEqual( 1782 [b, a], 1783 list(d.iterancestors(tag=('a', 'b')))) 1784 self.assertEqual( 1785 [], 1786 list(d.iterancestors(tag=('w', 'x', 'y', 'z')))) 1787 self.assertEqual( 1788 [], 1789 list(d.iterancestors(tag=('d', 'x')))) 1790 self.assertEqual( 1791 [b, a], 1792 list(d.iterancestors(tag=('b', '*')))) 1793 self.assertEqual( 1794 [b], 1795 list(d.iterancestors(tag=('b', 'c'))))17961798 Element = self.etree.Element 1799 SubElement = self.etree.SubElement 1800 1801 a = Element('a') 1802 b = SubElement(a, 'b') 1803 c = SubElement(a, 'c') 1804 d = SubElement(b, 'd') 1805 e = SubElement(c, 'e') 1806 1807 self.assertEqual( 1808 [b, d, c, e], 1809 list(a.iterdescendants())) 1810 self.assertEqual( 1811 [], 1812 list(d.iterdescendants()))18131815 Element = self.etree.Element 1816 SubElement = self.etree.SubElement 1817 1818 a = Element('a') 1819 b = SubElement(a, 'b') 1820 c = SubElement(a, 'c') 1821 d = SubElement(b, 'd') 1822 e = SubElement(c, 'e') 1823 1824 self.assertEqual( 1825 [], 1826 list(a.iterdescendants('a'))) 1827 a2 = SubElement(e, 'a') 1828 self.assertEqual( 1829 [a2], 1830 list(a.iterdescendants('a'))) 1831 self.assertEqual( 1832 [a2], 1833 list(c.iterdescendants('a')))18341836 Element = self.etree.Element 1837 SubElement = self.etree.SubElement 1838 1839 a = Element('a') 1840 b = SubElement(a, 'b') 1841 c = SubElement(a, 'c') 1842 d = SubElement(b, 'd') 1843 e = SubElement(c, 'e') 1844 1845 self.assertEqual( 1846 [b, e], 1847 list(a.iterdescendants(tag=('a', 'b', 'e')))) 1848 a2 = SubElement(e, 'a') 1849 self.assertEqual( 1850 [b, a2], 1851 list(a.iterdescendants(tag=('a', 'b')))) 1852 self.assertEqual( 1853 [], 1854 list(c.iterdescendants(tag=('x', 'y', 'z')))) 1855 self.assertEqual( 1856 [b, d, c, e, a2], 1857 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))18581860 Element = self.etree.Element 1861 SubElement = self.etree.SubElement 1862 1863 a = Element('a') 1864 b = SubElement(a, 'b') 1865 c = SubElement(a, 'c') 1866 d = SubElement(b, 'd') 1867 self.assertEqual( 1868 a, 1869 a.getroottree().getroot()) 1870 self.assertEqual( 1871 a, 1872 b.getroottree().getroot()) 1873 self.assertEqual( 1874 a, 1875 d.getroottree().getroot())18761878 Element = self.etree.Element 1879 SubElement = self.etree.SubElement 1880 1881 a = Element('a') 1882 b = SubElement(a, 'b') 1883 c = SubElement(a, 'c') 1884 self.assertEqual( 1885 None, 1886 a.getnext()) 1887 self.assertEqual( 1888 c, 1889 b.getnext()) 1890 self.assertEqual( 1891 None, 1892 c.getnext())18931895 Element = self.etree.Element 1896 SubElement = self.etree.SubElement 1897 1898 a = Element('a') 1899 b = SubElement(a, 'b') 1900 c = SubElement(a, 'c') 1901 d = SubElement(b, 'd') 1902 self.assertEqual( 1903 None, 1904 a.getprevious()) 1905 self.assertEqual( 1906 b, 1907 c.getprevious()) 1908 self.assertEqual( 1909 None, 1910 b.getprevious())19111913 Element = self.etree.Element 1914 SubElement = self.etree.SubElement 1915 1916 a = Element('a') 1917 b = SubElement(a, 'b') 1918 c = SubElement(a, 'c') 1919 d = SubElement(b, 'd') 1920 self.assertEqual( 1921 [], 1922 list(a.itersiblings())) 1923 self.assertEqual( 1924 [c], 1925 list(b.itersiblings())) 1926 self.assertEqual( 1927 [], 1928 list(c.itersiblings())) 1929 self.assertEqual( 1930 [b], 1931 list(c.itersiblings(preceding=True))) 1932 self.assertEqual( 1933 [], 1934 list(b.itersiblings(preceding=True)))1935