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 gzip 19 20 this_dir = os.path.dirname(__file__) 21 if this_dir not in sys.path: 22 sys.path.insert(0, this_dir) # needed for Py3 23 24 from common_imports import etree, StringIO, BytesIO, HelperTestCase, fileInTestDir, read_file 25 from common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest 26 from common_imports import canonicalize, sorted, _str, _bytes 27 28 print("") 29 print("TESTED VERSION: %s" % etree.__version__) 30 print(" Python: " + repr(sys.version_info)) 31 print(" lxml.etree: " + repr(etree.LXML_VERSION)) 32 print(" libxml used: " + repr(etree.LIBXML_VERSION)) 33 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION)) 34 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION)) 35 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION)) 36 print("") 37 38 try: 39 _unicode = unicode 40 except NameError: 41 # Python 3 42 _unicode = str 4345 """Tests only for etree, not ElementTree""" 46 etree = etree 4760949 self.assertTrue(isinstance(etree.__version__, _unicode)) 50 self.assertTrue(isinstance(etree.LXML_VERSION, tuple)) 51 self.assertEqual(len(etree.LXML_VERSION), 4) 52 self.assertTrue(isinstance(etree.LXML_VERSION[0], int)) 53 self.assertTrue(isinstance(etree.LXML_VERSION[1], int)) 54 self.assertTrue(isinstance(etree.LXML_VERSION[2], int)) 55 self.assertTrue(isinstance(etree.LXML_VERSION[3], int)) 56 self.assertTrue(etree.__version__.startswith( 57 str(etree.LXML_VERSION[0])))5860 if hasattr(self.etree, '__pyx_capi__'): 61 # newer Pyrex compatible C-API 62 self.assertTrue(isinstance(self.etree.__pyx_capi__, dict)) 63 self.assertTrue(len(self.etree.__pyx_capi__) > 0) 64 else: 65 # older C-API mechanism 66 self.assertTrue(hasattr(self.etree, '_import_c_api'))6769 Element = self.etree.Element 70 el = Element('name') 71 self.assertEqual(el.tag, 'name') 72 el = Element('{}name') 73 self.assertEqual(el.tag, 'name')7476 Element = self.etree.Element 77 el = Element('name') 78 self.assertRaises(ValueError, Element, '{}') 79 self.assertRaises(ValueError, setattr, el, 'tag', '{}') 80 81 self.assertRaises(ValueError, Element, '{test}') 82 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')8385 Element = self.etree.Element 86 self.assertRaises(ValueError, Element, 'p:name') 87 self.assertRaises(ValueError, Element, '{test}p:name') 88 89 el = Element('name') 90 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')9193 Element = self.etree.Element 94 self.assertRaises(ValueError, Element, "p'name") 95 self.assertRaises(ValueError, Element, 'p"name') 96 97 self.assertRaises(ValueError, Element, "{test}p'name") 98 self.assertRaises(ValueError, Element, '{test}p"name') 99 100 el = Element('name') 101 self.assertRaises(ValueError, setattr, el, 'tag', "p'name") 102 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')103105 Element = self.etree.Element 106 self.assertRaises(ValueError, Element, ' name ') 107 self.assertRaises(ValueError, Element, 'na me') 108 self.assertRaises(ValueError, Element, '{test} name') 109 110 el = Element('name') 111 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')112114 Element = self.etree.Element 115 SubElement = self.etree.SubElement 116 117 el = Element('name') 118 self.assertRaises(ValueError, SubElement, el, '{}') 119 self.assertRaises(ValueError, SubElement, el, '{test}')120122 Element = self.etree.Element 123 SubElement = self.etree.SubElement 124 125 el = Element('name') 126 self.assertRaises(ValueError, SubElement, el, 'p:name') 127 self.assertRaises(ValueError, SubElement, el, '{test}p:name')128130 Element = self.etree.Element 131 SubElement = self.etree.SubElement 132 133 el = Element('name') 134 self.assertRaises(ValueError, SubElement, el, "p'name") 135 self.assertRaises(ValueError, SubElement, el, "{test}p'name") 136 137 self.assertRaises(ValueError, SubElement, el, 'p"name') 138 self.assertRaises(ValueError, SubElement, el, '{test}p"name')139141 Element = self.etree.Element 142 SubElement = self.etree.SubElement 143 144 el = Element('name') 145 self.assertRaises(ValueError, SubElement, el, ' name ') 146 self.assertRaises(ValueError, SubElement, el, 'na me') 147 self.assertRaises(ValueError, SubElement, el, '{test} name')148150 Element = self.etree.Element 151 SubElement = self.etree.SubElement 152 153 el = Element('name') 154 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'}) 155 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'}) 156 self.assertEqual(0, len(el))157159 QName = self.etree.QName 160 self.assertRaises(ValueError, QName, '') 161 self.assertRaises(ValueError, QName, 'test', '')162164 QName = self.etree.QName 165 self.assertRaises(ValueError, QName, 'p:name') 166 self.assertRaises(ValueError, QName, 'test', 'p:name')167169 QName = self.etree.QName 170 self.assertRaises(ValueError, QName, ' name ') 171 self.assertRaises(ValueError, QName, 'na me') 172 self.assertRaises(ValueError, QName, 'test', ' name')173175 # ET doesn't have namespace/localname properties on QNames 176 QName = self.etree.QName 177 namespace, localname = 'http://myns', 'a' 178 qname = QName(namespace, localname) 179 self.assertEqual(namespace, qname.namespace) 180 self.assertEqual(localname, qname.localname)181183 # ET doesn't have namespace/localname properties on QNames 184 QName = self.etree.QName 185 qname1 = QName('http://myns', 'a') 186 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'}) 187 188 qname2 = QName(a) 189 self.assertEqual(a.tag, qname1.text) 190 self.assertEqual(qname1.text, qname2.text) 191 self.assertEqual(qname1, qname2)192194 # ET doesn't resove QNames as text values 195 etree = self.etree 196 qname = etree.QName('http://myns', 'a') 197 a = etree.Element(qname, nsmap={'p' : 'http://myns'}) 198 a.text = qname 199 200 self.assertEqual("p:a", a.text)201203 etree = self.etree 204 self.assertRaises(ValueError, 205 etree.Element, "root", nsmap={'"' : 'testns'}) 206 self.assertRaises(ValueError, 207 etree.Element, "root", nsmap={'&' : 'testns'}) 208 self.assertRaises(ValueError, 209 etree.Element, "root", nsmap={'a:b' : 'testns'})210212 # ET in Py 3.x has no "attrib.has_key()" method 213 XML = self.etree.XML 214 215 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />')) 216 self.assertEqual( 217 True, root.attrib.has_key('bar')) 218 self.assertEqual( 219 False, root.attrib.has_key('baz')) 220 self.assertEqual( 221 False, root.attrib.has_key('hah')) 222 self.assertEqual( 223 True, 224 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))225227 Element = self.etree.Element 228 root = Element("root") 229 root.set("attr", "TEST") 230 self.assertEqual("TEST", root.get("attr"))231233 # ElementTree accepts arbitrary attribute values 234 # lxml.etree allows only strings 235 Element = self.etree.Element 236 root = Element("root") 237 self.assertRaises(TypeError, root.set, "newattr", 5) 238 self.assertRaises(TypeError, root.set, "newattr", None)239241 XML = self.etree.XML 242 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>') 243 244 root = XML(xml) 245 self.etree.strip_attributes(root, 'a') 246 self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'), 247 self._writeElement(root)) 248 249 root = XML(xml) 250 self.etree.strip_attributes(root, 'b', 'c') 251 self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'), 252 self._writeElement(root))253255 XML = self.etree.XML 256 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>') 257 258 root = XML(xml) 259 self.etree.strip_attributes(root, 'a') 260 self.assertEqual( 261 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'), 262 self._writeElement(root)) 263 264 root = XML(xml) 265 self.etree.strip_attributes(root, '{http://test/ns}a', 'c') 266 self.assertEqual( 267 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'), 268 self._writeElement(root)) 269 270 root = XML(xml) 271 self.etree.strip_attributes(root, '{http://test/ns}*') 272 self.assertEqual( 273 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'), 274 self._writeElement(root))275277 XML = self.etree.XML 278 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>') 279 280 root = XML(xml) 281 self.etree.strip_elements(root, 'a') 282 self.assertEqual(_bytes('<test><x></x></test>'), 283 self._writeElement(root)) 284 285 root = XML(xml) 286 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z') 287 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'), 288 self._writeElement(root)) 289 290 root = XML(xml) 291 self.etree.strip_elements(root, 'c') 292 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'), 293 self._writeElement(root))294296 XML = self.etree.XML 297 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>') 298 299 root = XML(xml) 300 self.etree.strip_elements(root, 'a') 301 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>'), 302 self._writeElement(root)) 303 304 root = XML(xml) 305 self.etree.strip_elements(root, '{urn:a}b', 'c') 306 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>'), 307 self._writeElement(root)) 308 309 root = XML(xml) 310 self.etree.strip_elements(root, '{urn:a}*', 'c') 311 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 312 self._writeElement(root)) 313 314 root = XML(xml) 315 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False) 316 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'), 317 self._writeElement(root))318 337 363 390 416 435 448450 # lxml.etree separates target and text 451 Element = self.etree.Element 452 SubElement = self.etree.SubElement 453 ProcessingInstruction = self.etree.ProcessingInstruction 454 455 a = Element('a') 456 a.append(ProcessingInstruction('foo', 'some more text')) 457 self.assertEqual(a[0].target, 'foo') 458 self.assertEqual(a[0].text, 'some more text')459461 XML = self.etree.XML 462 root = XML(_bytes("<test><?mypi my test ?></test>")) 463 self.assertEqual(root[0].target, "mypi") 464 self.assertEqual(root[0].text, "my test ")465467 XML = self.etree.XML 468 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 469 self.assertEqual(root[0].target, "mypi") 470 self.assertEqual(root[0].get('my'), "1") 471 self.assertEqual(root[0].get('test'), " abc ") 472 self.assertEqual(root[0].get('quotes'), "' '") 473 self.assertEqual(root[0].get('only'), None) 474 self.assertEqual(root[0].get('names'), None) 475 self.assertEqual(root[0].get('nope'), None)476478 XML = self.etree.XML 479 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>")) 480 self.assertEqual(root[0].target, "mypi") 481 self.assertEqual(root[0].attrib['my'], "1") 482 self.assertEqual(root[0].attrib['test'], " abc ") 483 self.assertEqual(root[0].attrib['quotes'], "' '") 484 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only') 485 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names') 486 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')487489 # previously caused a crash 490 ProcessingInstruction = self.etree.ProcessingInstruction 491 492 a = ProcessingInstruction("PI", "ONE") 493 b = copy.deepcopy(a) 494 b.text = "ANOTHER" 495 496 self.assertEqual('ONE', a.text) 497 self.assertEqual('ANOTHER', b.text)498500 XML = self.etree.XML 501 tostring = self.etree.tostring 502 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->")) 503 tree1 = self.etree.ElementTree(root) 504 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 505 tostring(tree1)) 506 507 tree2 = copy.deepcopy(tree1) 508 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"), 509 tostring(tree2)) 510 511 root2 = copy.deepcopy(tree1.getroot()) 512 self.assertEqual(_bytes("<test/>"), 513 tostring(root2))514516 XML = self.etree.XML 517 tostring = self.etree.tostring 518 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>') 519 root = XML(xml) 520 tree1 = self.etree.ElementTree(root) 521 self.assertEqual(xml, tostring(tree1)) 522 523 tree2 = copy.deepcopy(tree1) 524 self.assertEqual(xml, tostring(tree2)) 525 526 root2 = copy.deepcopy(tree1.getroot()) 527 self.assertEqual(_bytes("<test/>"), 528 tostring(root2))529531 # ElementTree accepts arbitrary attribute values 532 # lxml.etree allows only strings 533 Element = self.etree.Element 534 535 root = Element("root") 536 root.set("attr", "TEST") 537 self.assertEqual("TEST", root.get("attr")) 538 self.assertRaises(TypeError, root.set, "newattr", 5)539541 fromstring = self.etree.fromstring 542 tostring = self.etree.tostring 543 XMLParser = self.etree.XMLParser 544 545 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 546 parser = XMLParser(remove_comments=True) 547 root = fromstring(xml, parser) 548 self.assertEqual( 549 _bytes('<a><b><c/></b></a>'), 550 tostring(root))551553 parse = self.etree.parse 554 tostring = self.etree.tostring 555 XMLParser = self.etree.XMLParser 556 557 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>') 558 559 f = BytesIO(xml) 560 tree = parse(f) 561 self.assertEqual( 562 xml, 563 tostring(tree)) 564 565 parser = XMLParser(remove_pis=True) 566 tree = parse(f, parser) 567 self.assertEqual( 568 _bytes('<a><b><c/></b></a>'), 569 tostring(tree))570572 # ET raises IOError only 573 parse = self.etree.parse 574 self.assertRaises(TypeError, parse, 'notthere.xml', object())575577 # ET removes comments 578 iterparse = self.etree.iterparse 579 tostring = self.etree.tostring 580 581 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 582 events = list(iterparse(f)) 583 root = events[-1][1] 584 self.assertEqual(3, len(events)) 585 self.assertEqual( 586 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 587 tostring(root))588590 # ET removes comments 591 iterparse = self.etree.iterparse 592 tostring = self.etree.tostring 593 594 def name(event, el): 595 if event == 'comment': 596 return el.text 597 else: 598 return el.tag599 600 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 601 events = list(iterparse(f, events=('end', 'comment'))) 602 root = events[-1][1] 603 self.assertEqual(6, len(events)) 604 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'], 605 [ name(*item) for item in events ]) 606 self.assertEqual( 607 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'), 608 tostring(root))611 # ET removes pis 612 iterparse = self.etree.iterparse 613 tostring = self.etree.tostring 614 ElementTree = self.etree.ElementTree 615 616 def name(event, el): 617 if event == 'pi': 618 return (el.target, el.text) 619 else: 620 return el.tag621 622 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>') 623 events = list(iterparse(f, events=('end', 'pi'))) 624 root = events[-2][1] 625 self.assertEqual(8, len(events)) 626 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b', 627 ('pid','d'), 'a', ('pie','e')], 628 [ name(*item) for item in events ]) 629 self.assertEqual( 630 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'), 631 tostring(ElementTree(root))) 632634 iterparse = self.etree.iterparse 635 tostring = self.etree.tostring 636 637 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>') 638 events = list(iterparse(f, remove_comments=True, 639 events=('end', 'comment'))) 640 root = events[-1][1] 641 self.assertEqual(3, len(events)) 642 self.assertEqual(['c', 'b', 'a'], 643 [ el.tag for (event, el) in events ]) 644 self.assertEqual( 645 _bytes('<a><b><c/></b></a>'), 646 tostring(root))647649 iterparse = self.etree.iterparse 650 f = BytesIO('<a><b><c/></a>') 651 # ET raises ExpatError, lxml raises XMLSyntaxError 652 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))653655 iterparse = self.etree.iterparse 656 f = BytesIO(""" 657 <a> \n \n <b> b test </b> \n 658 659 \n\t <c> \n </c> </a> \n """) 660 iterator = iterparse(f, remove_blank_text=True) 661 text = [ (element.text, element.tail) 662 for event, element in iterator ] 663 self.assertEqual( 664 [(" b test ", None), (" \n ", None), (None, None)], 665 text)666668 iterparse = self.etree.iterparse 669 f = BytesIO('<a><b><d/></b><c/></a>') 670 671 iterator = iterparse(f, tag="b", events=('start', 'end')) 672 events = list(iterator) 673 root = iterator.root 674 self.assertEqual( 675 [('start', root[0]), ('end', root[0])], 676 events)677679 iterparse = self.etree.iterparse 680 f = BytesIO('<a><b><d/></b><c/></a>') 681 682 iterator = iterparse(f, tag="*", events=('start', 'end')) 683 events = list(iterator) 684 self.assertEqual( 685 8, 686 len(events))687689 iterparse = self.etree.iterparse 690 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 691 692 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end')) 693 events = list(iterator) 694 root = iterator.root 695 self.assertEqual( 696 [('start', root[0]), ('end', root[0])], 697 events)698700 iterparse = self.etree.iterparse 701 f = BytesIO('<a><b><d/></b><c/></a>') 702 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 703 events = list(iterator) 704 root = iterator.root 705 self.assertEqual( 706 [('start', root[0]), ('end', root[0])], 707 events) 708 709 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 710 iterator = iterparse(f, tag="{}b", events=('start', 'end')) 711 events = list(iterator) 712 root = iterator.root 713 self.assertEqual([], events)714716 iterparse = self.etree.iterparse 717 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 718 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end')) 719 events = list(iterator) 720 self.assertEqual(8, len(events))721723 iterparse = self.etree.iterparse 724 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>') 725 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 726 events = list(iterator) 727 self.assertEqual([], events) 728 729 f = BytesIO('<a><b><d/></b><c/></a>') 730 iterator = iterparse(f, tag="{}*", events=('start', 'end')) 731 events = list(iterator) 732 self.assertEqual(8, len(events))733735 text = _str('Søk på nettet') 736 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 737 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 738 ).encode('iso-8859-1') 739 740 self.assertRaises(self.etree.ParseError, 741 list, self.etree.iterparse(BytesIO(xml_latin1)))742744 text = _str('Søk på nettet', encoding="UTF-8") 745 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>" 746 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text) 747 ).encode('iso-8859-1') 748 749 iterator = self.etree.iterparse(BytesIO(xml_latin1), 750 encoding="iso-8859-1") 751 self.assertEqual(1, len(list(iterator))) 752 753 a = iterator.root 754 self.assertEqual(a.text, text)755757 tostring = self.etree.tostring 758 f = BytesIO('<root><![CDATA[test]]></root>') 759 context = self.etree.iterparse(f, strip_cdata=False) 760 content = [ el.text for event,el in context ] 761 762 self.assertEqual(['test'], content) 763 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 764 tostring(context.root))765 769771 self.etree.XMLParser(encoding="ascii") 772 self.etree.XMLParser(encoding="utf-8") 773 self.etree.XMLParser(encoding="iso-8859-1")774776 parser = self.etree.XMLParser(recover=True) 777 778 parser.feed('<?xml version=') 779 parser.feed('"1.0"?><ro') 780 parser.feed('ot><') 781 parser.feed('a test="works"') 782 parser.feed('><othertag/></root') # <a> not closed! 783 parser.feed('>') 784 785 root = parser.close() 786 787 self.assertEqual(root.tag, "root") 788 self.assertEqual(len(root), 1) 789 self.assertEqual(root[0].tag, "a") 790 self.assertEqual(root[0].get("test"), "works") 791 self.assertEqual(len(root[0]), 1) 792 self.assertEqual(root[0][0].tag, "othertag")793 # FIXME: would be nice to get some errors logged ... 794 #self.assertTrue(len(parser.error_log) > 0, "error log is empty") 795797 assertEqual = self.assertEqual 798 assertFalse = self.assertFalse 799 800 events = [] 801 class Target(object): 802 def start(self, tag, attrib): 803 events.append("start") 804 assertFalse(attrib) 805 assertEqual("TAG", tag)806 def end(self, tag): 807 events.append("end") 808 assertEqual("TAG", tag) 809 def close(self): 810 return "DONE" # no Element! 811 812 parser = self.etree.XMLParser(target=Target()) 813 tree = self.etree.ElementTree() 814 815 self.assertRaises(TypeError, 816 tree.parse, BytesIO("<TAG/>"), parser=parser) 817 self.assertEqual(["start", "end"], events) 818820 # ET doesn't call .close() on errors 821 events = [] 822 class Target(object): 823 def start(self, tag, attrib): 824 events.append("start-" + tag)825 def end(self, tag): 826 events.append("end-" + tag) 827 if tag == 'a': 828 raise ValueError("dead and gone") 829 def data(self, data): 830 events.append("data-" + data) 831 def close(self): 832 events.append("close") 833 return "DONE" 834 835 parser = self.etree.XMLParser(target=Target()) 836 837 try: 838 parser.feed(_bytes('<root>A<a>ca</a>B</root>')) 839 done = parser.close() 840 self.fail("error expected, but parsing succeeded") 841 except ValueError: 842 done = 'value error received as expected' 843 844 self.assertEqual(["start-root", "data-A", "start-a", 845 "data-ca", "end-a", "close"], 846 events) 847849 # ET doesn't call .close() on errors 850 events = [] 851 class Target(object): 852 def start(self, tag, attrib): 853 events.append("start-" + tag)854 def end(self, tag): 855 events.append("end-" + tag) 856 if tag == 'a': 857 raise ValueError("dead and gone") 858 def data(self, data): 859 events.append("data-" + data) 860 def close(self): 861 events.append("close") 862 return "DONE" 863 864 parser = self.etree.XMLParser(target=Target()) 865 866 try: 867 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'), 868 parser=parser) 869 self.fail("error expected, but parsing succeeded") 870 except ValueError: 871 done = 'value error received as expected' 872 873 self.assertEqual(["start-root", "data-A", "start-a", 874 "data-ca", "end-a", "close"], 875 events) 876878 events = [] 879 class Target(object): 880 def start(self, tag, attrib): 881 events.append("start-" + tag)882 def end(self, tag): 883 events.append("end-" + tag) 884 def data(self, data): 885 events.append("data-" + data) 886 def comment(self, text): 887 events.append("comment-" + text) 888 def close(self): 889 return "DONE" 890 891 parser = self.etree.XMLParser(target=Target()) 892 893 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->')) 894 done = parser.close() 895 896 self.assertEqual("DONE", done) 897 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b", 898 "start-sub", "end-sub", "comment-c", "data-B", 899 "end-root", "comment-d"], 900 events) 901903 events = [] 904 class Target(object): 905 def start(self, tag, attrib): 906 events.append("start-" + tag)907 def end(self, tag): 908 events.append("end-" + tag) 909 def data(self, data): 910 events.append("data-" + data) 911 def pi(self, target, data): 912 events.append("pi-" + target + "-" + data) 913 def close(self): 914 return "DONE" 915 916 parser = self.etree.XMLParser(target=Target()) 917 918 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>')) 919 done = parser.close() 920 921 self.assertEqual("DONE", done) 922 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b", 923 "data-B", "end-root", "pi-test-c"], 924 events) 925927 events = [] 928 class Target(object): 929 def start(self, tag, attrib): 930 events.append("start-" + tag)931 def end(self, tag): 932 events.append("end-" + tag) 933 def data(self, data): 934 events.append("data-" + data) 935 def close(self): 936 return "DONE" 937 938 parser = self.etree.XMLParser(target=Target(), 939 strip_cdata=False) 940 941 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>')) 942 done = parser.close() 943 944 self.assertEqual("DONE", done) 945 self.assertEqual(["start-root", "data-A", "start-a", 946 "data-ca", "end-a", "data-B", "end-root"], 947 events) 948950 events = [] 951 class Target(object): 952 def start(self, tag, attrib): 953 events.append("start-" + tag)954 def end(self, tag): 955 events.append("end-" + tag) 956 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 recover=True) 964 965 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>')) 966 done = parser.close() 967 968 self.assertEqual("DONE", done) 969 self.assertEqual(["start-root", "data-A", "start-a", 970 "data-ca", "end-a", "data-B", 971 "end-root", "close"], 972 events) 973975 iterwalk = self.etree.iterwalk 976 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 977 978 iterator = iterwalk(root, tag="b", events=('start', 'end')) 979 events = list(iterator) 980 self.assertEqual( 981 [('start', root[0]), ('end', root[0])], 982 events)983985 iterwalk = self.etree.iterwalk 986 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 987 988 iterator = iterwalk(root, tag="*", events=('start', 'end')) 989 events = list(iterator) 990 self.assertEqual( 991 8, 992 len(events))993995 iterwalk = self.etree.iterwalk 996 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 997 998 events = list(iterwalk(root)) 999 self.assertEqual( 1000 [('end', root[0]), ('end', root[1]), ('end', root)], 1001 events)10021004 iterwalk = self.etree.iterwalk 1005 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1006 1007 iterator = iterwalk(root, events=('start',)) 1008 events = list(iterator) 1009 self.assertEqual( 1010 [('start', root), ('start', root[0]), ('start', root[1])], 1011 events)10121014 iterwalk = self.etree.iterwalk 1015 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1016 1017 iterator = iterwalk(root, events=('start','end')) 1018 events = list(iterator) 1019 self.assertEqual( 1020 [('start', root), ('start', root[0]), ('end', root[0]), 1021 ('start', root[1]), ('end', root[1]), ('end', root)], 1022 events)10231025 iterwalk = self.etree.iterwalk 1026 root = self.etree.XML(_bytes('<a><b></b><c/></a>')) 1027 1028 iterator = iterwalk(root) 1029 for event, elem in iterator: 1030 elem.clear() 1031 1032 self.assertEqual(0, 1033 len(root))10341036 iterwalk = self.etree.iterwalk 1037 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>')) 1038 1039 attr_name = '{testns}bla' 1040 events = [] 1041 iterator = iterwalk(root, events=('start','end','start-ns','end-ns')) 1042 for event, elem in iterator: 1043 events.append(event) 1044 if event == 'start': 1045 if elem.tag != '{ns1}a': 1046 elem.set(attr_name, 'value') 1047 1048 self.assertEqual( 1049 ['start-ns', 'start', 'start', 'start-ns', 'start', 1050 'end', 'end-ns', 'end', 'end', 'end-ns'], 1051 events) 1052 1053 self.assertEqual( 1054 None, 1055 root.get(attr_name)) 1056 self.assertEqual( 1057 'value', 1058 root[0].get(attr_name))10591061 iterwalk = self.etree.iterwalk 1062 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>')) 1063 1064 counts = [] 1065 for event, elem in iterwalk(root): 1066 counts.append(len(list(elem.getiterator()))) 1067 self.assertEqual( 1068 [1,2,1,4], 1069 counts)10701072 parse = self.etree.parse 1073 parser = self.etree.XMLParser(dtd_validation=True) 1074 assertEqual = self.assertEqual 1075 test_url = _str("__nosuch.dtd") 1076 1077 class MyResolver(self.etree.Resolver): 1078 def resolve(self, url, id, context): 1079 assertEqual(url, test_url) 1080 return self.resolve_string( 1081 _str('''<!ENTITY myentity "%s"> 1082 <!ELEMENT doc ANY>''') % url, context)1083 1084 parser.resolvers.add(MyResolver()) 1085 1086 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1087 tree = parse(StringIO(xml), parser) 1088 root = tree.getroot() 1089 self.assertEqual(root.text, test_url) 10901092 parse = self.etree.parse 1093 parser = self.etree.XMLParser(dtd_validation=True) 1094 assertEqual = self.assertEqual 1095 test_url = _str("__nosuch.dtd") 1096 1097 class MyResolver(self.etree.Resolver): 1098 def resolve(self, url, id, context): 1099 assertEqual(url, test_url) 1100 return self.resolve_string( 1101 (_str('''<!ENTITY myentity "%s"> 1102 <!ELEMENT doc ANY>''') % url).encode('utf-8'), 1103 context)1104 1105 parser.resolvers.add(MyResolver()) 1106 1107 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1108 tree = parse(StringIO(xml), parser) 1109 root = tree.getroot() 1110 self.assertEqual(root.text, test_url) 11111113 parse = self.etree.parse 1114 parser = self.etree.XMLParser(dtd_validation=True) 1115 assertEqual = self.assertEqual 1116 test_url = _str("__nosuch.dtd") 1117 1118 class MyResolver(self.etree.Resolver): 1119 def resolve(self, url, id, context): 1120 assertEqual(url, test_url) 1121 return self.resolve_file( 1122 SillyFileLike( 1123 _str('''<!ENTITY myentity "%s"> 1124 <!ELEMENT doc ANY>''') % url), context)1125 1126 parser.resolvers.add(MyResolver()) 1127 1128 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1129 tree = parse(StringIO(xml), parser) 1130 root = tree.getroot() 1131 self.assertEqual(root.text, test_url) 11321134 parse = self.etree.parse 1135 parser = self.etree.XMLParser(attribute_defaults=True) 1136 assertEqual = self.assertEqual 1137 test_url = _str("__nosuch.dtd") 1138 1139 class MyResolver(self.etree.Resolver): 1140 def resolve(self, url, id, context): 1141 assertEqual(url, test_url) 1142 return self.resolve_filename( 1143 fileInTestDir('test.dtd'), context)1144 1145 parser.resolvers.add(MyResolver()) 1146 1147 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1148 tree = parse(StringIO(xml), parser) 1149 root = tree.getroot() 1150 self.assertEqual( 1151 root.attrib, {'default': 'valueA'}) 1152 self.assertEqual( 1153 root[0].attrib, {'default': 'valueB'}) 11541156 parse = self.etree.parse 1157 parser = self.etree.XMLParser(attribute_defaults=True) 1158 assertEqual = self.assertEqual 1159 test_url = _str("__nosuch.dtd") 1160 1161 class MyResolver(self.etree.Resolver): 1162 def resolve(self, url, id, context): 1163 assertEqual(url, fileInTestDir(test_url)) 1164 return self.resolve_filename( 1165 fileInTestDir('test.dtd'), context)1166 1167 parser.resolvers.add(MyResolver()) 1168 1169 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1170 tree = parse(StringIO(xml), parser, 1171 base_url=fileInTestDir('__test.xml')) 1172 root = tree.getroot() 1173 self.assertEqual( 1174 root.attrib, {'default': 'valueA'}) 1175 self.assertEqual( 1176 root[0].attrib, {'default': 'valueB'}) 11771179 parse = self.etree.parse 1180 parser = self.etree.XMLParser(attribute_defaults=True) 1181 assertEqual = self.assertEqual 1182 test_url = _str("__nosuch.dtd") 1183 1184 class MyResolver(self.etree.Resolver): 1185 def resolve(self, url, id, context): 1186 assertEqual(url, test_url) 1187 return self.resolve_file( 1188 open(fileInTestDir('test.dtd'), 'rb'), context)1189 1190 parser.resolvers.add(MyResolver()) 1191 1192 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url 1193 tree = parse(StringIO(xml), parser) 1194 root = tree.getroot() 1195 self.assertEqual( 1196 root.attrib, {'default': 'valueA'}) 1197 self.assertEqual( 1198 root[0].attrib, {'default': 'valueB'}) 11991201 parse = self.etree.parse 1202 parser = self.etree.XMLParser(load_dtd=True) 1203 assertEqual = self.assertEqual 1204 test_url = _str("__nosuch.dtd") 1205 1206 class check(object): 1207 resolved = False1208 1209 class MyResolver(self.etree.Resolver): 1210 def resolve(self, url, id, context): 1211 assertEqual(url, test_url) 1212 check.resolved = True 1213 return self.resolve_empty(context) 1214 1215 parser.resolvers.add(MyResolver()) 1216 1217 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url 1218 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser) 1219 self.assertTrue(check.resolved) 12201222 parse = self.etree.parse 1223 parser = self.etree.XMLParser(dtd_validation=True) 1224 1225 class _LocalException(Exception): 1226 pass1227 1228 class MyResolver(self.etree.Resolver): 1229 def resolve(self, url, id, context): 1230 raise _LocalException 1231 1232 parser.resolvers.add(MyResolver()) 1233 1234 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>' 1235 self.assertRaises(_LocalException, parse, BytesIO(xml), parser) 1236 1237 if etree.LIBXML_VERSION > (2,6,20):1239 parse = self.etree.parse 1240 tostring = self.etree.tostring 1241 parser = self.etree.XMLParser(resolve_entities=False) 1242 Entity = self.etree.Entity 1243 1244 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>') 1245 tree = parse(BytesIO(xml), parser) 1246 root = tree.getroot() 1247 self.assertEqual(root[0].tag, Entity) 1248 self.assertEqual(root[0].text, "&myentity;") 1249 self.assertEqual(root[0].tail, None) 1250 self.assertEqual(root[0].name, "myentity") 1251 1252 self.assertEqual(_bytes('<doc>&myentity;</doc>'), 1253 tostring(root))12541256 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]> 1257 <root> 1258 <child1/> 1259 <child2/> 1260 <child3> </child3> 1261 </root>''') 1262 1263 parser = self.etree.XMLParser(resolve_entities=False) 1264 root = etree.fromstring(xml, parser) 1265 self.assertEqual([ el.tag for el in root ], 1266 ['child1', 'child2', 'child3']) 1267 1268 root[0] = root[-1] 1269 self.assertEqual([ el.tag for el in root ], 1270 ['child3', 'child2']) 1271 self.assertEqual(root[0][0].text, ' ') 1272 self.assertEqual(root[0][0].name, 'nbsp')12731275 Entity = self.etree.Entity 1276 Element = self.etree.Element 1277 tostring = self.etree.tostring 1278 1279 root = Element("root") 1280 root.append( Entity("test") ) 1281 1282 self.assertEqual(root[0].tag, Entity) 1283 self.assertEqual(root[0].text, "&test;") 1284 self.assertEqual(root[0].tail, None) 1285 self.assertEqual(root[0].name, "test") 1286 1287 self.assertEqual(_bytes('<root>&test;</root>'), 1288 tostring(root))12891291 Entity = self.etree.Entity 1292 self.assertEqual(Entity("test").text, '&test;') 1293 self.assertEqual(Entity("#17683").text, '䔓') 1294 self.assertEqual(Entity("#x1768").text, 'ᝨ') 1295 self.assertEqual(Entity("#x98AF").text, '颯')12961298 Entity = self.etree.Entity 1299 self.assertRaises(ValueError, Entity, 'a b c') 1300 self.assertRaises(ValueError, Entity, 'a,b') 1301 self.assertRaises(ValueError, Entity, 'a\0b') 1302 self.assertRaises(ValueError, Entity, '#abc') 1303 self.assertRaises(ValueError, Entity, '#xxyz')13041306 CDATA = self.etree.CDATA 1307 Element = self.etree.Element 1308 tostring = self.etree.tostring 1309 1310 root = Element("root") 1311 root.text = CDATA('test') 1312 1313 self.assertEqual('test', 1314 root.text) 1315 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1316 tostring(root))13171319 CDATA = self.etree.CDATA 1320 Element = self.etree.Element 1321 root = Element("root") 1322 1323 root.text = CDATA("test") 1324 self.assertEqual('test', root.text) 1325 1326 root.text = CDATA(_str("test")) 1327 self.assertEqual('test', root.text) 1328 1329 self.assertRaises(TypeError, CDATA, 1)13301332 CDATA = self.etree.CDATA 1333 Element = self.etree.Element 1334 1335 root = Element("root") 1336 cdata = CDATA('test') 1337 1338 self.assertRaises(TypeError, 1339 setattr, root, 'tail', cdata) 1340 self.assertRaises(TypeError, 1341 root.set, 'attr', cdata) 1342 self.assertRaises(TypeError, 1343 operator.setitem, root.attrib, 'attr', cdata)13441346 tostring = self.etree.tostring 1347 parser = self.etree.XMLParser(strip_cdata=False) 1348 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1349 1350 self.assertEqual('test', root.text) 1351 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1352 tostring(root))13531355 tostring = self.etree.tostring 1356 parser = self.etree.XMLParser(strip_cdata=False) 1357 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser) 1358 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'), 1359 tostring(root)) 1360 1361 self.assertEqual(['test'], root.xpath('//text()'))1362 1363 # TypeError in etree, AssertionError in ElementTree;1365 Element = self.etree.Element 1366 SubElement = self.etree.SubElement 1367 1368 a = Element('a') 1369 b = SubElement(a, 'b') 1370 1371 self.assertRaises(TypeError, 1372 a.__setitem__, 0, 'foo')13731375 Element = self.etree.Element 1376 root = Element('root') 1377 # raises AssertionError in ElementTree 1378 self.assertRaises(TypeError, root.append, None) 1379 self.assertRaises(TypeError, root.extend, [None]) 1380 self.assertRaises(TypeError, root.extend, [Element('one'), None]) 1381 self.assertEqual('one', root[0].tag)13821384 Element = self.etree.Element 1385 SubElement = self.etree.SubElement 1386 root = Element('root') 1387 SubElement(root, 'a') 1388 SubElement(root, 'b') 1389 1390 self.assertEqual(['a', 'b'], 1391 [c.tag for c in root]) 1392 root[1].addnext(root[0]) 1393 self.assertEqual(['b', 'a'], 1394 [c.tag for c in root])13951397 Element = self.etree.Element 1398 SubElement = self.etree.SubElement 1399 root = Element('root') 1400 SubElement(root, 'a') 1401 SubElement(root, 'b') 1402 1403 self.assertEqual(['a', 'b'], 1404 [c.tag for c in root]) 1405 root[0].addprevious(root[1]) 1406 self.assertEqual(['b', 'a'], 1407 [c.tag for c in root])14081410 Element = self.etree.Element 1411 a = Element('a') 1412 b = Element('b') 1413 self.assertRaises(TypeError, a.addnext, b)14141416 Element = self.etree.Element 1417 a = Element('a') 1418 b = Element('b') 1419 self.assertRaises(TypeError, a.addnext, b)14201422 Element = self.etree.Element 1423 SubElement = self.etree.SubElement 1424 PI = self.etree.PI 1425 root = Element('root') 1426 SubElement(root, 'a') 1427 pi = PI('TARGET', 'TEXT') 1428 pi.tail = "TAIL" 1429 1430 self.assertEqual(_bytes('<root><a></a></root>'), 1431 self._writeElement(root)) 1432 root[0].addprevious(pi) 1433 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'), 1434 self._writeElement(root))14351437 Element = self.etree.Element 1438 PI = self.etree.PI 1439 root = Element('root') 1440 pi = PI('TARGET', 'TEXT') 1441 pi.tail = "TAIL" 1442 1443 self.assertEqual(_bytes('<root></root>'), 1444 self._writeElement(root)) 1445 root.addprevious(pi) 1446 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'), 1447 self._writeElement(root))14481450 Element = self.etree.Element 1451 SubElement = self.etree.SubElement 1452 PI = self.etree.PI 1453 root = Element('root') 1454 SubElement(root, 'a') 1455 pi = PI('TARGET', 'TEXT') 1456 pi.tail = "TAIL" 1457 1458 self.assertEqual(_bytes('<root><a></a></root>'), 1459 self._writeElement(root)) 1460 root[0].addnext(pi) 1461 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'), 1462 self._writeElement(root))14631465 Element = self.etree.Element 1466 PI = self.etree.PI 1467 root = Element('root') 1468 pi = PI('TARGET', 'TEXT') 1469 pi.tail = "TAIL" 1470 1471 self.assertEqual(_bytes('<root></root>'), 1472 self._writeElement(root)) 1473 root.addnext(pi) 1474 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'), 1475 self._writeElement(root))14761478 Element = self.etree.Element 1479 SubElement = self.etree.SubElement 1480 Comment = self.etree.Comment 1481 root = Element('root') 1482 SubElement(root, 'a') 1483 comment = Comment('TEXT ') 1484 comment.tail = "TAIL" 1485 1486 self.assertEqual(_bytes('<root><a></a></root>'), 1487 self._writeElement(root)) 1488 root[0].addnext(comment) 1489 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'), 1490 self._writeElement(root))14911493 Element = self.etree.Element 1494 Comment = self.etree.Comment 1495 root = Element('root') 1496 comment = Comment('TEXT ') 1497 comment.tail = "TAIL" 1498 1499 self.assertEqual(_bytes('<root></root>'), 1500 self._writeElement(root)) 1501 root.addnext(comment) 1502 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'), 1503 self._writeElement(root))15041506 Element = self.etree.Element 1507 SubElement = self.etree.SubElement 1508 Comment = self.etree.Comment 1509 root = Element('root') 1510 SubElement(root, 'a') 1511 comment = Comment('TEXT ') 1512 comment.tail = "TAIL" 1513 1514 self.assertEqual(_bytes('<root><a></a></root>'), 1515 self._writeElement(root)) 1516 root[0].addprevious(comment) 1517 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'), 1518 self._writeElement(root))15191521 Element = self.etree.Element 1522 Comment = self.etree.Comment 1523 root = Element('root') 1524 comment = Comment('TEXT ') 1525 comment.tail = "TAIL" 1526 1527 self.assertEqual(_bytes('<root></root>'), 1528 self._writeElement(root)) 1529 root.addprevious(comment) 1530 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'), 1531 self._writeElement(root))1532 1533 # ET's Elements have items() and key(), but not values()1535 XML = self.etree.XML 1536 1537 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>')) 1538 values = root.values() 1539 values.sort() 1540 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)1541 1542 # gives error in ElementTree1544 Element = self.etree.Element 1545 Comment = self.etree.Comment 1546 1547 a = Element('a') 1548 a.append(Comment()) 1549 self.assertEqual( 1550 _bytes('<a><!----></a>'), 1551 self._writeElement(a))1552 1553 # ElementTree ignores comments1555 ElementTree = self.etree.ElementTree 1556 tostring = self.etree.tostring 1557 1558 xml = _bytes('<a><b/><!----><c/></a>') 1559 f = BytesIO(xml) 1560 doc = ElementTree(file=f) 1561 a = doc.getroot() 1562 self.assertEqual( 1563 '', 1564 a[1].text) 1565 self.assertEqual( 1566 xml, 1567 tostring(a))1568 1569 # ElementTree ignores comments1571 ElementTree = self.etree.ElementTree 1572 1573 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>') 1574 doc = ElementTree(file=f) 1575 a = doc.getroot() 1576 self.assertEqual( 1577 ' hoi ', 1578 a[1].text)1579 1580 # does not raise an exception in ElementTree1582 Element = self.etree.Element 1583 Comment = self.etree.Comment 1584 1585 c = Comment() 1586 el = Element('myel') 1587 1588 self.assertRaises(TypeError, c.append, el) 1589 self.assertRaises(TypeError, c.insert, 0, el) 1590 self.assertRaises(TypeError, c.set, "myattr", "test")1591 1592 # test passing 'None' to dump 15951597 ElementTree = self.etree.ElementTree 1598 1599 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>') 1600 doc = ElementTree(file=f) 1601 a = doc.getroot() 1602 self.assertEqual( 1603 None, 1604 a.prefix) 1605 self.assertEqual( 1606 'foo', 1607 a[0].prefix)16081610 ElementTree = self.etree.ElementTree 1611 1612 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>') 1613 doc = ElementTree(file=f) 1614 a = doc.getroot() 1615 self.assertEqual( 1616 None, 1617 a.prefix) 1618 self.assertEqual( 1619 None, 1620 a[0].prefix)16211623 Element = self.etree.Element 1624 SubElement = self.etree.SubElement 1625 1626 a = Element('a') 1627 b = SubElement(a, 'b') 1628 c = SubElement(a, 'c') 1629 d = SubElement(b, 'd') 1630 self.assertEqual( 1631 None, 1632 a.getparent()) 1633 self.assertEqual( 1634 a, 1635 b.getparent()) 1636 self.assertEqual( 1637 b.getparent(), 1638 c.getparent()) 1639 self.assertEqual( 1640 b, 1641 d.getparent())16421644 XML = self.etree.XML 1645 1646 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 1647 result = [] 1648 for el in root.iterchildren(): 1649 result.append(el.tag) 1650 self.assertEqual(['one', 'two', 'three'], result)16511653 XML = self.etree.XML 1654 1655 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>')) 1656 result = [] 1657 for el in root.iterchildren(reversed=True): 1658 result.append(el.tag) 1659 self.assertEqual(['three', 'two', 'one'], result)16601662 XML = self.etree.XML 1663 1664 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 1665 result = [] 1666 for el in root.iterchildren(tag='two'): 1667 result.append(el.text) 1668 self.assertEqual(['Two', 'Bla'], result)16691671 XML = self.etree.XML 1672 1673 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>')) 1674 result = [] 1675 for el in root.iterchildren(reversed=True, tag='two'): 1676 result.append(el.text) 1677 self.assertEqual(['Bla', 'Two'], result)16781680 XML = self.etree.XML 1681 1682 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 1683 result = [] 1684 for el in root.iterchildren(tag=['two', 'three']): 1685 result.append(el.text) 1686 self.assertEqual(['Two', 'Bla', None], result)16871689 XML = self.etree.XML 1690 1691 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>')) 1692 result = [] 1693 for el in root.iterchildren(reversed=True, tag=['two', 'three']): 1694 result.append(el.text) 1695 self.assertEqual([None, 'Bla', 'Two'], result)16961698 Element = self.etree.Element 1699 SubElement = self.etree.SubElement 1700 1701 a = Element('a') 1702 b = SubElement(a, 'b') 1703 c = SubElement(a, 'c') 1704 d = SubElement(b, 'd') 1705 self.assertEqual( 1706 [], 1707 list(a.iterancestors())) 1708 self.assertEqual( 1709 [a], 1710 list(b.iterancestors())) 1711 self.assertEqual( 1712 [a], 1713 list(c.iterancestors())) 1714 self.assertEqual( 1715 [b, a], 1716 list(d.iterancestors()))17171719 Element = self.etree.Element 1720 SubElement = self.etree.SubElement 1721 1722 a = Element('a') 1723 b = SubElement(a, 'b') 1724 c = SubElement(a, 'c') 1725 d = SubElement(b, 'd') 1726 self.assertEqual( 1727 [a], 1728 list(d.iterancestors(tag='a'))) 1729 self.assertEqual( 1730 [b, a], 1731 list(d.iterancestors(tag='*')))17321734 Element = self.etree.Element 1735 SubElement = self.etree.SubElement 1736 1737 a = Element('a') 1738 b = SubElement(a, 'b') 1739 c = SubElement(a, 'c') 1740 d = SubElement(b, 'd') 1741 self.assertEqual( 1742 [b, a], 1743 list(d.iterancestors(tag=('a', 'b')))) 1744 self.assertEqual( 1745 [], 1746 list(d.iterancestors(tag=('w', 'x', 'y', 'z')))) 1747 self.assertEqual( 1748 [], 1749 list(d.iterancestors(tag=('d', 'x')))) 1750 self.assertEqual( 1751 [b, a], 1752 list(d.iterancestors(tag=('b', '*')))) 1753 self.assertEqual( 1754 [b], 1755 list(d.iterancestors(tag=('b', 'c'))))17561758 Element = self.etree.Element 1759 SubElement = self.etree.SubElement 1760 1761 a = Element('a') 1762 b = SubElement(a, 'b') 1763 c = SubElement(a, 'c') 1764 d = SubElement(b, 'd') 1765 e = SubElement(c, 'e') 1766 1767 self.assertEqual( 1768 [b, d, c, e], 1769 list(a.iterdescendants())) 1770 self.assertEqual( 1771 [], 1772 list(d.iterdescendants()))17731775 Element = self.etree.Element 1776 SubElement = self.etree.SubElement 1777 1778 a = Element('a') 1779 b = SubElement(a, 'b') 1780 c = SubElement(a, 'c') 1781 d = SubElement(b, 'd') 1782 e = SubElement(c, 'e') 1783 1784 self.assertEqual( 1785 [], 1786 list(a.iterdescendants('a'))) 1787 a2 = SubElement(e, 'a') 1788 self.assertEqual( 1789 [a2], 1790 list(a.iterdescendants('a'))) 1791 self.assertEqual( 1792 [a2], 1793 list(c.iterdescendants('a')))17941796 Element = self.etree.Element 1797 SubElement = self.etree.SubElement 1798 1799 a = Element('a') 1800 b = SubElement(a, 'b') 1801 c = SubElement(a, 'c') 1802 d = SubElement(b, 'd') 1803 e = SubElement(c, 'e') 1804 1805 self.assertEqual( 1806 [b, e], 1807 list(a.iterdescendants(tag=('a', 'b', 'e')))) 1808 a2 = SubElement(e, 'a') 1809 self.assertEqual( 1810 [b, a2], 1811 list(a.iterdescendants(tag=('a', 'b')))) 1812 self.assertEqual( 1813 [], 1814 list(c.iterdescendants(tag=('x', 'y', 'z')))) 1815 self.assertEqual( 1816 [b, d, c, e, a2], 1817 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))18181820 Element = self.etree.Element 1821 SubElement = self.etree.SubElement 1822 1823 a = Element('a') 1824 b = SubElement(a, 'b') 1825 c = SubElement(a, 'c') 1826 d = SubElement(b, 'd') 1827 self.assertEqual( 1828 a, 1829 a.getroottree().getroot()) 1830 self.assertEqual( 1831 a, 1832 b.getroottree().getroot()) 1833 self.assertEqual( 1834 a, 1835 d.getroottree().getroot())18361838 Element = self.etree.Element 1839 SubElement = self.etree.SubElement 1840 1841 a = Element('a') 1842 b = SubElement(a, 'b') 1843 c = SubElement(a, 'c') 1844 self.assertEqual( 1845 None, 1846 a.getnext()) 1847 self.assertEqual( 1848 c, 1849 b.getnext()) 1850 self.assertEqual( 1851 None, 1852 c.getnext())18531855 Element = self.etree.Element 1856 SubElement = self.etree.SubElement 1857 1858 a = Element('a') 1859 b = SubElement(a, 'b') 1860 c = SubElement(a, 'c') 1861 d = SubElement(b, 'd') 1862 self.assertEqual( 1863 None, 1864 a.getprevious()) 1865 self.assertEqual( 1866 b, 1867 c.getprevious()) 1868 self.assertEqual( 1869 None, 1870 b.getprevious())18711873 Element = self.etree.Element 1874 SubElement = self.etree.SubElement 1875 1876 a = Element('a') 1877 b = SubElement(a, 'b') 1878 c = SubElement(a, 'c') 1879 d = SubElement(b, 'd') 1880 self.assertEqual( 1881 [], 1882 list(a.itersiblings())) 1883 self.assertEqual( 1884 [c], 1885 list(b.itersiblings())) 1886 self.assertEqual( 1887 [], 1888 list(c.itersiblings())) 1889 self.assertEqual( 1890 [b], 1891 list(c.itersiblings(preceding=True))) 1892 self.assertEqual( 1893 [], 1894 list(b.itersiblings(preceding=True)))18951897 Element = self.etree.Element 1898 SubElement = self.etree.SubElement 1899 1900 a = Element('a') 1901 b = SubElement(a, 'b') 1902 c = SubElement(a, 'c') 1903 d = SubElement(b, 'd') 1904 self.assertEqual( 1905 [], 1906 list(a.itersiblings(tag='XXX'))) 1907 self.assertEqual( 1908 [c], 1909 list(b.itersiblings(tag='c'))) 1910 self.assertEqual( 1911 [c], 1912 list(b.itersiblings(tag='*'))) 1913 self.assertEqual( 1914 [b], 1915 list(c.itersiblings(preceding=True, tag='b'))) 1916 self.assertEqual( 1917 [], 1918 list(c.itersiblings(preceding=True, tag='c')))19191921 Element = self.etree.Element 1922 SubElement = self.etree.SubElement 1923 1924 a = Element('a') 1925 b = SubElement(a, 'b') 1926 c = SubElement(a, 'c') 1927 d = SubElement(b, 'd') 1928 e = SubElement(a, 'e') 1929 self.assertEqual( 1930 [], 1931 list(a.itersiblings(tag=('XXX', 'YYY')))) 1932 self.assertEqual( 1933 [c, e], 1934 list(b.itersiblings(tag=('c', 'd', 'e')))) 1935 self.assertEqual( 1936 [b], 1937 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd')))) 1938 self.assertEqual( 1939 [c, b], 1940 list(e.itersiblings(preceding=True, tag=('c', '*'))))19411943 parseid = self.etree.parseid 1944 XML = self.etree.XML 1945 xml_text = _bytes(''' 1946 <!DOCTYPE document [ 1947 <!ELEMENT document (h1,p)*> 1948 <!ELEMENT h1 (#PCDATA)> 1949 <!ATTLIST h1 myid ID #REQUIRED> 1950 <!ELEMENT p (#PCDATA)> 1951 <!ATTLIST p someid ID #REQUIRED> 1952 ]> 1953 <document> 1954 <h1 myid="chapter1">...</h1> 1955 <p id="note1" class="note">...</p> 1956 <p>Regular paragraph.</p> 1957 <p xml:id="xmlid">XML:ID paragraph.</p> 1958 <p someid="warn1" class="warning">...</p> 1959 </document> 1960 ''') 1961 1962 tree, dic = parseid(BytesIO(xml_text)) 1963 root = tree.getroot() 1964 root2 = XML(xml_text) 1965 self.assertEqual(self._writeElement(root), 1966 self._writeElement(root2)) 1967 expected = { 1968 "chapter1" :