1
2
3 """
4 Tests for the ElementTree API
5
6 Only test cases that apply equally well to etree and ElementTree
7 belong here. Note that there is a second test module called test_io.py
8 for IO related test cases.
9 """
10
11 from __future__ import absolute_import
12
13 import copy
14 import io
15 import operator
16 import os
17 import re
18 import sys
19 import textwrap
20 import unittest
21 from contextlib import contextmanager
22 from functools import wraps, partial
23 from itertools import islice
24
25 from .common_imports import (
26 BytesIO, etree, HelperTestCase,
27 ElementTree, cElementTree, ET_VERSION, CET_VERSION,
28 filter_by_version, fileInTestDir, canonicalize, tmpfile,
29 _str, _bytes, unicode, next, IS_PYTHON2
30 )
31
32 if cElementTree is not None and (CET_VERSION <= (1,0,7) or sys.version_info[0] >= 3):
33 cElementTree = None
34
35 if ElementTree is not None:
36 print("Comparing with ElementTree %s" % getattr(ElementTree, "VERSION", "?"))
37
38 if cElementTree is not None:
39 print("Comparing with cElementTree %s" % getattr(cElementTree, "VERSION", "?"))
43 def wrap(method):
44 @wraps(method)
45 def testfunc(self, *args):
46 if self.etree is not etree and sys.version_info < version:
47 raise unittest.SkipTest("requires ET in Python %s" % '.'.join(map(str, version)))
48 return method(self, *args)
49 return testfunc
50 return wrap
51
54 etree = None
55 required_versions_ET = {}
56 required_versions_cET = {}
57
65
66 try:
67 HelperTestCase.assertRegex
68 except AttributeError:
70 return self.assertRegexpMatches(*args, **kwargs)
71
72 @et_needs_pyversion(3, 6)
74
75
76 def check_string(string):
77 len(string)
78 for char in string:
79 self.assertEqual(len(char), 1,
80 msg="expected one-character string, got %r" % char)
81 new_string = string + ""
82 new_string = string + " "
83 string[:0]
84
85 def check_mapping(mapping):
86 len(mapping)
87 keys = mapping.keys()
88 items = mapping.items()
89 for key in keys:
90 item = mapping[key]
91 mapping["key"] = "value"
92 self.assertEqual(mapping["key"], "value",
93 msg="expected value string, got %r" % mapping["key"])
94
95 def check_element(element):
96 self.assertTrue(self.etree.iselement(element), msg="not an element")
97 direlem = dir(element)
98 for attr in 'tag', 'attrib', 'text', 'tail':
99 self.assertTrue(hasattr(element, attr),
100 msg='no %s member' % attr)
101 self.assertIn(attr, direlem,
102 msg='no %s visible by dir' % attr)
103
104 check_string(element.tag)
105 check_mapping(element.attrib)
106 if element.text is not None:
107 check_string(element.text)
108 if element.tail is not None:
109 check_string(element.tail)
110 for elem in element:
111 check_element(elem)
112
113 element = self.etree.Element("tag")
114 check_element(element)
115 tree = self.etree.ElementTree(element)
116 check_element(tree.getroot())
117 element = self.etree.Element(u"t\xe4g", key="value")
118 tree = self.etree.ElementTree(element)
119
120
121 element = self.etree.Element("tag", key="value")
122
123
124
125 def check_method(method):
126 self.assertTrue(hasattr(method, '__call__'),
127 msg="%s not callable" % method)
128
129 check_method(element.append)
130 check_method(element.extend)
131 check_method(element.insert)
132 check_method(element.remove)
133
134
135 check_method(element.find)
136 check_method(element.iterfind)
137 check_method(element.findall)
138 check_method(element.findtext)
139 check_method(element.clear)
140 check_method(element.get)
141 check_method(element.set)
142 check_method(element.keys)
143 check_method(element.items)
144 check_method(element.iter)
145 check_method(element.itertext)
146
147
148
149
150
151 def check_iter(it):
152 check_method(it.next if IS_PYTHON2 else it.__next__)
153
154 check_iter(element.iterfind("tag"))
155 check_iter(element.iterfind("*"))
156 check_iter(tree.iterfind("tag"))
157 check_iter(tree.iterfind("*"))
158
159
160
161
162
163 self.assertEqual(self.etree.PI, self.etree.ProcessingInstruction)
164
166 for i in range(10):
167 e = self.etree.Element('foo')
168 self.assertEqual(e.tag, 'foo')
169 self.assertEqual(e.text, None)
170 self.assertEqual(e.tail, None)
171
184
185
195
208
210 Element = self.etree.Element
211 SubElement = self.etree.SubElement
212
213 root1 = Element('root')
214 SubElement(root1, 'one')
215 self.assertTrue(root1[0] in root1)
216
217 root2 = Element('root')
218 SubElement(root2, 'two')
219 SubElement(root2, 'three')
220 self.assertTrue(root2[0] in root2)
221 self.assertTrue(root2[1] in root2)
222
223 self.assertFalse(root1[0] in root2)
224 self.assertFalse(root2[0] in root1)
225 self.assertFalse(None in root2)
226
228 ElementTree = self.etree.ElementTree
229
230 f = BytesIO('<doc>Test<one>One</one></doc>')
231 doc = ElementTree(file=f)
232 root = doc.getroot()
233 self.assertEqual(1, len(root))
234 self.assertEqual('one', root[0].tag)
235 self.assertRaises(IndexError, operator.getitem, root, 1)
236
238 ElementTree = self.etree.ElementTree
239
240 f = BytesIO('<doc><one>One</one><two>Two</two>hm<three>Three</three></doc>')
241 doc = ElementTree(file=f)
242 root = doc.getroot()
243 self.assertEqual(3, len(root))
244 self.assertEqual('one', root[0].tag)
245 self.assertEqual('two', root[1].tag)
246 self.assertEqual('three', root[2].tag)
247
249 ElementTree = self.etree.ElementTree
250
251 f = BytesIO('<doc>Test</doc>')
252 doc = ElementTree(file=f)
253 root = doc.getroot()
254 self.assertEqual(0, len(root))
255
257 Element = self.etree.Element
258 SubElement = self.etree.SubElement
259 a = Element('a')
260 b = SubElement(a, 'b')
261 c = SubElement(a, 'c')
262 d = SubElement(a, 'd')
263 self.assertEqual(d, a[-1])
264 self.assertEqual(c, a[-2])
265 self.assertEqual(b, a[-3])
266 self.assertRaises(IndexError, operator.getitem, a, -4)
267 a[-1] = e = Element('e')
268 self.assertEqual(e, a[-1])
269 del a[-1]
270 self.assertEqual(2, len(a))
271
281
282 - def test_text(self):
283 ElementTree = self.etree.ElementTree
284
285 f = BytesIO('<doc>This is a text</doc>')
286 doc = ElementTree(file=f)
287 root = doc.getroot()
288 self.assertEqual('This is a text', root.text)
289
290 - def test_text_empty(self):
291 ElementTree = self.etree.ElementTree
292
293 f = BytesIO('<doc></doc>')
294 doc = ElementTree(file=f)
295 root = doc.getroot()
296 self.assertEqual(None, root.text)
297
298 - def test_text_other(self):
299 ElementTree = self.etree.ElementTree
300
301 f = BytesIO('<doc><one>One</one></doc>')
302 doc = ElementTree(file=f)
303 root = doc.getroot()
304 self.assertEqual(None, root.text)
305 self.assertEqual('One', root[0].text)
306
308 ElementTree = self.etree.ElementTree
309
310 f = BytesIO('<doc>This is > than a text</doc>')
311 doc = ElementTree(file=f)
312 root = doc.getroot()
313 self.assertEqual('This is > than a text', root.text)
314
316 Element = self.etree.Element
317
318 a = Element("a")
319 a.text = "<>&"
320 self.assertXML(_bytes('<a><>&</a>'),
321 a)
322
324 tostring = self.etree.tostring
325 Element = self.etree.Element
326
327 a = Element("a")
328 a.text = "<>&"
329 self.assertEqual(_bytes('<a><>&</a>'),
330 tostring(a))
331
333 Element = self.etree.Element
334
335 class strTest(str):
336 pass
337
338 a = Element("a")
339 a.text = strTest("text")
340 self.assertXML(_bytes('<a>text</a>'),
341 a)
342
354
361
362 a = Element("a")
363 SubElement(a, "t").tail = strTest("tail")
364 self.assertXML(_bytes('<a><t></t>tail</a>'),
365 a)
366
368
369 XML = self.etree.XML
370
371 root = XML(_bytes('<doc>This is <i>mixed</i> content.</doc>'))
372 self.assertEqual(1, len(root))
373 self.assertEqual('This is ', root.text)
374 self.assertEqual(None, root.tail)
375 self.assertEqual('mixed', root[0].text)
376 self.assertEqual(' content.', root[0].tail)
377
378 del root[0].tail
379
380 self.assertEqual(1, len(root))
381 self.assertEqual('This is ', root.text)
382 self.assertEqual(None, root.tail)
383 self.assertEqual('mixed', root[0].text)
384 self.assertEqual(None, root[0].tail)
385
386 root[0].tail = "TAIL"
387
388 self.assertEqual(1, len(root))
389 self.assertEqual('This is ', root.text)
390 self.assertEqual(None, root.tail)
391 self.assertEqual('mixed', root[0].text)
392 self.assertEqual('TAIL', root[0].tail)
393
403
413
424
435
446
457
468
478
489
491 Element = self.etree.Element
492 SubElement = self.etree.SubElement
493
494 attribNS = '{http://foo/bar}x'
495
496 parent = Element('parent')
497 parent.set(attribNS, 'a')
498 child = SubElement(parent, 'child')
499 child.set(attribNS, 'b')
500
501 self.assertEqual('a', parent.get(attribNS))
502 self.assertEqual('b', child.get(attribNS))
503
504 parent.clear()
505 self.assertEqual(None, parent.get(attribNS))
506 self.assertEqual('b', child.get(attribNS))
507
521
528
532
536
540
542 XML = self.etree.XML
543
544 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
545 items = list(root.attrib.items())
546 items.sort()
547 self.assertEqual(
548 [('alpha', 'Alpha'), ('beta', 'Beta')],
549 items)
550
551 root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'})
552
553 items = list(root.attrib.items())
554 items.sort()
555 self.assertEqual(
556 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
557 items)
558
560 XML = self.etree.XML
561
562 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
563 items = list(root.attrib.items())
564 items.sort()
565 self.assertEqual(
566 [('alpha', 'Alpha'), ('beta', 'Beta')],
567 items)
568
569 root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'}.items())
570
571 items = list(root.attrib.items())
572 items.sort()
573 self.assertEqual(
574 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
575 items)
576
578 XML = self.etree.XML
579
580 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
581 items = list(root.attrib.items())
582 items.sort()
583 self.assertEqual(
584 [('alpha', 'Alpha'), ('beta', 'Beta')],
585 items)
586
587 root.attrib.update(iter({'alpha' : 'test', 'gamma' : 'Gamma'}.items()))
588
589 items = list(root.attrib.items())
590 items.sort()
591 self.assertEqual(
592 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
593 items)
594
596 XML = self.etree.XML
597
598 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
599 items = list(root.attrib.items())
600 items.sort()
601 self.assertEqual(
602 [('alpha', 'Alpha'), ('beta', 'Beta')],
603 items)
604
605 other = XML(_bytes('<doc alpha="test" gamma="Gamma"/>'))
606 root.attrib.update(other.attrib)
607
608 items = list(root.attrib.items())
609 items.sort()
610 self.assertEqual(
611 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
612 items)
613
621
629
631 XML = self.etree.XML
632
633 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
634 items = list(root.items())
635 items.sort()
636 self.assertEqual(
637 [('alpha','Alpha'), ('beta','Beta'), ('gamma','Gamma')],
638 items)
639
641 XML = self.etree.XML
642
643 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
644 keys = list(root.keys())
645 keys.sort()
646 self.assertEqual(['bar', '{http://ns.codespeak.net/test}baz'],
647 keys)
648
656
665
678
680 XML = self.etree.XML
681
682 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
683 items = list(root.attrib.items())
684 items.sort()
685 self.assertEqual(
686 [('bar', 'Bar'), ('{http://ns.codespeak.net/test}baz', 'Baz')],
687 items)
688
690 XML = self.etree.XML
691
692 expected = "{'{http://ns.codespeak.net/test}baz': 'Baz', 'bar': 'Bar'}"
693 alternative = "{'bar': 'Bar', '{http://ns.codespeak.net/test}baz': 'Baz'}"
694
695 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
696 try:
697 self.assertEqual(expected, str(root.attrib))
698 except AssertionError:
699 self.assertEqual(alternative, str(root.attrib))
700
702 XML = self.etree.XML
703
704 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
705 self.assertEqual(
706 True, 'bar' in root.attrib)
707 self.assertEqual(
708 False, 'baz' in root.attrib)
709 self.assertEqual(
710 False, 'hah' in root.attrib)
711 self.assertEqual(
712 True,
713 '{http://ns.codespeak.net/test}baz' in root.attrib)
714
721
731
733 XML = self.etree.XML
734
735 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma" />'))
736 result = []
737 for key in root.attrib:
738 result.append(key)
739 result.sort()
740 self.assertEqual(['alpha', 'beta', 'gamma'], result)
741
751
753 Element = self.etree.Element
754
755 a = Element('a')
756 a.attrib['{http://a/}foo'] = 'Foo'
757 a.attrib['{http://a/}bar'] = 'Bar'
758 self.assertEqual(None, a.get('foo'))
759 self.assertEqual('Foo', a.get('{http://a/}foo'))
760 self.assertEqual('Foo', a.attrib['{http://a/}foo'])
761
762 self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
763 self.assertEqual('Foo', a.attrib['{http://a/}foo'])
764
765 del a.attrib['{http://a/}foo']
766 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
767
769 XML = self.etree.XML
770
771 a = XML(_bytes('<a xmlns:nsa="http://a/" nsa:foo="FooNS" foo="Foo" />'))
772
773 self.assertEqual('Foo', a.attrib['foo'])
774 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
775
776 del a.attrib['foo']
777 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
778 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
779 self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
780
781 del a.attrib['{http://a/}foo']
782 self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
783 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
784
785 a = XML(_bytes('<a xmlns:nsa="http://a/" foo="Foo" nsa:foo="FooNS" />'))
786
787 self.assertEqual('Foo', a.attrib['foo'])
788 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
789
790 del a.attrib['foo']
791 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
792 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
793
794 del a.attrib['{http://a/}foo']
795 self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
796 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
797
804
806 XMLID = self.etree.XMLID
807 XML = self.etree.XML
808 xml_text = _bytes('''
809 <document>
810 <h1 id="chapter1">...</h1>
811 <p id="note1" class="note">...</p>
812 <p>Regular paragraph.</p>
813 <p xml:id="xmlid">XML:ID paragraph.</p>
814 <p id="warn1" class="warning">...</p>
815 </document>
816 ''')
817
818 root, dic = XMLID(xml_text)
819 root2 = XML(xml_text)
820 self.assertEqual(self._writeElement(root),
821 self._writeElement(root2))
822 expected = {
823 "chapter1" : root[0],
824 "note1" : root[1],
825 "warn1" : root[4]
826 }
827 self.assertEqual(dic, expected)
828
835
836 required_versions_ET['test_fromstringlist'] = (1,3)
844
845 required_versions_ET['test_fromstringlist_characters'] = (1,3)
852
853 required_versions_ET['test_fromstringlist_single'] = (1,3)
860
884
886 XML = self.etree.XML
887
888 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
889 result = []
890 for el in root:
891 result.append(el.tag)
892 self.assertEqual(['one', 'two', 'three'], result)
893
902
904 XML = self.etree.XML
905
906 root = XML(_bytes('<doc>Text</doc>'))
907 result = []
908 for el in root:
909 result.append(el.tag)
910 self.assertEqual([], result)
911
918
925
927 XML = self.etree.XML
928 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
929 result = []
930 for el in reversed(root):
931 result.append(el.tag)
932 self.assertEqual(['three', 'two', 'one'], result)
933
946
948 XML = self.etree.XML
949
950 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
951 result = []
952 for el in root:
953 result.append(el.tag)
954 del root[-1]
955 self.assertEqual(['one', 'two'], result)
956
958 XML = self.etree.XML
959
960 root = XML(_bytes('<doc><one/><two/></doc>'))
961 result = []
962 for el0 in root:
963 result.append(el0.tag)
964 for el1 in root:
965 result.append(el1.tag)
966 self.assertEqual(['one','one', 'two', 'two', 'one', 'two'], result)
967
968 required_versions_ET['test_itertext'] = (1,3)
969 - def test_itertext(self):
970
971 XML = self.etree.XML
972 root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
973
974 text = list(root.itertext())
975 self.assertEqual(["RTEXT", "ATAIL", "CTEXT", "CTAIL"],
976 text)
977
978 required_versions_ET['test_itertext_child'] = (1,3)
980
981 XML = self.etree.XML
982 root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
983
984 text = list(root[2].itertext())
985 self.assertEqual(["CTEXT"],
986 text)
987
997
999 XML = self.etree.XML
1000 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
1001 self.assertEqual(len(list(root.findall(".//{X}b"))), 2)
1002 self.assertEqual(len(list(root.findall(".//b"))), 3)
1003 self.assertEqual(len(list(root.findall("b"))), 2)
1004
1005 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
1007 def summarize_list(l):
1008 return [el.tag for el in l]
1009
1010 root = self.etree.XML('''
1011 <a xmlns:x="X" xmlns:y="Y">
1012 <x:b><c/></x:b>
1013 <b/>
1014 <c><x:b/><b/></c><y:b/>
1015 </a>''')
1016 root.append(self.etree.Comment('test'))
1017
1018 self.assertEqual(summarize_list(root.findall("{*}b")),
1019 ['{X}b', 'b', '{Y}b'])
1020 self.assertEqual(summarize_list(root.findall("{*}c")),
1021 ['c'])
1022 self.assertEqual(summarize_list(root.findall("{X}*")),
1023 ['{X}b'])
1024 self.assertEqual(summarize_list(root.findall("{Y}*")),
1025 ['{Y}b'])
1026 self.assertEqual(summarize_list(root.findall("{}*")),
1027 ['b', 'c'])
1028 self.assertEqual(summarize_list(root.findall("{}b")),
1029 ['b'])
1030 self.assertEqual(summarize_list(root.findall("{}b")),
1031 summarize_list(root.findall("b")))
1032 self.assertEqual(summarize_list(root.findall("{*}*")),
1033 ['{X}b', 'b', 'c', '{Y}b'])
1034 self.assertEqual(summarize_list(root.findall("{*}*")
1035 + ([] if self.etree is etree else [root[-1]])),
1036 summarize_list(root.findall("*")))
1037
1038 self.assertEqual(summarize_list(root.findall(".//{*}b")),
1039 ['{X}b', 'b', '{X}b', 'b', '{Y}b'])
1040 self.assertEqual(summarize_list(root.findall(".//{*}c")),
1041 ['c', 'c'])
1042 self.assertEqual(summarize_list(root.findall(".//{X}*")),
1043 ['{X}b', '{X}b'])
1044 self.assertEqual(summarize_list(root.findall(".//{Y}*")),
1045 ['{Y}b'])
1046 self.assertEqual(summarize_list(root.findall(".//{}*")),
1047 ['c', 'b', 'c', 'b'])
1048 self.assertEqual(summarize_list(root.findall(".//{}b")),
1049 ['b', 'b'])
1050
1057
1064
1066 Element = self.etree.Element
1067
1068 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, baz='Baz')
1069 self.assertEqual('Foo', el.attrib['foo'])
1070 self.assertEqual('Bar', el.attrib['bar'])
1071 self.assertEqual('Baz', el.attrib['baz'])
1072
1074 Element = self.etree.Element
1075
1076 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, bar='Baz')
1077 self.assertEqual('Foo', el.attrib['foo'])
1078 self.assertEqual('Baz', el.attrib['bar'])
1079
1081 Element = self.etree.Element
1082
1083 el = Element('tag', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
1084 self.assertEqual('Foo', el.attrib['{ns1}foo'])
1085 self.assertEqual('Bar', el.attrib['{ns2}bar'])
1086
1095
1104
1118
1119 required_versions_ET['test_write_method_html'] = (1,3)
1138
1139 required_versions_ET['test_write_method_text'] = (1,3)
1141 ElementTree = self.etree.ElementTree
1142 Element = self.etree.Element
1143 SubElement = self.etree.SubElement
1144
1145 a = Element('a')
1146 a.text = "A"
1147 a.tail = "tail"
1148 b = SubElement(a, 'b')
1149 b.text = "B"
1150 b.tail = "TAIL"
1151 c = SubElement(a, 'c')
1152 c.text = "C"
1153
1154 tree = ElementTree(element=a)
1155 f = BytesIO()
1156 tree.write(f, method="text")
1157 data = f.getvalue()
1158
1159 self.assertEqual(_bytes('ABTAILCtail'),
1160 data)
1161
1169
1170
1171
1180
1181
1193
1216
1217 - def test_set_text(self):
1218 Element = self.etree.Element
1219 SubElement = self.etree.SubElement
1220
1221 a = Element('a')
1222 b = SubElement(a, 'b')
1223 a.text = 'hoi'
1224 self.assertEqual(
1225 'hoi',
1226 a.text)
1227 self.assertEqual(
1228 'b',
1229 a[0].tag)
1230
1231 - def test_set_text2(self):
1232 Element = self.etree.Element
1233 SubElement = self.etree.SubElement
1234
1235 a = Element('a')
1236 a.text = 'hoi'
1237 b = SubElement(a ,'b')
1238 self.assertEqual(
1239 'hoi',
1240 a.text)
1241 self.assertEqual(
1242 'b',
1243 a[0].tag)
1244
1246 Element = self.etree.Element
1247
1248 a = Element('a')
1249
1250 a.text = 'foo'
1251 a.text = None
1252
1253 self.assertEqual(
1254 None,
1255 a.text)
1256 self.assertXML(_bytes('<a></a>'), a)
1257
1259 Element = self.etree.Element
1260
1261 a = Element('a')
1262 self.assertEqual(None, a.text)
1263
1264 a.text = ''
1265 self.assertEqual('', a.text)
1266 self.assertXML(_bytes('<a></a>'), a)
1267
1282
1292
1304
1314
1315 required_versions_ET['test_extend'] = (1,3)
1317 root = self.etree.Element('foo')
1318 for i in range(3):
1319 element = self.etree.SubElement(root, 'a%s' % i)
1320 element.text = "text%d" % i
1321 element.tail = "tail%d" % i
1322
1323 elements = []
1324 for i in range(3):
1325 new_element = self.etree.Element("test%s" % i)
1326 new_element.text = "TEXT%s" % i
1327 new_element.tail = "TAIL%s" % i
1328 elements.append(new_element)
1329
1330 root.extend(elements)
1331
1332 self.assertEqual(
1333 ["a0", "a1", "a2", "test0", "test1", "test2"],
1334 [ el.tag for el in root ])
1335 self.assertEqual(
1336 ["text0", "text1", "text2", "TEXT0", "TEXT1", "TEXT2"],
1337 [ el.text for el in root ])
1338 self.assertEqual(
1339 ["tail0", "tail1", "tail2", "TAIL0", "TAIL1", "TAIL2"],
1340 [ el.tail for el in root ])
1341
1351
1352
1353 required_versions_ET['test_comment_text'] = (1,3)
1374
1375
1376 required_versions_ET['test_comment_whitespace'] = (1,3)
1389
1401
1413
1425
1427 ProcessingInstruction = self.etree.ProcessingInstruction
1428 pi = ProcessingInstruction('foo')
1429 self.assertEqual({}, pi.attrib)
1430 self.assertEqual([], list(pi.keys()))
1431 self.assertEqual([], list(pi.items()))
1432 self.assertEqual(None, pi.get('hoi'))
1433 self.assertEqual(0, len(pi))
1434
1435 for i in pi:
1436 pass
1437
1453
1471
1481
1490
1505
1522
1540
1559
1565
1566 a = Element("a")
1567 a.tag = strTest("TAG")
1568 self.assertXML(_bytes('<TAG></TAG>'),
1569 a)
1570
1600
1602 Element = self.etree.Element
1603 SubElement = self.etree.SubElement
1604
1605 a = Element('a')
1606 b = SubElement(a, 'b')
1607 bs = SubElement(b, 'bs')
1608 c = SubElement(a, 'c')
1609 cs = SubElement(c, 'cs')
1610
1611 el = a[0]
1612 self.assertXML(
1613 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1614 a)
1615 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1616 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1617
1618 del a[0]
1619 self.assertXML(
1620 _bytes('<a><c><cs></cs></c></a>'),
1621 a)
1622 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1623 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1624
1625 a.insert(0, el)
1626 self.assertXML(
1627 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1628 a)
1629 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1630 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1631
1650
1669
1671 XML = self.etree.XML
1672 a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
1673 b, c = a
1674
1675 a[:] = []
1676
1677 self.assertEqual("B2", b.tail)
1678 self.assertEqual("C2", c.tail)
1679
1681 XML = self.etree.XML
1682 root = XML(_bytes(
1683 '<foo><bar xmlns:baz="http://huhu"><puh><baz:bump1 /><baz:bump2 /></puh></bar></foo>'))
1684 root[:] = root.findall('.//puh')
1685
1686
1687 result = self.etree.tostring(root)
1688 foo = self.etree.fromstring(result)
1689
1690 self.assertEqual('puh', foo[0].tag)
1691 self.assertEqual('{http://huhu}bump1', foo[0][0].tag)
1692 self.assertEqual('{http://huhu}bump2', foo[0][1].tag)
1693
1703
1716
1718 Element = self.etree.Element
1719
1720 a = Element('a')
1721 a.text = 'foo'
1722 a.tail = 'bar'
1723 a.set('hoi', 'dag')
1724 a.clear()
1725 self.assertEqual(None, a.text)
1726 self.assertEqual(None, a.tail)
1727 self.assertEqual(None, a.get('hoi'))
1728 self.assertEqual('a', a.tag)
1729
1731 Element = self.etree.Element
1732 SubElement = self.etree.SubElement
1733
1734 a = Element('a')
1735 a.text = 'foo'
1736 a.tail = 'bar'
1737 a.set('hoi', 'dag')
1738 b = SubElement(a, 'b')
1739 c = SubElement(b, 'c')
1740 a.clear()
1741 self.assertEqual(None, a.text)
1742 self.assertEqual(None, a.tail)
1743 self.assertEqual(None, a.get('hoi'))
1744 self.assertEqual('a', a.tag)
1745 self.assertEqual(0, len(a))
1746 self.assertXML(_bytes('<a></a>'),
1747 a)
1748 self.assertXML(_bytes('<b><c></c></b>'),
1749 b)
1750
1760
1787
1789
1790 Element = self.etree.Element
1791 SubElement = self.etree.SubElement
1792
1793
1794 import uuid
1795 names = dict((k, 'tag-' + str(uuid.uuid4())) for k in 'abcde')
1796
1797 a = Element(names['a'])
1798 b = SubElement(a, names['b'])
1799 c = SubElement(a, names['c'])
1800 d = Element(names['d'])
1801 a.insert(0, d)
1802
1803 self.assertEqual(
1804 d,
1805 a[0])
1806
1807 self.assertXML(
1808 _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(c)s></%(c)s></%(a)s>' % names),
1809 a)
1810
1811 e = Element(names['e'])
1812 a.insert(2, e)
1813 self.assertEqual(
1814 e,
1815 a[2])
1816 self.assertXML(
1817 _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(e)s></%(e)s><%(c)s></%(c)s></%(a)s>' % names),
1818 a)
1819
1835
1852
1867
1883
1899
1910
1923
1937
1946
1947 required_versions_ET['test_iter'] = (1,3)
1949 Element = self.etree.Element
1950 SubElement = self.etree.SubElement
1951
1952 a = Element('a')
1953 b = SubElement(a, 'b')
1954 c = SubElement(a, 'c')
1955 d = SubElement(b, 'd')
1956 e = SubElement(c, 'e')
1957
1958 self.assertEqual(
1959 [a, b, d, c, e],
1960 list(a.iter()))
1961 self.assertEqual(
1962 [d],
1963 list(d.iter()))
1964
1992
1994 Element = self.etree.Element
1995 SubElement = self.etree.SubElement
1996
1997 a = Element('a')
1998 b = SubElement(a, 'b')
1999 c = SubElement(a, 'c')
2000 d = SubElement(a, 'd')
2001
2002 self.assertEqual(
2003 [b, c],
2004 a[0:2])
2005 self.assertEqual(
2006 [b, c, d],
2007 a[:])
2008 self.assertEqual(
2009 [b, c, d],
2010 a[:10])
2011 self.assertEqual(
2012 [b],
2013 a[0:1])
2014 self.assertEqual(
2015 [],
2016 a[10:12])
2017
2019 Element = self.etree.Element
2020 SubElement = self.etree.SubElement
2021
2022 a = Element('a')
2023 b = SubElement(a, 'b')
2024 c = SubElement(a, 'c')
2025 d = SubElement(a, 'd')
2026
2027 self.assertEqual(
2028 [d],
2029 a[-1:])
2030 self.assertEqual(
2031 [c, d],
2032 a[-2:])
2033 self.assertEqual(
2034 [c],
2035 a[-2:-1])
2036 self.assertEqual(
2037 [b, c],
2038 a[-3:-1])
2039 self.assertEqual(
2040 [b, c],
2041 a[-3:2])
2042
2044 Element = self.etree.Element
2045 SubElement = self.etree.SubElement
2046
2047 a = Element('a')
2048 b = SubElement(a, 'b')
2049 c = SubElement(a, 'c')
2050 d = SubElement(a, 'd')
2051 e = SubElement(a, 'e')
2052
2053 self.assertEqual(
2054 [e,d,c,b],
2055 a[::-1])
2056 self.assertEqual(
2057 [b,d],
2058 a[::2])
2059 self.assertEqual(
2060 [e,c],
2061 a[::-2])
2062 self.assertEqual(
2063 [d,c],
2064 a[-2:0:-1])
2065 self.assertEqual(
2066 [e],
2067 a[:1:-2])
2068
2070 ElementTree = self.etree.ElementTree
2071
2072 f = BytesIO('<a><b>B</b>B1<c>C</c>C1</a>')
2073 doc = ElementTree(file=f)
2074 a = doc.getroot()
2075 b = a[0]
2076 c = a[1]
2077 self.assertEqual(
2078 [b, c],
2079 a[:])
2080 self.assertEqual(
2081 [b],
2082 a[0:1])
2083 self.assertEqual(
2084 [c],
2085 a[1:])
2086
2110
2125
2140
2155
2170
2185
2200
2210
2212 ElementTree = self.etree.ElementTree
2213 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2214 doc = ElementTree(file=f)
2215 a = doc.getroot()
2216 b, c, d, e = a
2217 del a[1:3]
2218 self.assertXML(
2219 _bytes('<a><b></b>B2<e></e>E2</a>'),
2220 a)
2221 self.assertEqual("B2", b.tail)
2222 self.assertEqual("C2", c.tail)
2223 self.assertEqual("D2", d.tail)
2224 self.assertEqual("E2", e.tail)
2225
2227 XML = self.etree.XML
2228 a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
2229 b, c = a
2230
2231 del a[:]
2232
2233 self.assertEqual("B2", b.tail)
2234 self.assertEqual("C2", c.tail)
2235
2246
2248 Element = self.etree.Element
2249 SubElement = self.etree.SubElement
2250
2251 a = Element('a')
2252 b = SubElement(a, 'b')
2253 c = SubElement(a, 'c')
2254 d = SubElement(a, 'd')
2255
2256 e = Element('e')
2257 f = Element('f')
2258 g = Element('g')
2259
2260 s = [e, f, g]
2261 a[1:2] = s
2262 self.assertEqual(
2263 [b, e, f, g, d],
2264 list(a))
2265
2283
2299
2314
2329
2331 Element = self.etree.Element
2332 SubElement = self.etree.SubElement
2333
2334 a = Element('{ns}a')
2335 b = SubElement(a, '{ns}b', {'{ns1}a1': 'test'})
2336 c = SubElement(a, '{ns}c', {'{ns2}a2': 'test'})
2337 d = SubElement(a, '{ns}d', {'{ns3}a3': 'test'})
2338
2339 s = [d, c, b]
2340 a[:] = s
2341 self.assertEqual(
2342 [d, c, b],
2343 list(a))
2344 self.assertEqual(
2345 ['{ns}d', '{ns}c', '{ns}b'],
2346 [ child.tag for child in a ])
2347
2348 self.assertEqual(
2349 [['{ns3}a3'], ['{ns2}a2'], ['{ns1}a1']],
2350 [ list(child.attrib.keys()) for child in a ])
2351
2353 Element = self.etree.Element
2354 SubElement = self.etree.SubElement
2355
2356 a = Element('{ns}a')
2357 b = SubElement(a, '{ns1}b', {'{ns}a1': 'test'})
2358 c = SubElement(a, '{ns2}c', {'{ns}a2': 'test'})
2359 d = SubElement(a, '{ns3}d', {'{ns}a3': 'test'})
2360
2361 s = [d, c, b]
2362 a[:] = s
2363 self.assertEqual(
2364 [d, c, b],
2365 list(a))
2366 self.assertEqual(
2367 ['{ns3}d', '{ns2}c', '{ns1}b'],
2368 [ child.tag for child in a ])
2369
2370 self.assertEqual(
2371 [['{ns}a3'], ['{ns}a2'], ['{ns}a1']],
2372 [ list(child.attrib.keys()) for child in a ])
2373
2375 Element = self.etree.Element
2376 SubElement = self.etree.SubElement
2377
2378 a = Element('a')
2379 b = SubElement(a, 'b')
2380 c = SubElement(a, 'c')
2381
2382 e = Element('e')
2383 f = Element('f')
2384 g = Element('g')
2385 h = Element('h')
2386
2387 s = [e, f]
2388 a[99:] = s
2389 self.assertEqual(
2390 [b, c, e, f],
2391 list(a))
2392
2393 s = [g, h]
2394 a[:0] = s
2395 self.assertEqual(
2396 [g, h, b, c, e, f],
2397 list(a))
2398
2400 Element = self.etree.Element
2401 SubElement = self.etree.SubElement
2402
2403 a = Element('a')
2404 b = SubElement(a, 'b')
2405 c = SubElement(a, 'c')
2406 d = SubElement(a, 'd')
2407
2408 e = Element('e')
2409 f = Element('f')
2410 g = Element('g')
2411
2412 s = [e, f, g]
2413 a[3:] = s
2414 self.assertEqual(
2415 [b, c, d, e, f, g],
2416 list(a))
2417
2440
2457
2474
2491
2504
2514
2525
2527 ElementTree = self.etree.ElementTree
2528 ns = 'http://xml.infrae.com/1'
2529 ns2 = 'http://xml.infrae.com/2'
2530 f = BytesIO('<x:a xmlns:x="%s" xmlns:y="%s"><x:b></x:b><y:b></y:b></x:a>' % (ns, ns2))
2531 t = ElementTree(file=f)
2532 a = t.getroot()
2533 self.assertEqual('{%s}a' % ns,
2534 a.tag)
2535 self.assertEqual('{%s}b' % ns,
2536 a[0].tag)
2537 self.assertEqual('{%s}b' % ns2,
2538 a[1].tag)
2539
2541 Element = self.etree.Element
2542 SubElement = self.etree.SubElement
2543 ns = 'http://xml.infrae.com/1'
2544 ns2 = 'http://xml.infrae.com/2'
2545 a = Element('{%s}a' % ns)
2546 b = SubElement(a, '{%s}b' % ns2)
2547 c = SubElement(a, '{%s}c' % ns)
2548 self.assertEqual('{%s}a' % ns,
2549 a.tag)
2550 self.assertEqual('{%s}b' % ns2,
2551 b.tag)
2552 self.assertEqual('{%s}c' % ns,
2553 c.tag)
2554 self.assertEqual('{%s}a' % ns,
2555 a.tag)
2556 self.assertEqual('{%s}b' % ns2,
2557 b.tag)
2558 self.assertEqual('{%s}c' % ns,
2559 c.tag)
2560
2578
2580 Element = self.etree.Element
2581 ns = 'http://xml.infrae.com/1'
2582 ns2 = 'http://xml.infrae.com/2'
2583 a = Element('a')
2584 a.set('{%s}foo' % ns, 'Foo')
2585 a.set('{%s}bar' % ns2, 'Bar')
2586 self.assertEqual(
2587 'Foo',
2588 a.get('{%s}foo' % ns))
2589 self.assertEqual(
2590 'Bar',
2591 a.get('{%s}bar' % ns2))
2592 try:
2593 self.assertXML(
2594 _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns0:foo="Foo" ns1:bar="Bar"></a>' % (ns, ns2)),
2595 a)
2596 except AssertionError:
2597 self.assertXML(
2598 _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns1:foo="Foo" ns0:bar="Bar"></a>' % (ns2, ns)),
2599 a)
2600
2602 Element = self.etree.Element
2603 one = self.etree.fromstring(
2604 _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
2605 baz = one[0][0]
2606
2607 two = Element('root')
2608 two.append(baz)
2609
2610
2611 del one, baz
2612 self.assertEqual('{http://a.b.c}baz', two[0].tag)
2613
2623
2633
2644
2657
2659 Element = self.etree.Element
2660
2661 root = Element('element')
2662
2663 subelement = Element('subelement',
2664 {"{http://www.w3.org/XML/1998/namespace}id": "foo"})
2665 self.assertEqual(1, len(subelement.attrib))
2666 self.assertEqual(
2667 "foo",
2668 subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
2669
2670 root.append(subelement)
2671 self.assertEqual(1, len(subelement.attrib))
2672 self.assertEqual(
2673 list({"{http://www.w3.org/XML/1998/namespace}id" : "foo"}.items()),
2674 list(subelement.attrib.items()))
2675 self.assertEqual(
2676 "foo",
2677 subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
2678
2690
2706
2724
2725 required_versions_ET['test_register_namespace'] = (1,3)
2743
2755
2769
2783
2784 required_versions_ET['test_tostring_method_html'] = (1,3)
2798
2799 required_versions_ET['test_tostring_method_text'] = (1,3)
2801 tostring = self.etree.tostring
2802 Element = self.etree.Element
2803 SubElement = self.etree.SubElement
2804
2805 a = Element('a')
2806 a.text = "A"
2807 a.tail = "tail"
2808 b = SubElement(a, 'b')
2809 b.text = "B"
2810 b.tail = "TAIL"
2811 c = SubElement(a, 'c')
2812 c.text = "C"
2813
2814 self.assertEqual(_bytes('ABTAILCtail'),
2815 tostring(a, method="text"))
2816
2818 iterparse = self.etree.iterparse
2819 f = BytesIO('<a><b></b><c/></a>')
2820
2821 iterator = iterparse(f)
2822 self.assertEqual(None,
2823 iterator.root)
2824 events = list(iterator)
2825 root = iterator.root
2826 self.assertEqual(
2827 [('end', root[0]), ('end', root[1]), ('end', root)],
2828 events)
2829
2840
2851
2853 iterparse = self.etree.iterparse
2854 f = BytesIO('<a><b></b><c/></a>')
2855
2856 iterator = iterparse(f, events=('start',))
2857 events = list(iterator)
2858 root = iterator.root
2859 self.assertEqual(
2860 [('start', root), ('start', root[0]), ('start', root[1])],
2861 events)
2862
2864 iterparse = self.etree.iterparse
2865 f = BytesIO('<a><b></b><c/></a>')
2866
2867 iterator = iterparse(f, events=('start','end'))
2868 events = list(iterator)
2869 root = iterator.root
2870 self.assertEqual(
2871 [('start', root), ('start', root[0]), ('end', root[0]),
2872 ('start', root[1]), ('end', root[1]), ('end', root)],
2873 events)
2874
2886
2888 iterparse = self.etree.iterparse
2889 CHILD_COUNT = 12345
2890 f = BytesIO('<a>%s</a>' % ('<b>test</b>'*CHILD_COUNT))
2891
2892 i = 0
2893 for key in iterparse(f):
2894 event, element = key
2895 i += 1
2896 self.assertEqual(i, CHILD_COUNT + 1)
2897
2899 iterparse = self.etree.iterparse
2900 f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
2901
2902 attr_name = '{http://testns/}bla'
2903 events = []
2904 iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
2905 for event, elem in iterator:
2906 events.append(event)
2907 if event == 'start':
2908 if elem.tag != '{http://ns1/}a':
2909 elem.set(attr_name, 'value')
2910
2911 self.assertEqual(
2912 ['start-ns', 'start', 'start', 'start-ns', 'start',
2913 'end', 'end-ns', 'end', 'end', 'end-ns'],
2914 events)
2915
2916 root = iterator.root
2917 self.assertEqual(
2918 None,
2919 root.get(attr_name))
2920 self.assertEqual(
2921 'value',
2922 root[0].get(attr_name))
2923
2925 iterparse = self.etree.iterparse
2926 f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
2927
2928 attr_name = '{http://testns/}bla'
2929 events = []
2930 iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
2931 for event, elem in iterator:
2932 events.append(event)
2933 if event == 'start':
2934 if elem.tag != '{http://ns1/}a':
2935 elem.set(attr_name, 'value')
2936
2937 self.assertEqual(
2938 ['start-ns', 'start', 'start', 'start-ns', 'start',
2939 'end', 'end-ns', 'end', 'end', 'end-ns'],
2940 events)
2941
2942 root = iterator.root
2943 self.assertEqual(
2944 None,
2945 root.get(attr_name))
2946 self.assertEqual(
2947 'value',
2948 root[0].get(attr_name))
2949
2962
2964 tostring = self.etree.tostring
2965 f = BytesIO('<root><![CDATA[test]]></root>')
2966 context = self.etree.iterparse(f)
2967 content = [ el.text for event,el in context ]
2968
2969 self.assertEqual(['test'], content)
2970 self.assertEqual(_bytes('<root>test</root>'),
2971 tostring(context.root))
2972
2980
2984
2988
2989 required_versions_ET['test_parse_error'] = (1,3)
2991
2992 parse = self.etree.parse
2993 f = BytesIO('<a><b></c></b></a>')
2994 self.assertRaises(SyntaxError, parse, f)
2995 f.close()
2996
2997 required_versions_ET['test_parse_error_from_file'] = (1,3)
3004
3014
3024
3032
3039
3048
3061
3069
3079
3096
3097 required_versions_ET['test_parse_encoding_8bit_explicit'] = (1,3)
3112
3113 required_versions_ET['test_parse_encoding_8bit_override'] = (1,3)
3130
3132
3133 XML = self.etree.XML
3134 test_utf = (_str('<?xml version="1.0" encoding="iso-8859-1"?>') +
3135 _str('<a>Søk på nettet</a>'))
3136 self.assertRaises(SyntaxError, XML, test_utf)
3137
3152
3161
3170
3181
3193
3206
3220
3222 utext = _str('Søk på nettet')
3223 uxml = _str('<p>%s</p>') % utext
3224 prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
3225 isoxml = prologue + uxml.encode('iso-8859-1')
3226 tree = self.etree.XML(isoxml)
3227 self.assertEqual(utext, tree.text)
3228
3230 utext = _str('Søk på nettet')
3231 uxml = (_str('<?xml version="1.0" encoding="UTF-8"?>') +
3232 _str('<p>%s</p>') % utext)
3233 bom = _bytes('\\xEF\\xBB\\xBF').decode("unicode_escape").encode("latin1")
3234 xml = bom + uxml.encode("utf-8")
3235 tree = etree.XML(xml)
3236 self.assertEqual(utext, tree.text)
3237
3239 utext = _str('Søk på nettet')
3240 uxml = _str('<p>%s</p>') % utext
3241 prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
3242 isoxml = prologue + uxml.encode('iso-8859-1')
3243 el = self.etree.parse(BytesIO(isoxml)).getroot()
3244 self.assertEqual(utext, el.text)
3245
3259
3261 Element = self.etree.Element
3262
3263 a = Element('a')
3264 a.text = 'Foo'
3265
3266 b = copy.deepcopy(a)
3267 self.assertEqual('Foo', b.text)
3268
3269 b.text = 'Bar'
3270 self.assertEqual('Bar', b.text)
3271 self.assertEqual('Foo', a.text)
3272
3273 del a
3274 self.assertEqual('Bar', b.text)
3275
3277 Element = self.etree.Element
3278
3279 a = Element('a')
3280 a.tail = 'Foo'
3281
3282 b = copy.deepcopy(a)
3283 self.assertEqual('Foo', b.tail)
3284
3285 b.tail = 'Bar'
3286 self.assertEqual('Bar', b.tail)
3287 self.assertEqual('Foo', a.tail)
3288
3289 del a
3290 self.assertEqual('Bar', b.tail)
3291
3293 Element = self.etree.Element
3294 SubElement = self.etree.SubElement
3295
3296 root = Element('root')
3297 a = SubElement(root, 'a')
3298 a.text = 'FooText'
3299 a.tail = 'FooTail'
3300
3301 b = copy.deepcopy(a)
3302 self.assertEqual('FooText', b.text)
3303 self.assertEqual('FooTail', b.tail)
3304
3305 b.text = 'BarText'
3306 b.tail = 'BarTail'
3307 self.assertEqual('BarTail', b.tail)
3308 self.assertEqual('FooTail', a.tail)
3309 self.assertEqual('BarText', b.text)
3310 self.assertEqual('FooText', a.text)
3311
3312 del a
3313 self.assertEqual('BarTail', b.tail)
3314 self.assertEqual('BarText', b.text)
3315
3317 root = self.etree.XML(_bytes('''<doc xmlns="dns" xmlns:t="tns">
3318 <parent><node t:foo="bar" /></parent>
3319 </doc>'''))
3320 self.assertEqual(
3321 root[0][0].get('{tns}foo'),
3322 copy.deepcopy(root[0])[0].get('{tns}foo') )
3323 self.assertEqual(
3324 root[0][0].get('{tns}foo'),
3325 copy.deepcopy(root[0][0]).get('{tns}foo') )
3326
3341
3353
3366
3367
3380
3382
3383 etree = self.etree
3384 e = etree.Element('foo')
3385 self.assertEqual(False, bool(e))
3386 etree.SubElement(e, 'bar')
3387 self.assertEqual(True, bool(e))
3388 e = etree.Element('foo')
3389 e.text = 'hey'
3390 self.assertEqual(False, bool(e))
3391 e = etree.Element('foo')
3392 e.tail = 'bar'
3393 self.assertEqual(False, bool(e))
3394 e = etree.Element('foo')
3395 e.set('bar', 'Bar')
3396 self.assertEqual(False, bool(e))
3397
3415
3423
3425 etree = self.etree
3426 qname1 = etree.QName('myns', 'a')
3427 qname2 = etree.QName('myns', 'a')
3428 self.assertEqual(qname1, "{myns}a")
3429 self.assertEqual("{myns}a", qname2)
3430 self.assertEqual(qname1, qname1)
3431 self.assertEqual(qname1, qname2)
3432
3442
3455
3465
3475
3485
3492
3493
3494
3510
3525
3526 required_versions_ET['test_feed_parser_error_close_empty'] = (1,3)
3531
3532 required_versions_ET['test_feed_parser_error_close_incomplete'] = (1,3)
3541
3542 required_versions_ET['test_feed_parser_error_broken'] = (1,3)
3556
3557 required_versions_ET['test_feed_parser_error_position'] = (1,3)
3569
3570
3571
3572 required_versions_ET['test_parser_target_property'] = (1,3)
3574 class Target(object):
3575 pass
3576
3577 target = Target()
3578 parser = self.XMLParser(target=target)
3579
3580 self.assertEqual(target, parser.target)
3581
3583 assertEqual = self.assertEqual
3584 assertFalse = self.assertFalse
3585
3586 events = []
3587 class Target(object):
3588 def start(self, tag, attrib):
3589 events.append("start")
3590 assertFalse(attrib)
3591 assertEqual("TAG", tag)
3592 def end(self, tag):
3593 events.append("end")
3594 assertEqual("TAG", tag)
3595 def close(self):
3596 return "DONE"
3597
3598 parser = self.XMLParser(target=Target())
3599
3600 parser.feed("<TAG/>")
3601 done = parser.close()
3602
3603 self.assertEqual("DONE", done)
3604 self.assertEqual(["start", "end"], events)
3605
3607 assertEqual = self.assertEqual
3608
3609 events = []
3610 class Target(object):
3611 def start(self, tag, attrib):
3612 events.append("start")
3613 assertEqual("TAG", tag)
3614 raise ValueError("TEST")
3615 def end(self, tag):
3616 events.append("end")
3617 assertEqual("TAG", tag)
3618 def close(self):
3619 return "DONE"
3620
3621 parser = self.XMLParser(target=Target())
3622
3623 try:
3624 parser.feed("<TAG/>")
3625 except ValueError:
3626 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3627 else:
3628 self.assertTrue(False)
3629 if 'lxml' in self.etree.__name__:
3630 self.assertEqual(["start"], events)
3631 else:
3632
3633 self.assertTrue("start" in events)
3634
3636 assertEqual = self.assertEqual
3637
3638 events = []
3639 class Target(object):
3640 def start(self, tag, attrib):
3641 events.append("start")
3642 assertEqual("TAG", tag)
3643 def end(self, tag):
3644 events.append("end")
3645 assertEqual("TAG", tag)
3646 raise ValueError("TEST")
3647 def close(self):
3648 return "DONE"
3649
3650 parser = self.XMLParser(target=Target())
3651
3652 try:
3653 parser.feed("<TAG/>")
3654 except ValueError:
3655 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3656 else:
3657 self.assertTrue(False)
3658 self.assertEqual(["start", "end"], events)
3659
3661 assertEqual = self.assertEqual
3662
3663 events = []
3664 class Target(object):
3665 def start(self, tag, attrib):
3666 events.append("start")
3667 assertEqual("TAG", tag)
3668 def end(self, tag):
3669 events.append("end")
3670 assertEqual("TAG", tag)
3671 def close(self):
3672 raise ValueError("TEST")
3673
3674 parser = self.XMLParser(target=Target())
3675
3676 try:
3677 parser.feed("<TAG/>")
3678 parser.close()
3679 except ValueError:
3680 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3681 else:
3682 self.assertTrue(False)
3683 self.assertEqual(["start", "end"], events)
3684
3686 assertEqual = self.assertEqual
3687
3688 events = []
3689 class Target(object):
3690 def start(self, tag, attrib):
3691 events.append("start")
3692 assertEqual("TAG", tag)
3693 raise IndexError("TEST-IE")
3694 def end(self, tag):
3695 events.append("end")
3696 assertEqual("TAG", tag)
3697 def close(self):
3698 raise ValueError("TEST-VE")
3699
3700 parser = self.XMLParser(target=Target())
3701
3702 try:
3703 parser.feed("<TAG/>")
3704 parser.close()
3705 except IndexError:
3706 if 'lxml' in self.etree.__name__:
3707
3708 self.assertTrue(sys.version_info[0] < 3)
3709 self.assertTrue('TEST-IE' in str(sys.exc_info()[1]))
3710 except ValueError:
3711 if 'lxml' in self.etree.__name__:
3712 self.assertTrue(sys.version_info[0] >= 3)
3713 self.assertTrue('TEST-VE' in str(sys.exc_info()[1]))
3714 else:
3715 self.assertTrue(False)
3716
3717 if 'lxml' in self.etree.__name__:
3718 self.assertEqual(["start"], events)
3719 else:
3720
3721 self.assertTrue("start" in events)
3722
3724 assertEqual = self.assertEqual
3725 assertFalse = self.assertFalse
3726 Element = self.etree.Element
3727
3728 events = []
3729 class Target(object):
3730 def start(self, tag, attrib):
3731 events.append("start")
3732 assertFalse(attrib)
3733 assertEqual("TAG", tag)
3734 def end(self, tag):
3735 events.append("end")
3736 assertEqual("TAG", tag)
3737 def close(self):
3738 return Element("DONE")
3739
3740 parser = self.XMLParser(target=Target())
3741 tree = self.etree.ElementTree()
3742 tree.parse(BytesIO("<TAG/>"), parser=parser)
3743
3744 self.assertEqual("DONE", tree.getroot().tag)
3745 self.assertEqual(["start", "end"], events)
3746
3748 assertEqual = self.assertEqual
3749
3750 events = []
3751 class Target(object):
3752 def start(self, tag, attrib):
3753 events.append("start-" + tag)
3754 for name, value in attrib.items():
3755 assertEqual(tag + name, value)
3756 def end(self, tag):
3757 events.append("end-" + tag)
3758 def close(self):
3759 return "DONE"
3760
3761 parser = self.XMLParser(target=Target())
3762
3763 parser.feed('<root a="roota" b="rootb"><sub c="subc"/></root>')
3764 done = parser.close()
3765
3766 self.assertEqual("DONE", done)
3767 self.assertEqual(["start-root", "start-sub", "end-sub", "end-root"],
3768 events)
3769
3771 events = []
3772 class Target(object):
3773 def start(self, tag, attrib):
3774 events.append("start-" + tag)
3775 def end(self, tag):
3776 events.append("end-" + tag)
3777 def data(self, data):
3778 events.append("data-" + data)
3779 def close(self):
3780 return "DONE"
3781
3782 parser = self.XMLParser(target=Target())
3783
3784 parser.feed('<root>A<sub/>B</root>')
3785 done = parser.close()
3786
3787 self.assertEqual("DONE", done)
3788 self.assertEqual(["start-root", "data-A", "start-sub",
3789 "end-sub", "data-B", "end-root"],
3790 events)
3791
3793 events = []
3794 class Target(object):
3795 def __init__(self):
3796 self._data = []
3797 def _flush_data(self):
3798 if self._data:
3799 events.append("data-" + ''.join(self._data))
3800 del self._data[:]
3801 def start(self, tag, attrib):
3802 self._flush_data()
3803 events.append("start-" + tag)
3804 def end(self, tag):
3805 self._flush_data()
3806 events.append("end-" + tag)
3807 def data(self, data):
3808 self._data.append(data)
3809 def close(self):
3810 self._flush_data()
3811 return "DONE"
3812
3813 parser = self.XMLParser(target=Target())
3814
3815 dtd = '''
3816 <!DOCTYPE root [
3817 <!ELEMENT root (sub*)>
3818 <!ELEMENT sub (#PCDATA)>
3819 <!ENTITY ent "an entity">
3820 ]>
3821 '''
3822 parser.feed(dtd+'<root><sub/><sub>this is &ent;</sub><sub/></root>')
3823 done = parser.close()
3824
3825 self.assertEqual("DONE", done)
3826 self.assertEqual(["start-root", "start-sub", "end-sub", "start-sub",
3827 "data-this is an entity",
3828 "end-sub", "start-sub", "end-sub", "end-root"],
3829 events)
3830
3831 required_versions_ET['test_parser_target_entity_unknown'] = (1,3)
3833 events = []
3834 class Target(object):
3835 def __init__(self):
3836 self._data = []
3837 def _flush_data(self):
3838 if self._data:
3839 events.append("data-" + ''.join(self._data))
3840 del self._data[:]
3841 def start(self, tag, attrib):
3842 self._flush_data()
3843 events.append("start-" + tag)
3844 def end(self, tag):
3845 self._flush_data()
3846 events.append("end-" + tag)
3847 def data(self, data):
3848 self._data.append(data)
3849 def close(self):
3850 self._flush_data()
3851 return "DONE"
3852
3853 parser = self.XMLParser(target=Target())
3854
3855 def feed():
3856 parser.feed('<root><sub/><sub>some &ent;</sub><sub/></root>')
3857 parser.close()
3858
3859 self.assertRaises(self.etree.ParseError, feed)
3860
3861 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3863 class Builder(list):
3864 def start(self, tag, attrib):
3865 self.append(("start", tag))
3866 def end(self, tag):
3867 self.append(("end", tag))
3868 def data(self, text):
3869 pass
3870 def pi(self, target, data):
3871 self.append(("pi", target, data))
3872 def comment(self, data):
3873 self.append(("comment", data))
3874 def start_ns(self, prefix, uri):
3875 self.append(("start-ns", prefix, uri))
3876 def end_ns(self, prefix):
3877 self.append(("end-ns", prefix))
3878
3879 builder = Builder()
3880 parser = self.etree.XMLParser(target=builder)
3881 parser.feed(textwrap.dedent("""\
3882 <?pi data?>
3883 <!-- comment -->
3884 <root xmlns='namespace'>
3885 <element key='value'>text</element>
3886 <element>text</element>tail
3887 <empty-element/>
3888 </root>
3889 """))
3890 self.assertEqual(builder, [
3891 ('pi', 'pi', 'data'),
3892 ('comment', ' comment '),
3893 ('start-ns', '', 'namespace'),
3894 ('start', '{namespace}root'),
3895 ('start', '{namespace}element'),
3896 ('end', '{namespace}element'),
3897 ('start', '{namespace}element'),
3898 ('end', '{namespace}element'),
3899 ('start', '{namespace}empty-element'),
3900 ('end', '{namespace}empty-element'),
3901 ('end', '{namespace}root'),
3902 ('end-ns', ''),
3903 ])
3904
3905 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3907 class Builder(list):
3908 def end_ns(self, prefix):
3909 self.append(("end-ns", prefix))
3910
3911 builder = Builder()
3912 parser = self.etree.XMLParser(target=builder)
3913 parser.feed(textwrap.dedent("""\
3914 <?pi data?>
3915 <!-- comment -->
3916 <root xmlns='namespace' xmlns:p='pns'>
3917 <element key='value'>text</element>
3918 <p:element>text</p:element>tail
3919 <empty-element/>
3920 </root>
3921 """))
3922 self.assertEqual(builder, [
3923 ('end-ns', 'p'),
3924 ('end-ns', ''),
3925 ])
3926
3928 builder = self.etree.TreeBuilder()
3929 el = builder.start("root", {'a':'A', 'b':'B'})
3930 self.assertEqual("root", el.tag)
3931 self.assertEqual({'a':'A', 'b':'B'}, el.attrib)
3932 builder.data("ROOTTEXT")
3933 el = builder.start("child", {'x':'X', 'y':'Y'})
3934 self.assertEqual("child", el.tag)
3935 self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
3936 builder.data("CHILDTEXT")
3937 el = builder.end("child")
3938 self.assertEqual("child", el.tag)
3939 self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
3940 self.assertEqual("CHILDTEXT", el.text)
3941 self.assertEqual(None, el.tail)
3942 builder.data("CHILDTAIL")
3943 root = builder.end("root")
3944
3945 self.assertEqual("root", root.tag)
3946 self.assertEqual("ROOTTEXT", root.text)
3947 self.assertEqual("CHILDTEXT", root[0].text)
3948 self.assertEqual("CHILDTAIL", root[0].tail)
3949
3959
3960 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3970
3971
3972
3973
3974 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3976 ET = self.etree
3977 is_lxml = ET.__name__ == 'lxml.etree'
3978
3979 b = ET.TreeBuilder()
3980 self.assertEqual(b.pi('target', None).tag, ET.PI)
3981 if is_lxml:
3982 self.assertEqual(b.pi('target', None).target, 'target')
3983 else:
3984 self.assertEqual(b.pi('target', None).text, 'target')
3985
3986 b = ET.TreeBuilder(pi_factory=ET.PI)
3987 self.assertEqual(b.pi('target').tag, ET.PI)
3988 if is_lxml:
3989 self.assertEqual(b.pi('target').target, "target")
3990 else:
3991 self.assertEqual(b.pi('target').text, "target")
3992 self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI)
3993 if is_lxml:
3994 self.assertEqual(b.pi('pitarget', ' text ').target, "pitarget")
3995 self.assertEqual(b.pi('pitarget', ' text ').text, " text ")
3996 else:
3997 self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget text ")
3998
3999
4000
4001
4002
4004
4005 ET = self.etree
4006 class TreeBuilderSubclass(ET.TreeBuilder):
4007 pass
4008
4009 if ET.__name__ == 'lxml.etree':
4010 def assert_content(a):
4011 self.assertEqual(a.text, "text")
4012 self.assertEqual(a[0].tail, "tail")
4013 else:
4014 def assert_content(a):
4015 self.assertEqual(a.text, "texttail")
4016
4017 xml = "<a>text<!-- comment -->tail</a>"
4018 a = ET.fromstring(xml)
4019 assert_content(a)
4020
4021 parser = ET.XMLParser(target=TreeBuilderSubclass())
4022 parser.feed(xml)
4023 a = parser.close()
4024 assert_content(a)
4025
4026 xml = "<a>text<?pi data?>tail</a>"
4027 a = ET.fromstring(xml)
4028 assert_content(a)
4029
4030 xml = "<a>text<?pi data?>tail</a>"
4031 parser = ET.XMLParser(target=TreeBuilderSubclass())
4032 parser.feed(xml)
4033 a = parser.close()
4034 assert_content(a)
4035
4036 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4043
4044 xml = "<a>text<?pi1?> <!-- comment -->\n<?pi2?>tail</a>"
4045 parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True, insert_pis=False))
4046 parser.feed(xml)
4047 a = parser.close()
4048 self.assertEqual(a[0].text, ' comment ')
4049 self.assertEqual(a[0].tail, '\ntail')
4050 self.assertEqual(a.text, "text ")
4051
4052 parser = ET.XMLParser(target=TreeBuilderSubclass(insert_comments=True, insert_pis=False))
4053 parser.feed(xml)
4054 a = parser.close()
4055 self.assertEqual(a[0].text, ' comment ')
4056 self.assertEqual(a[0].tail, '\ntail')
4057 self.assertEqual(a.text, "text ")
4058
4059 xml = "<a>text<!-- comment -->\n<?pi data?>tail</a>"
4060 parser = ET.XMLParser(target=ET.TreeBuilder(insert_pis=True, insert_comments=False))
4061 parser.feed(xml)
4062 a = parser.close()
4063 self.assertEqual(a[0].text[-4:], 'data')
4064 self.assertEqual(a[0].tail, 'tail')
4065 self.assertEqual(a.text, "text\n")
4066
4067 parser = ET.XMLParser(target=TreeBuilderSubclass(insert_pis=True, insert_comments=False))
4068 parser.feed(xml)
4069 a = parser.close()
4070 self.assertEqual(a[0].text[-4:], 'data')
4071 self.assertEqual(a[0].tail, 'tail')
4072 self.assertEqual(a.text, "text\n")
4073
4074
4075
4081
4093
4094 - def assertXML(self, expected, element, encoding='us-ascii'):
4095 """Writes element out and checks whether it is expected.
4096
4097 Does this two ways; once using BytesIO, once using a real file.
4098 """
4099 if isinstance(expected, unicode):
4100 expected = expected.encode(encoding)
4101 self.assertEqual(expected, self._writeElement(element, encoding))
4102 self.assertEqual(expected, self._writeElementFile(element, encoding))
4103
4105 "Checks if the result XML byte string specifies the encoding."
4106 enc_re = r"<\?xml[^>]+ encoding=[\"']([^\"']+)[\"']"
4107 if isinstance(result, str):
4108 has_encoding = re.compile(enc_re).match
4109 else:
4110 has_encoding = re.compile(_bytes(enc_re)).match
4111 self.assertTrue(has_encoding(result))
4112 result_encoding = has_encoding(result).group(1)
4113 self.assertEqual(result_encoding.upper(), encoding.upper())
4114
4118
4121
4133
4135 len(string)
4136 for char in string:
4137 self.assertEqual(1, len(char))
4138 new_string = string + ""
4139 new_string = string + " "
4140 string[:0]
4141
4143 len(mapping)
4144 keys = mapping.keys()
4145 values = mapping.values()
4146 items = mapping.items()
4147 for key in keys:
4148 item = mapping[key]
4149 mapping["key"] = "value"
4150 self.assertEqual("value", mapping["key"])
4151
4154 etree = None
4155
4158
4161
4163 """Create an Element with a tag 'a', with the given amount of children
4164 named 'a0', 'a1' ... and so on.
4165
4166 """
4167 e = self.etree.Element('a')
4168 for i in range(numchildren):
4169 self.etree.SubElement(e, 'a%s' % i)
4170 return e
4171
4173 e = self._make_elem_with_children(10)
4174
4175 self.assertEqual(e[1].tag, 'a1')
4176 self.assertEqual(e[-2].tag, 'a8')
4177
4178 self.assertRaises(IndexError, lambda: e[12])
4179 self.assertRaises(IndexError, lambda: e[-12])
4180
4182 e = self._make_elem_with_children(6)
4183
4184 self.assertEqual(self._elem_tags(e[3:]), ['a3', 'a4', 'a5'])
4185 self.assertEqual(self._elem_tags(e[3:6]), ['a3', 'a4', 'a5'])
4186 self.assertEqual(self._elem_tags(e[3:16]), ['a3', 'a4', 'a5'])
4187 self.assertEqual(self._elem_tags(e[3:5]), ['a3', 'a4'])
4188 self.assertEqual(self._elem_tags(e[3:-1]), ['a3', 'a4'])
4189 self.assertEqual(self._elem_tags(e[:2]), ['a0', 'a1'])
4190
4192 e = self._make_elem_with_children(10)
4193
4194 self.assertEqual(self._elem_tags(e[8:10:1]), ['a8', 'a9'])
4195 self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
4196 self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
4197 self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
4198 self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
4199 self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
4200
4202 e = self._make_elem_with_children(4)
4203
4204 self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
4205 self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
4206 self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
4207 self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
4208 self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
4209
4234
4236 e = self._make_elem_with_children(4)
4237 e[1] = self.etree.Element('b')
4238 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4239
4240 e[-2] = self.etree.Element('c')
4241 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
4242
4243 with self.assertRaises(IndexError):
4244 e[5] = self.etree.Element('d')
4245 with self.assertRaises(IndexError):
4246 e[-5] = self.etree.Element('d')
4247 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
4248
4250 e = self._make_elem_with_children(4)
4251 e[1:3] = [self.etree.Element('b%s' % i) for i in range(2)]
4252 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
4253
4254 e = self._make_elem_with_children(4)
4255 e[1:3] = [self.etree.Element('b')]
4256 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
4257
4258 e = self._make_elem_with_children(4)
4259 e[1:3] = [self.etree.Element('b%s' % i) for i in range(3)]
4260 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
4261
4263 e = self._make_elem_with_children(6)
4264 e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(2)]
4265 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
4266
4267 e = self._make_elem_with_children(6)
4268 with self.assertRaises(ValueError):
4269 e[1:5:2] = [self.etree.Element('b')]
4270 with self.assertRaises(ValueError):
4271 e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(3)]
4272 with self.assertRaises(ValueError):
4273 e[1:5:2] = []
4274 self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
4275
4276 e = self._make_elem_with_children(4)
4277 e[1::sys.maxsize] = [self.etree.Element('b')]
4278 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4279 e[1::sys.maxsize<<64] = [self.etree.Element('c')]
4280 self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
4281
4283 e = self._make_elem_with_children(4)
4284 e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(2)]
4285 self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
4286
4287 e = self._make_elem_with_children(4)
4288 with self.assertRaises(ValueError):
4289 e[2:0:-1] = [self.etree.Element('b')]
4290 with self.assertRaises(ValueError):
4291 e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(3)]
4292 with self.assertRaises(ValueError):
4293 e[2:0:-1] = []
4294 self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
4295
4296 e = self._make_elem_with_children(4)
4297 e[1::-sys.maxsize] = [self.etree.Element('b')]
4298 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4299 e[1::-sys.maxsize-1] = [self.etree.Element('c')]
4300 self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
4301 e[1::-sys.maxsize<<64] = [self.etree.Element('d')]
4302 self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
4303
4306 etree = None
4307
4315
4316 - def _feed(self, parser, data, chunk_size=None):
4322
4324 self.assertEqual(
4325 [(event, (elem.tag, elem.text))
4326 for event, elem in islice(parser.read_events(), max_events)],
4327 expected)
4328
4330 self.assertEqual(
4331 list(islice(parser.read_events(), max_events)),
4332 expected)
4333
4338
4340 for chunk_size in (None, 1, 5):
4341
4342 parser = self.etree.XMLPullParser()
4343 self.assert_event_tags(parser, [])
4344 self._feed(parser, "<!-- comment -->\n", chunk_size)
4345 self.assert_event_tags(parser, [])
4346 self._feed(parser,
4347 "<root>\n <element key='value'>text</element",
4348 chunk_size)
4349 self.assert_event_tags(parser, [])
4350 self._feed(parser, ">\n", chunk_size)
4351 self.assert_event_tags(parser, [('end', 'element')])
4352 self._feed(parser, "<element>text</element>tail\n", chunk_size)
4353 self._feed(parser, "<empty-element/>\n", chunk_size)
4354 self.assert_event_tags(parser, [
4355 ('end', 'element'),
4356 ('end', 'empty-element'),
4357 ])
4358 self._feed(parser, "</root>\n", chunk_size)
4359 self.assert_event_tags(parser, [('end', 'root')])
4360 root = self._close_and_return_root(parser)
4361 self.assertEqual(root.tag, 'root')
4362
4364 parser = self.etree.XMLPullParser()
4365 it = parser.read_events()
4366 self._feed(parser, "<root>\n <element key='value'>text</element>\n")
4367 action, elem = next(it)
4368 self.assertEqual((action, elem.tag), ('end', 'element'))
4369 self._feed(parser, "</root>\n")
4370 action, elem = next(it)
4371 self.assertEqual((action, elem.tag), ('end', 'root'))
4372 with self.assertRaises(StopIteration):
4373 next(it)
4374
4376 parser = self.etree.XMLPullParser()
4377 self.assert_event_tags(parser, [])
4378 self._feed(parser, "<!-- comment -->\n")
4379 self.assert_event_tags(parser, [])
4380 self._feed(parser, "<root xmlns='namespace'>\n")
4381 self.assert_event_tags(parser, [])
4382 self._feed(parser, "<element key='value'>text</element")
4383 self.assert_event_tags(parser, [])
4384 self._feed(parser, ">\n")
4385 self.assert_event_tags(parser, [('end', '{namespace}element')])
4386 self._feed(parser, "<element>text</element>tail\n")
4387 self._feed(parser, "<empty-element/>\n")
4388 self.assert_event_tags(parser, [
4389 ('end', '{namespace}element'),
4390 ('end', '{namespace}empty-element'),
4391 ])
4392 self._feed(parser, "</root>\n")
4393 self.assert_event_tags(parser, [('end', '{namespace}root')])
4394 root = self._close_and_return_root(parser)
4395 self.assertEqual(root.tag, '{namespace}root')
4396
4398 parser = self.etree.XMLPullParser(events=('start-ns', 'end-ns'))
4399 self._feed(parser, "<!-- comment -->\n")
4400 self._feed(parser, "<root xmlns='namespace'>\n")
4401 self.assertEqual(
4402 list(parser.read_events()),
4403 [('start-ns', ('', 'namespace'))])
4404 self._feed(parser, "<element key='value'>text</element")
4405 self._feed(parser, ">\n")
4406 self._feed(parser, "<element>text</element>tail\n")
4407 self._feed(parser, "<empty-element/>\n")
4408 self._feed(parser, "</root>\n")
4409 self.assertEqual(list(parser.read_events()), [('end-ns', None)])
4410 parser.close()
4411
4413 parser = self.etree.XMLPullParser(events=['end-ns'])
4414 self._feed(parser, "<!-- comment -->\n")
4415 self._feed(parser, "<root xmlns='namespace' xmlns:a='abc' xmlns:b='xyz'>\n")
4416 self.assertEqual(list(parser.read_events()), [])
4417 self._feed(parser, "<a:element key='value'>text</a:element")
4418 self._feed(parser, ">\n")
4419 self._feed(parser, "<b:element>text</b:element>tail\n")
4420 self._feed(parser, "<empty-element/>\n")
4421 self.assertEqual(list(parser.read_events()), [])
4422 self._feed(parser, "</root>\n")
4423 self.assertEqual(list(parser.read_events()), [
4424 ('end-ns', None),
4425 ('end-ns', None),
4426 ('end-ns', None),
4427 ])
4428 parser.close()
4429
4430 @et_needs_pyversion(3,8)
4432 parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end'))
4433 self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
4434 self.assert_event_tuples(parser, [
4435 ('start-ns', ('', 'abc')),
4436 ('start-ns', ('p', 'xyz')),
4437 ], max_events=2)
4438 self.assert_event_tags(parser, [
4439 ('start', '{abc}tag'),
4440 ], max_events=1)
4441
4442 self._feed(parser, "<child />\n")
4443 self.assert_event_tags(parser, [
4444 ('start', '{abc}child'),
4445 ('end', '{abc}child'),
4446 ])
4447
4448 self._feed(parser, "</tag>\n")
4449 parser.close()
4450 self.assert_event_tags(parser, [
4451 ('end', '{abc}tag'),
4452 ])
4453
4454 @et_needs_pyversion(3,8)
4456 parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns'))
4457 self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
4458 self.assert_event_tuples(parser, [
4459 ('start-ns', ('', 'abc')),
4460 ('start-ns', ('p', 'xyz')),
4461 ], max_events=2)
4462 self.assert_event_tags(parser, [
4463 ('start', '{abc}tag'),
4464 ], max_events=1)
4465
4466 self._feed(parser, "<child />\n")
4467 self.assert_event_tags(parser, [
4468 ('start', '{abc}child'),
4469 ('end', '{abc}child'),
4470 ])
4471
4472 self._feed(parser, "</tag>\n")
4473 parser.close()
4474 self.assert_event_tags(parser, [
4475 ('end', '{abc}tag'),
4476 ], max_events=1)
4477 self.assert_event_tuples(parser, [
4478 ('end-ns', None),
4479 ('end-ns', None),
4480 ])
4481
4483 parser = self.etree.XMLPullParser(events=())
4484 self._feed(parser, "<root/>\n")
4485 self.assert_event_tags(parser, [])
4486
4487 parser = self.etree.XMLPullParser(events=('start', 'end'))
4488 self._feed(parser, "<!-- text here -->\n")
4489 self.assert_events(parser, [])
4490
4491 parser = self.etree.XMLPullParser(events=('start', 'end'))
4492 self._feed(parser, "<root>\n")
4493 self.assert_event_tags(parser, [('start', 'root')])
4494 self._feed(parser, "<element key='value'>text</element")
4495 self.assert_event_tags(parser, [('start', 'element')])
4496 self._feed(parser, ">\n")
4497 self.assert_event_tags(parser, [('end', 'element')])
4498 self._feed(parser,
4499 "<element xmlns='foo'>text<empty-element/></element>tail\n")
4500 self.assert_event_tags(parser, [
4501 ('start', '{foo}element'),
4502 ('start', '{foo}empty-element'),
4503 ('end', '{foo}empty-element'),
4504 ('end', '{foo}element'),
4505 ])
4506 self._feed(parser, "</root>")
4507 root = self._close_and_return_root(parser)
4508 self.assert_event_tags(parser, [('end', 'root')])
4509 self.assertEqual(root.tag, 'root')
4510
4511 parser = self.etree.XMLPullParser(events=('start',))
4512 self._feed(parser, "<!-- comment -->\n")
4513 self.assert_event_tags(parser, [])
4514 self._feed(parser, "<root>\n")
4515 self.assert_event_tags(parser, [('start', 'root')])
4516 self._feed(parser, "<element key='value'>text</element")
4517 self.assert_event_tags(parser, [('start', 'element')])
4518 self._feed(parser, ">\n")
4519 self.assert_event_tags(parser, [])
4520 self._feed(parser,
4521 "<element xmlns='foo'>text<empty-element/></element>tail\n")
4522 self.assert_event_tags(parser, [
4523 ('start', '{foo}element'),
4524 ('start', '{foo}empty-element'),
4525 ])
4526 self._feed(parser, "</root>")
4527 root = self._close_and_return_root(parser)
4528 self.assertEqual(root.tag, 'root')
4529
4530 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4549
4550 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4559
4561
4562 eventset = {'end', 'start'}
4563 parser = self.etree.XMLPullParser(events=eventset)
4564 self._feed(parser, "<foo>bar</foo>")
4565 self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
4566
4567 class DummyIter(object):
4568 def __init__(self):
4569 self.events = iter(['start', 'end', 'start-ns'])
4570 def __iter__(self):
4571 return self
4572 def __next__(self):
4573 return next(self.events)
4574 def next(self):
4575 return next(self.events)
4576
4577 parser = self.etree.XMLPullParser(events=DummyIter())
4578 self._feed(parser, "<foo>bar</foo>")
4579 self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
4580
4582 with self.assertRaises(ValueError):
4583 self.etree.XMLPullParser(events=('start', 'end', 'bogus'))
4584
4587 etree = None
4588 maxDiff = None
4589
4590 if not hasattr(unittest.TestCase, 'subTest'):
4591 @contextmanager
4592 - def subTest(self, name, **kwargs):
4593 try:
4594 yield
4595 except unittest.SkipTest:
4596 raise
4597 except Exception as e:
4598 print("Subtest {} failed: {}".format(name, e))
4599 raise
4600
4603
4604
4605
4606
4609
4611 c14n_roundtrip = self.c14n_roundtrip
4612
4613 self.assertEqual(c14n_roundtrip("<doc/>"), '<doc></doc>')
4614 self.assertEqual(c14n_roundtrip("<doc xmlns='uri'/>"),
4615 '<doc xmlns="uri"></doc>')
4616 self.assertEqual(c14n_roundtrip("<prefix:doc xmlns:prefix='uri'/>"),
4617 '<prefix:doc xmlns:prefix="uri"></prefix:doc>')
4618 self.assertEqual(c14n_roundtrip("<doc xmlns:prefix='uri'><prefix:bar/></doc>"),
4619 '<doc><prefix:bar xmlns:prefix="uri"></prefix:bar></doc>')
4620 self.assertEqual(c14n_roundtrip("<elem xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' />"),
4621 '<elem></elem>')
4622
4623
4624 self.assertEqual(c14n_roundtrip("<doc>Hello, world!<!-- Comment 1 --></doc>"),
4625 '<doc>Hello, world!</doc>')
4626 self.assertEqual(c14n_roundtrip("<value>2</value>"),
4627 '<value>2</value>')
4628 self.assertEqual(c14n_roundtrip('<compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>'),
4629 '<compute>value>"0" && value<"10" ?"valid":"error"</compute>')
4630 self.assertEqual(c14n_roundtrip('''<compute expr='value>"0" && value<"10" ?"valid":"error"'>valid</compute>'''),
4631 '<compute expr="value>"0" && value<"10" ?"valid":"error"">valid</compute>')
4632 self.assertEqual(c14n_roundtrip("<norm attr=' '   
	 ' '/>"),
4633 '<norm attr=" \' 
	 \' "></norm>')
4634 self.assertEqual(c14n_roundtrip("<normNames attr=' A   
	 B '/>"),
4635 '<normNames attr=" A 
	 B "></normNames>')
4636 self.assertEqual(c14n_roundtrip("<normId id=' '   
	 ' '/>"),
4637 '<normId id=" \' 
	 \' "></normId>')
4638
4639
4640
4641
4642
4644 c14n_roundtrip = self.c14n_roundtrip
4645 xml = textwrap.dedent("""\
4646 <root xmlns:x="http://example.com/x">
4647 <a x:attr="attrx">
4648 <b>abtext</b>
4649 </a>
4650 <b>btext</b>
4651 <c>
4652 <x:d>dtext</x:d>
4653 </c>
4654 </root>
4655 """)
4656 self.assertEqual(
4657 c14n_roundtrip(xml, strip_text=True),
4658 '<root>'
4659 '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
4660 '<b>btext</b>'
4661 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4662 '</root>')
4663 self.assertEqual(
4664 c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']),
4665 '<root>'
4666 '<a><b>abtext</b></a>'
4667 '<b>btext</b>'
4668 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4669 '</root>')
4670 self.assertEqual(
4671 c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']),
4672 '<root>'
4673 '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
4674 '<b>btext</b>'
4675 '<c></c>'
4676 '</root>')
4677 self.assertEqual(
4678 c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'],
4679 exclude_tags=['{http://example.com/x}d']),
4680 '<root>'
4681 '<a><b>abtext</b></a>'
4682 '<b>btext</b>'
4683 '<c></c>'
4684 '</root>')
4685 self.assertEqual(
4686 c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']),
4687 '<root>'
4688 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4689 '</root>')
4690 self.assertEqual(
4691 c14n_roundtrip(xml, exclude_tags=['a', 'b']),
4692 '<root>\n'
4693 ' \n'
4694 ' \n'
4695 ' <c>\n'
4696 ' <x:d xmlns:x="http://example.com/x">dtext</x:d>\n'
4697 ' </c>\n'
4698 '</root>')
4699 self.assertEqual(
4700 c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']),
4701 '<root>'
4702 '<a xmlns:x="http://example.com/x" x:attr="attrx"></a>'
4703 '<c></c>'
4704 '</root>')
4705 self.assertEqual(
4706 c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']),
4707 '<root>\n'
4708 ' <a xmlns:x="http://example.com/x" x:attr="attrx">\n'
4709 ' \n'
4710 ' </a>\n'
4711 ' \n'
4712 ' <c>\n'
4713 ' \n'
4714 ' </c>\n'
4715 '</root>')
4716
4717
4718
4719
4720
4721
4722
4723
4725 datadir = os.path.join(os.path.dirname(__file__), "c14n-20")
4726 full_path = partial(os.path.join, datadir)
4727
4728 files = [filename[:-4] for filename in sorted(os.listdir(datadir))
4729 if filename.endswith('.xml')]
4730 input_files = [
4731 filename for filename in files
4732 if filename.startswith('in')
4733 ]
4734 configs = {
4735 filename: {
4736
4737 option.tag.split('}')[-1]: ((option.text or '').strip(), option)
4738 for option in self.etree.parse(full_path(filename) + ".xml").getroot()
4739 }
4740 for filename in files
4741 if filename.startswith('c14n')
4742 }
4743
4744 tests = {
4745 input_file: [
4746 (filename, configs[filename.rsplit('_', 1)[-1]])
4747 for filename in files
4748 if filename.startswith('out_%s_' % input_file)
4749 and filename.rsplit('_', 1)[-1] in configs
4750 ]
4751 for input_file in input_files
4752 }
4753
4754
4755 self.assertEqual(30, len([
4756 output_file for output_files in tests.values()
4757 for output_file in output_files]))
4758
4759 def get_option(config, option_name, default=None):
4760 return config.get(option_name, (default, ()))[0]
4761
4762 for input_file, output_files in tests.items():
4763 for output_file, config in output_files:
4764 keep_comments = get_option(
4765 config, 'IgnoreComments') == 'true'
4766 strip_text = get_option(
4767 config, 'TrimTextNodes') == 'true'
4768 rewrite_prefixes = get_option(
4769 config, 'PrefixRewrite') == 'sequential'
4770 if 'QNameAware' in config:
4771 qattrs = [
4772 "{%s}%s" % (el.get('NS'), el.get('Name'))
4773 for el in config['QNameAware'][1].findall(
4774 '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr')
4775 ]
4776 qtags = [
4777 "{%s}%s" % (el.get('NS'), el.get('Name'))
4778 for el in config['QNameAware'][1].findall(
4779 '{http://www.w3.org/2010/xml-c14n2}Element')
4780 ]
4781 else:
4782 qtags = qattrs = None
4783
4784
4785 config_descr = ','.join(
4786 "%s=%s" % (name, value or ','.join(c.tag.split('}')[-1] for c in children))
4787 for name, (value, children) in sorted(config.items())
4788 )
4789
4790 with self.subTest("{}({})".format(output_file, config_descr)):
4791 if input_file == 'inNsRedecl' and not rewrite_prefixes:
4792 self.skipTest(
4793 "Redeclared namespace handling is not supported in {}".format(
4794 output_file))
4795 if input_file == 'inNsSuperfluous' and not rewrite_prefixes:
4796 self.skipTest(
4797 "Redeclared namespace handling is not supported in {}".format(
4798 output_file))
4799 if 'QNameAware' in config and config['QNameAware'][1].find(
4800 '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None:
4801 self.skipTest(
4802 "QName rewriting in XPath text is not supported in {}".format(
4803 output_file))
4804
4805 f = full_path(input_file + ".xml")
4806 if input_file == 'inC14N5':
4807
4808 with open(full_path('world.txt'), 'rb') as entity_file:
4809 with open(f, 'rb') as f:
4810 f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read().strip()))
4811
4812 text = self._canonicalize(
4813 f,
4814 with_comments=keep_comments,
4815 strip_text=strip_text,
4816 rewrite_prefixes=rewrite_prefixes,
4817 qname_aware_tags=qtags, qname_aware_attrs=qattrs)
4818
4819 with io.open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f:
4820 expected = f.read()
4821 if input_file == 'inC14N3' and self.etree is not etree:
4822
4823 expected = expected.replace(' attr="default"', '')
4824 text = text.replace(' attr="default"', '')
4825 self.assertEqual(expected, text)
4826
4827
4828 if etree:
4831
4834
4837
4840
4842 - def _canonicalize(self, input_file, with_comments=True, strip_text=False,
4843 rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
4844 **options):
4845 if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
4846 self.skipTest("C14N 2.0 feature not supported with ElementTree.write()")
4847
4848 parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
4849 tree = self.etree.parse(input_file, parser)
4850 out = io.BytesIO()
4851 tree.write(
4852 out, method='c14n2',
4853 with_comments=with_comments, strip_text=strip_text,
4854 **options)
4855 return out.getvalue().decode('utf8')
4856
4858 - def _canonicalize(self, input_file, with_comments=True, strip_text=False,
4859 rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
4860 **options):
4861 if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
4862 self.skipTest("C14N 2.0 feature not supported with ElementTree.tostring()")
4863
4864 parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
4865 tree = self.etree.parse(input_file, parser)
4866 return self.etree.tostring(
4867 tree, method='c14n2',
4868 with_comments=with_comments, strip_text=strip_text,
4869 **options).decode('utf8')
4870
4871
4872 if ElementTree:
4874 etree = ElementTree
4875
4876 @classmethod
4878 if sys.version_info >= (3, 9):
4879 return
4880 import warnings
4881
4882 warnings.filterwarnings(
4883 'ignore',
4884 r'This method will be removed.*\.iter\(\).*instead',
4885 PendingDeprecationWarning)
4886
4887 filter_by_version(
4888 ElementTreeTestCase,
4889 ElementTreeTestCase.required_versions_ET, ET_VERSION)
4890
4891 if hasattr(ElementTree, 'XMLPullParser'):
4894 else:
4895 ElementTreePullTestCase = None
4896
4897 if hasattr(ElementTree, 'canonicalize'):
4900 else:
4901 ElementTreeC14NTest = None
4905
4906
4907 if cElementTree:
4910
4911 filter_by_version(
4912 CElementTreeTestCase,
4913 CElementTreeTestCase.required_versions_cET, CET_VERSION)
4917
4939
4940 if __name__ == '__main__':
4941 print('to test use test.py %s' % __file__)
4942