1
2
3 """
4 Tests specific to the extended etree API
5
6 Tests that apply to the general ElementTree API should go into
7 test_elementtree
8 """
9
10 from __future__ import absolute_import
11
12 import os.path
13 import unittest
14 import copy
15 import sys
16 import re
17 import gc
18 import operator
19 import tempfile
20 import textwrap
21 import zlib
22 import gzip
23
24 from .common_imports import etree, StringIO, BytesIO, HelperTestCase
25 from .common_imports import fileInTestDir, fileUrlInTestDir, read_file, path2url, tmpfile
26 from .common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
27 from .common_imports import canonicalize, _str, _bytes
28
29 print("""
30 TESTED VERSION: %s""" % etree.__version__ + """
31 Python: %r""" % (sys.version_info,) + """
32 lxml.etree: %r""" % (etree.LXML_VERSION,) + """
33 libxml used: %r""" % (etree.LIBXML_VERSION,) + """
34 libxml compiled: %r""" % (etree.LIBXML_COMPILED_VERSION,) + """
35 libxslt used: %r""" % (etree.LIBXSLT_VERSION,) + """
36 libxslt compiled: %r""" % (etree.LIBXSLT_COMPILED_VERSION,) + """
37 FS encoding: %s""" % (sys.getfilesystemencoding(),) + """
38 Default encoding: %s""" % (sys.getdefaultencoding(),) + """
39 Max Unicode: %s""" % (sys.maxunicode,) + """
40 """)
41
42 try:
43 _unicode = unicode
44 except NameError:
45
46 _unicode = str
47
48
50 """Tests only for etree, not ElementTree"""
51 etree = etree
52
63
72
80
87
89 Element = self.etree.Element
90 el = Element('name')
91 self.assertRaises(ValueError, Element, '{}')
92 self.assertRaises(ValueError, setattr, el, 'tag', '{}')
93
94 self.assertRaises(ValueError, Element, '{test}')
95 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
96
98 Element = self.etree.Element
99 self.assertRaises(ValueError, Element, 'p:name')
100 self.assertRaises(ValueError, Element, '{test}p:name')
101
102 el = Element('name')
103 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
104
106 Element = self.etree.Element
107 self.assertRaises(ValueError, Element, "p'name")
108 self.assertRaises(ValueError, Element, 'p"name')
109
110 self.assertRaises(ValueError, Element, "{test}p'name")
111 self.assertRaises(ValueError, Element, '{test}p"name')
112
113 el = Element('name')
114 self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
115 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
116
118 Element = self.etree.Element
119 self.assertRaises(ValueError, Element, ' name ')
120 self.assertRaises(ValueError, Element, 'na me')
121 self.assertRaises(ValueError, Element, '{test} name')
122
123 el = Element('name')
124 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
125
133
141
143 Element = self.etree.Element
144 SubElement = self.etree.SubElement
145
146 el = Element('name')
147 self.assertRaises(ValueError, SubElement, el, "p'name")
148 self.assertRaises(ValueError, SubElement, el, "{test}p'name")
149
150 self.assertRaises(ValueError, SubElement, el, 'p"name')
151 self.assertRaises(ValueError, SubElement, el, '{test}p"name')
152
161
170
172 QName = self.etree.QName
173 self.assertRaises(ValueError, QName, '')
174 self.assertRaises(ValueError, QName, None)
175 self.assertRaises(ValueError, QName, None, None)
176 self.assertRaises(ValueError, QName, 'test', '')
177
184
186 QName = self.etree.QName
187 self.assertRaises(ValueError, QName, 'p:name')
188 self.assertRaises(ValueError, QName, 'test', 'p:name')
189
191 QName = self.etree.QName
192 self.assertRaises(ValueError, QName, ' name ')
193 self.assertRaises(ValueError, QName, 'na me')
194 self.assertRaises(ValueError, QName, 'test', ' name')
195
203
205
206 QName = self.etree.QName
207 qname1 = QName('http://myns', 'a')
208 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
209
210 qname2 = QName(a)
211 self.assertEqual(a.tag, qname1.text)
212 self.assertEqual(a.tag, qname1)
213 self.assertEqual(qname1.text, qname2.text)
214 self.assertEqual(qname1, qname2.text)
215 self.assertEqual(qname1.text, qname2)
216 self.assertEqual(qname1, qname2)
217
219
220 etree = self.etree
221 qname = etree.QName('http://myns', 'a')
222 a = etree.Element(qname, nsmap={'p' : 'http://myns'})
223 a.text = qname
224
225 self.assertEqual("p:a", a.text)
226
235
242
257
263
273
285
287 Element = self.etree.Element
288
289 keys = ["attr%d" % i for i in range(10)]
290 values = ["TEST-%d" % i for i in range(10)]
291 items = list(zip(keys, values))
292
293 root = Element("root")
294 for key, value in items:
295 root.set(key, value)
296 self.assertEqual(keys, root.attrib.keys())
297 self.assertEqual(values, root.attrib.values())
298
299 root2 = Element("root2", root.attrib,
300 attr_99='TOAST-1', attr_98='TOAST-2')
301
302 if sys.version_info >= (3, 6):
303 self.assertEqual(['attr_99', 'attr_98'] + keys,
304 root2.attrib.keys())
305 self.assertEqual(['TOAST-1', 'TOAST-2'] + values,
306 root2.attrib.values())
307 else:
308 self.assertEqual(['attr_98', 'attr_99'] + keys,
309 root2.attrib.keys())
310 self.assertEqual(['TOAST-2', 'TOAST-1'] + values,
311 root2.attrib.values())
312
313 self.assertEqual(keys, root.attrib.keys())
314 self.assertEqual(values, root.attrib.values())
315
317
318
319 Element = self.etree.Element
320 root = Element("root")
321 self.assertRaises(TypeError, root.set, "newattr", 5)
322 self.assertRaises(TypeError, root.set, "newattr", object)
323 self.assertRaises(TypeError, root.set, "newattr", None)
324 self.assertRaises(TypeError, root.set, "newattr")
325
339
361
363 XML = self.etree.XML
364 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
365
366 root = XML(xml)
367 self.etree.strip_elements(root, 'a')
368 self.assertEqual(_bytes('<test><x></x></test>'),
369 self._writeElement(root))
370
371 root = XML(xml)
372 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
373 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'),
374 self._writeElement(root))
375
376 root = XML(xml)
377 self.etree.strip_elements(root, 'c')
378 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
379 self._writeElement(root))
380
382 XML = self.etree.XML
383 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>')
384
385 root = XML(xml)
386 self.etree.strip_elements(root, 'a')
387 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>'),
388 self._writeElement(root))
389
390 root = XML(xml)
391 self.etree.strip_elements(root, '{urn:a}b', 'c')
392 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>'),
393 self._writeElement(root))
394
395 root = XML(xml)
396 self.etree.strip_elements(root, '{urn:a}*', 'c')
397 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
398 self._writeElement(root))
399
400 root = XML(xml)
401 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
402 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
403 self._writeElement(root))
404
423
449
476
503
522
535
546
552
554 XML = self.etree.XML
555 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
556 self.assertEqual(root[0].target, "mypi")
557 self.assertEqual(root[0].get('my'), "1")
558 self.assertEqual(root[0].get('test'), " abc ")
559 self.assertEqual(root[0].get('quotes'), "' '")
560 self.assertEqual(root[0].get('only'), None)
561 self.assertEqual(root[0].get('names'), None)
562 self.assertEqual(root[0].get('nope'), None)
563
565 XML = self.etree.XML
566 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
567 self.assertEqual(root[0].target, "mypi")
568 self.assertEqual(root[0].attrib['my'], "1")
569 self.assertEqual(root[0].attrib['test'], " abc ")
570 self.assertEqual(root[0].attrib['quotes'], "' '")
571 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
572 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
573 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
574
576
577 ProcessingInstruction = self.etree.ProcessingInstruction
578
579 a = ProcessingInstruction("PI", "ONE")
580 b = copy.deepcopy(a)
581 b.text = "ANOTHER"
582
583 self.assertEqual('ONE', a.text)
584 self.assertEqual('ANOTHER', b.text)
585
601
616
627
639
658
663
676
687
688 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
689 events = list(iterparse(f, events=('end', 'comment')))
690 root = events[-1][1]
691 self.assertEqual(6, len(events))
692 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'],
693 [ name(*item) for item in events ])
694 self.assertEqual(
695 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
696 tostring(root))
697
709
710 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
711 events = list(iterparse(f, events=('end', 'pi')))
712 root = events[-2][1]
713 self.assertEqual(8, len(events))
714 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
715 ('pid','d'), 'a', ('pie','e')],
716 [ name(*item) for item in events ])
717 self.assertEqual(
718 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
719 tostring(ElementTree(root)))
720
735
741
743 iterparse = self.etree.iterparse
744 f = BytesIO('<a><b><c/></a>')
745 it = iterparse(f, events=('start', 'end'), recover=True)
746 events = [(ev, el.tag) for ev, el in it]
747 root = it.root
748 self.assertTrue(root is not None)
749
750 self.assertEqual(1, events.count(('start', 'a')))
751 self.assertEqual(1, events.count(('end', 'a')))
752
753 self.assertEqual(1, events.count(('start', 'b')))
754 self.assertEqual(1, events.count(('end', 'b')))
755
756 self.assertEqual(1, events.count(('start', 'c')))
757 self.assertEqual(1, events.count(('end', 'c')))
758
760 iterparse = self.etree.iterparse
761 f = BytesIO('<a><b><c/></d><b><c/></a></b>')
762 it = iterparse(f, events=('start', 'end'), recover=True)
763 events = [(ev, el.tag) for ev, el in it]
764 root = it.root
765 self.assertTrue(root is not None)
766
767 self.assertEqual(1, events.count(('start', 'a')))
768 self.assertEqual(1, events.count(('end', 'a')))
769
770 self.assertEqual(2, events.count(('start', 'b')))
771 self.assertEqual(2, events.count(('end', 'b')))
772
773 self.assertEqual(2, events.count(('start', 'c')))
774 self.assertEqual(2, events.count(('end', 'c')))
775
777 iterparse = self.etree.iterparse
778 f = BytesIO("""
779 <a> \n \n <b> b test </b> \n
780
781 \n\t <c> \n </c> </a> \n """)
782 iterator = iterparse(f, remove_blank_text=True)
783 text = [ (element.text, element.tail)
784 for event, element in iterator ]
785 self.assertEqual(
786 [(" b test ", None), (" \n ", None), (None, None)],
787 text)
788
790 iterparse = self.etree.iterparse
791 f = BytesIO('<a><b><d/></b><c/></a>')
792
793 iterator = iterparse(f, tag="b", events=('start', 'end'))
794 events = list(iterator)
795 root = iterator.root
796 self.assertEqual(
797 [('start', root[0]), ('end', root[0])],
798 events)
799
801 iterparse = self.etree.iterparse
802 f = BytesIO('<a><b><d/></b><c/></a>')
803
804 iterator = iterparse(f, tag="*", events=('start', 'end'))
805 events = list(iterator)
806 self.assertEqual(
807 8,
808 len(events))
809
811 iterparse = self.etree.iterparse
812 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
813
814 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
815 events = list(iterator)
816 root = iterator.root
817 self.assertEqual(
818 [('start', root[0]), ('end', root[0])],
819 events)
820
822 iterparse = self.etree.iterparse
823 f = BytesIO('<a><b><d/></b><c/></a>')
824 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
825 events = list(iterator)
826 root = iterator.root
827 self.assertEqual(
828 [('start', root[0]), ('end', root[0])],
829 events)
830
831 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
832 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
833 events = list(iterator)
834 root = iterator.root
835 self.assertEqual([], events)
836
838 iterparse = self.etree.iterparse
839 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
840 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
841 events = list(iterator)
842 self.assertEqual(8, len(events))
843
845 iterparse = self.etree.iterparse
846 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
847 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
848 events = list(iterator)
849 self.assertEqual([], events)
850
851 f = BytesIO('<a><b><d/></b><c/></a>')
852 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
853 events = list(iterator)
854 self.assertEqual(8, len(events))
855
857 text = _str('Søk på nettet')
858 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
859 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
860 ).encode('iso-8859-1')
861
862 self.assertRaises(self.etree.ParseError,
863 list, self.etree.iterparse(BytesIO(xml_latin1)))
864
866 text = _str('Søk på nettet', encoding="UTF-8")
867 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
868 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
869 ).encode('iso-8859-1')
870
871 iterator = self.etree.iterparse(BytesIO(xml_latin1),
872 encoding="iso-8859-1")
873 self.assertEqual(1, len(list(iterator)))
874
875 a = iterator.root
876 self.assertEqual(a.text, text)
877
879 tostring = self.etree.tostring
880 f = BytesIO('<root><![CDATA[test]]></root>')
881 context = self.etree.iterparse(f, strip_cdata=False)
882 content = [ el.text for event,el in context ]
883
884 self.assertEqual(['test'], content)
885 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
886 tostring(context.root))
887
891
896
915
916
917
940
941
942
944 assertEqual = self.assertEqual
945 assertFalse = self.assertFalse
946
947 events = []
948 class Target(object):
949 def start(self, tag, attrib):
950 events.append("start")
951 assertFalse(attrib)
952 assertEqual("TAG", tag)
953 def end(self, tag):
954 events.append("end")
955 assertEqual("TAG", tag)
956 def close(self):
957 return "DONE"
958
959 parser = self.etree.XMLParser(target=Target())
960 tree = self.etree.ElementTree()
961
962 self.assertRaises(TypeError,
963 tree.parse, BytesIO("<TAG/>"), parser=parser)
964 self.assertEqual(["start", "end"], events)
965
967
968 events = []
969 class Target(object):
970 def start(self, tag, attrib):
971 events.append("start-" + tag)
972 def end(self, tag):
973 events.append("end-" + tag)
974 if tag == 'a':
975 raise ValueError("dead and gone")
976 def data(self, data):
977 events.append("data-" + data)
978 def close(self):
979 events.append("close")
980 return "DONE"
981
982 parser = self.etree.XMLParser(target=Target())
983
984 try:
985 parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
986 done = parser.close()
987 self.fail("error expected, but parsing succeeded")
988 except ValueError:
989 done = 'value error received as expected'
990
991 self.assertEqual(["start-root", "data-A", "start-a",
992 "data-ca", "end-a", "close"],
993 events)
994
996
997 events = []
998 class Target(object):
999 def start(self, tag, attrib):
1000 events.append("start-" + tag)
1001 def end(self, tag):
1002 events.append("end-" + tag)
1003 if tag == 'a':
1004 raise ValueError("dead and gone")
1005 def data(self, data):
1006 events.append("data-" + data)
1007 def close(self):
1008 events.append("close")
1009 return "DONE"
1010
1011 parser = self.etree.XMLParser(target=Target())
1012
1013 try:
1014 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
1015 parser=parser)
1016 self.fail("error expected, but parsing succeeded")
1017 except ValueError:
1018 done = 'value error received as expected'
1019
1020 self.assertEqual(["start-root", "data-A", "start-a",
1021 "data-ca", "end-a", "close"],
1022 events)
1023
1025
1026 events = []
1027 class Target(object):
1028 def start(self, tag, attrib):
1029 events.append("start-" + tag)
1030 def end(self, tag):
1031 events.append("end-" + tag)
1032 def data(self, data):
1033 events.append("data-" + data)
1034 def comment(self, text):
1035 events.append("comment-" + text)
1036 def close(self):
1037 return "DONE"
1038
1039 parser = self.etree.XMLParser(target=Target(), collect_ids=False)
1040
1041 parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->'))
1042 parser.feed(_bytes('<sub xml:id="321"/>B</root>'))
1043 done = parser.close()
1044
1045 self.assertEqual("DONE", done)
1046 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1047 "start-sub", "end-sub", "data-B", "end-root"],
1048 events)
1049
1055 def end(self, tag):
1056 events.append("end-" + tag)
1057 def data(self, data):
1058 events.append("data-" + data)
1059 def comment(self, text):
1060 events.append("comment-" + text)
1061 def close(self):
1062 return "DONE"
1063
1064 parser = self.etree.XMLParser(target=Target())
1065
1066 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
1067 done = parser.close()
1068
1069 self.assertEqual("DONE", done)
1070 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1071 "start-sub", "end-sub", "comment-c", "data-B",
1072 "end-root", "comment-d"],
1073 events)
1074
1076 events = []
1077 class Target(object):
1078 def start(self, tag, attrib):
1079 events.append("start-" + tag)
1080 def end(self, tag):
1081 events.append("end-" + tag)
1082 def data(self, data):
1083 events.append("data-" + data)
1084 def pi(self, target, data):
1085 events.append("pi-" + target + "-" + data)
1086 def close(self):
1087 return "DONE"
1088
1089 parser = self.etree.XMLParser(target=Target())
1090
1091 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
1092 done = parser.close()
1093
1094 self.assertEqual("DONE", done)
1095 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b",
1096 "data-B", "end-root", "pi-test-c"],
1097 events)
1098
1100 events = []
1101 class Target(object):
1102 def start(self, tag, attrib):
1103 events.append("start-" + tag)
1104 def end(self, tag):
1105 events.append("end-" + tag)
1106 def data(self, data):
1107 events.append("data-" + data)
1108 def close(self):
1109 return "DONE"
1110
1111 parser = self.etree.XMLParser(target=Target(),
1112 strip_cdata=False)
1113
1114 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
1115 done = parser.close()
1116
1117 self.assertEqual("DONE", done)
1118 self.assertEqual(["start-root", "data-A", "start-a",
1119 "data-ca", "end-a", "data-B", "end-root"],
1120 events)
1121
1123 events = []
1124 class Target(object):
1125 def start(self, tag, attrib):
1126 events.append("start-" + tag)
1127 def end(self, tag):
1128 events.append("end-" + tag)
1129 def data(self, data):
1130 events.append("data-" + data)
1131 def close(self):
1132 events.append("close")
1133 return "DONE"
1134
1135 parser = self.etree.XMLParser(target=Target(),
1136 recover=True)
1137
1138 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
1139 done = parser.close()
1140
1141 self.assertEqual("DONE", done)
1142 self.assertEqual(["start-root", "data-A", "start-a",
1143 "data-ca", "end-a", "data-B",
1144 "end-root", "close"],
1145 events)
1146
1156
1166
1175
1190
1206
1208 iterwalk = self.etree.iterwalk
1209 root = self.etree.XML(
1210 b'<?C0?><a><?Ca?><b><?Cb?></b><?Cc?><c/></a><?C99?>')
1211
1212 iterator = iterwalk(root, events=('start', 'end', 'pi'))
1213 events = list(iterator)
1214 self.assertEqual(
1215 [('start', root), ('pi', root[0]),
1216 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]),
1217 ('pi', root[2]), ('start', root[3]), ('end', root[3]),
1218 ('end', root),
1219 ],
1220 events)
1221
1223 iterwalk = self.etree.iterwalk
1224 root = self.etree.XML(
1225 b'<?C0?><a><?Ca?><b><?Cb?></b><?Cc?><c/></a><?C99?>')
1226
1227 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'pi'))
1228 events = list(iterator)
1229 self.assertEqual(
1230 [('pi', root.getprevious()),
1231 ('start', root), ('pi', root[0]),
1232 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]),
1233 ('pi', root[2]), ('start', root[3]), ('end', root[3]),
1234 ('end', root), ('pi', root.getnext()),
1235 ],
1236 events)
1237
1255
1270
1280
1282 iterwalk = self.etree.iterwalk
1283 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1284
1285 iterator = iterwalk(root, events=('start','end'))
1286 events = list(iterator)
1287 self.assertEqual(
1288 [('start', root), ('start', root[0]), ('end', root[0]),
1289 ('start', root[1]), ('end', root[1]), ('end', root)],
1290 events)
1291
1301
1311
1325
1336
1338 iterwalk = self.etree.iterwalk
1339 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
1340
1341 attr_name = '{testns}bla'
1342 events = []
1343 iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
1344 for event, elem in iterator:
1345 events.append(event)
1346 if event == 'start':
1347 if elem.tag != '{ns1}a':
1348 elem.set(attr_name, 'value')
1349
1350 self.assertEqual(
1351 ['start-ns', 'start', 'start', 'start-ns', 'start',
1352 'end', 'end-ns', 'end', 'end', 'end-ns'],
1353 events)
1354
1355 self.assertEqual(
1356 None,
1357 root.get(attr_name))
1358 self.assertEqual(
1359 'value',
1360 root[0].get(attr_name))
1361
1374
1376 iterwalk = self.etree.iterwalk
1377 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>'))
1378
1379 iterator = iterwalk(root, events=('start', 'end'))
1380 tags = []
1381 for event, elem in iterator:
1382 tags.append((event, elem.tag))
1383 if elem.tag in ('b', 'e'):
1384
1385 iterator.skip_subtree()
1386
1387 self.assertEqual(
1388 [('start', 'a'),
1389 ('start', 'b'), ('end', 'b'),
1390 ('start', 'd'),
1391 ('start', 'e'), ('end', 'e'),
1392 ('end', 'd'),
1393 ('end', 'a')],
1394 tags)
1395
1397 iterwalk = self.etree.iterwalk
1398 root = self.etree.XML(_bytes(
1399 '<a xmlns="ns1"><b xmlns="nsb"><c xmlns="ns2"/></b><d xmlns="ns2"><e/></d></a>'))
1400
1401 events = []
1402 iterator = iterwalk(root, events=('start','start-ns','end-ns'))
1403 for event, elem in iterator:
1404 if event in ('start-ns', 'end-ns'):
1405 events.append((event, elem))
1406 if event == 'start-ns' and elem == ('', 'nsb'):
1407 events.append('skip')
1408 iterator.skip_subtree()
1409 else:
1410 events.append((event, elem.tag))
1411
1412 self.assertEqual(
1413 [('start-ns', ('', 'ns1')),
1414 ('start', '{ns1}a'),
1415 ('start-ns', ('', 'nsb')),
1416 'skip',
1417 ('start', '{nsb}b'),
1418 ('end-ns', None),
1419 ('start-ns', ('', 'ns2')),
1420 ('start', '{ns2}d'),
1421 ('start', '{ns2}e'),
1422 ('end-ns', None),
1423 ('end-ns', None)
1424 ],
1425 events)
1426
1437
1439 parse = self.etree.parse
1440 parser = self.etree.XMLParser(dtd_validation=True)
1441 assertEqual = self.assertEqual
1442 test_url = _str("__nosuch.dtd")
1443
1444 class MyResolver(self.etree.Resolver):
1445 def resolve(self, url, id, context):
1446 assertEqual(url, test_url)
1447 return self.resolve_string(
1448 _str('''<!ENTITY myentity "%s">
1449 <!ELEMENT doc ANY>''') % url, context)
1450
1451 parser.resolvers.add(MyResolver())
1452
1453 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1454 tree = parse(StringIO(xml), parser)
1455 root = tree.getroot()
1456 self.assertEqual(root.text, test_url)
1457
1459 parse = self.etree.parse
1460 parser = self.etree.XMLParser(dtd_validation=True)
1461 assertEqual = self.assertEqual
1462 test_url = _str("__nosuch.dtd")
1463
1464 class MyResolver(self.etree.Resolver):
1465 def resolve(self, url, id, context):
1466 assertEqual(url, test_url)
1467 return self.resolve_string(
1468 (_str('''<!ENTITY myentity "%s">
1469 <!ELEMENT doc ANY>''') % url).encode('utf-8'),
1470 context)
1471
1472 parser.resolvers.add(MyResolver())
1473
1474 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1475 tree = parse(StringIO(xml), parser)
1476 root = tree.getroot()
1477 self.assertEqual(root.text, test_url)
1478
1480 parse = self.etree.parse
1481 parser = self.etree.XMLParser(dtd_validation=True)
1482 assertEqual = self.assertEqual
1483 test_url = _str("__nosuch.dtd")
1484
1485 class MyResolver(self.etree.Resolver):
1486 def resolve(self, url, id, context):
1487 assertEqual(url, test_url)
1488 return self.resolve_file(
1489 SillyFileLike(
1490 _str('''<!ENTITY myentity "%s">
1491 <!ELEMENT doc ANY>''') % url), context)
1492
1493 parser.resolvers.add(MyResolver())
1494
1495 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1496 tree = parse(StringIO(xml), parser)
1497 root = tree.getroot()
1498 self.assertEqual(root.text, test_url)
1499
1501 parse = self.etree.parse
1502 parser = self.etree.XMLParser(attribute_defaults=True)
1503 assertEqual = self.assertEqual
1504 test_url = _str("__nosuch.dtd")
1505
1506 class MyResolver(self.etree.Resolver):
1507 def resolve(self, url, id, context):
1508 assertEqual(url, test_url)
1509 return self.resolve_filename(
1510 fileInTestDir('test.dtd'), context)
1511
1512 parser.resolvers.add(MyResolver())
1513
1514 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1515 tree = parse(StringIO(xml), parser)
1516 root = tree.getroot()
1517 self.assertEqual(
1518 root.attrib, {'default': 'valueA'})
1519 self.assertEqual(
1520 root[0].attrib, {'default': 'valueB'})
1521
1536
1537 parser.resolvers.add(MyResolver())
1538
1539 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1540 tree = parse(StringIO(xml), parser,
1541 base_url=fileUrlInTestDir('__test.xml'))
1542 root = tree.getroot()
1543 self.assertEqual(
1544 root.attrib, {'default': 'valueA'})
1545 self.assertEqual(
1546 root[0].attrib, {'default': 'valueB'})
1547
1549 parse = self.etree.parse
1550 parser = self.etree.XMLParser(attribute_defaults=True)
1551 assertEqual = self.assertEqual
1552 test_url = _str("__nosuch.dtd")
1553
1554 class MyResolver(self.etree.Resolver):
1555 def resolve(self, url, id, context):
1556 assertEqual(url, test_url)
1557 return self.resolve_file(
1558 open(fileInTestDir('test.dtd'), 'rb'), context)
1559
1560 parser.resolvers.add(MyResolver())
1561
1562 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1563 tree = parse(StringIO(xml), parser)
1564 root = tree.getroot()
1565 self.assertEqual(
1566 root.attrib, {'default': 'valueA'})
1567 self.assertEqual(
1568 root[0].attrib, {'default': 'valueB'})
1569
1571 parse = self.etree.parse
1572 parser = self.etree.XMLParser(load_dtd=True)
1573 assertEqual = self.assertEqual
1574 test_url = _str("__nosuch.dtd")
1575
1576 class check(object):
1577 resolved = False
1578
1579 class MyResolver(self.etree.Resolver):
1580 def resolve(self, url, id, context):
1581 assertEqual(url, test_url)
1582 check.resolved = True
1583 return self.resolve_empty(context)
1584
1585 parser.resolvers.add(MyResolver())
1586
1587 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1588 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
1589 self.assertTrue(check.resolved)
1590
1597
1598 class MyResolver(self.etree.Resolver):
1599 def resolve(self, url, id, context):
1600 raise _LocalException
1601
1602 parser.resolvers.add(MyResolver())
1603
1604 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
1605 self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
1606
1623
1625 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]>
1626 <root>
1627 <child1/>
1628 <child2/>
1629 <child3> </child3>
1630 </root>''')
1631
1632 parser = self.etree.XMLParser(resolve_entities=False)
1633 root = etree.fromstring(xml, parser)
1634 self.assertEqual([ el.tag for el in root ],
1635 ['child1', 'child2', 'child3'])
1636
1637 root[0] = root[-1]
1638 self.assertEqual([ el.tag for el in root ],
1639 ['child3', 'child2'])
1640 self.assertEqual(root[0][0].text, ' ')
1641 self.assertEqual(root[0][0].name, 'nbsp')
1642
1658
1676
1683
1685 Entity = self.etree.Entity
1686 self.assertRaises(ValueError, Entity, 'a b c')
1687 self.assertRaises(ValueError, Entity, 'a,b')
1688 self.assertRaises(ValueError, Entity, 'a\0b')
1689 self.assertRaises(ValueError, Entity, '#abc')
1690 self.assertRaises(ValueError, Entity, '#xxyz')
1691
1704
1725
1738
1750
1759
1768
1769
1779
1788
1790 Element = self.etree.Element
1791 SubElement = self.etree.SubElement
1792 root = Element('root')
1793 self.assertRaises(ValueError, root.append, root)
1794 child = SubElement(root, 'child')
1795 self.assertRaises(ValueError, child.append, root)
1796 child2 = SubElement(child, 'child2')
1797 self.assertRaises(ValueError, child2.append, root)
1798 self.assertRaises(ValueError, child2.append, child)
1799 self.assertEqual('child2', root[0][0].tag)
1800
1813
1826
1837
1848
1858
1868
1884
1900
1906
1921
1934
1949
1962
1977
1990
2005
2018
2019
2027
2028
2038
2039
2054
2055
2065
2066
2077
2104
2105
2107 self.assertRaises(TypeError, self.etree.dump, None)
2108
2121
2134
2155
2164
2166 XML = self.etree.XML
2167
2168 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
2169 result = []
2170 for el in root.iterchildren(reversed=True):
2171 result.append(el.tag)
2172 self.assertEqual(['three', 'two', 'one'], result)
2173
2182
2191
2200
2202 XML = self.etree.XML
2203
2204 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2205 result = []
2206 for el in root.iterchildren(tag=['two', 'three']):
2207 result.append(el.text)
2208 self.assertEqual(['Two', 'Bla', None], result)
2209
2211 XML = self.etree.XML
2212
2213 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2214 result = []
2215 for el in root.iterchildren('two', 'three'):
2216 result.append(el.text)
2217 self.assertEqual(['Two', 'Bla', None], result)
2218
2220 XML = self.etree.XML
2221
2222 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2223 result = []
2224 for el in root.iterchildren(reversed=True, tag=['two', 'three']):
2225 result.append(el.text)
2226 self.assertEqual([None, 'Bla', 'Two'], result)
2227
2248
2270
2272 Element = self.etree.Element
2273 SubElement = self.etree.SubElement
2274
2275 a = Element('a')
2276 b = SubElement(a, 'b')
2277 c = SubElement(a, 'c')
2278 d = SubElement(b, 'd')
2279 self.assertEqual(
2280 [b, a],
2281 list(d.iterancestors(tag=('a', 'b'))))
2282 self.assertEqual(
2283 [b, a],
2284 list(d.iterancestors('a', 'b')))
2285
2286 self.assertEqual(
2287 [],
2288 list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
2289 self.assertEqual(
2290 [],
2291 list(d.iterancestors('w', 'x', 'y', 'z')))
2292
2293 self.assertEqual(
2294 [],
2295 list(d.iterancestors(tag=('d', 'x'))))
2296 self.assertEqual(
2297 [],
2298 list(d.iterancestors('d', 'x')))
2299
2300 self.assertEqual(
2301 [b, a],
2302 list(d.iterancestors(tag=('b', '*'))))
2303 self.assertEqual(
2304 [b, a],
2305 list(d.iterancestors('b', '*')))
2306
2307 self.assertEqual(
2308 [b],
2309 list(d.iterancestors(tag=('b', 'c'))))
2310 self.assertEqual(
2311 [b],
2312 list(d.iterancestors('b', 'c')))
2313
2330
2332 Element = self.etree.Element
2333 SubElement = self.etree.SubElement
2334
2335 a = Element('a')
2336 b = SubElement(a, 'b')
2337 c = SubElement(a, 'c')
2338 d = SubElement(b, 'd')
2339 e = SubElement(c, 'e')
2340
2341 self.assertEqual(
2342 [],
2343 list(a.iterdescendants('a')))
2344 self.assertEqual(
2345 [],
2346 list(a.iterdescendants(tag='a')))
2347
2348 a2 = SubElement(e, 'a')
2349 self.assertEqual(
2350 [a2],
2351 list(a.iterdescendants('a')))
2352
2353 self.assertEqual(
2354 [a2],
2355 list(c.iterdescendants('a')))
2356 self.assertEqual(
2357 [a2],
2358 list(c.iterdescendants(tag='a')))
2359
2361 Element = self.etree.Element
2362 SubElement = self.etree.SubElement
2363
2364 a = Element('a')
2365 b = SubElement(a, 'b')
2366 c = SubElement(a, 'c')
2367 d = SubElement(b, 'd')
2368 e = SubElement(c, 'e')
2369
2370 self.assertEqual(
2371 [b, e],
2372 list(a.iterdescendants(tag=('a', 'b', 'e'))))
2373 self.assertEqual(
2374 [b, e],
2375 list(a.iterdescendants('a', 'b', 'e')))
2376
2377 a2 = SubElement(e, 'a')
2378 self.assertEqual(
2379 [b, a2],
2380 list(a.iterdescendants(tag=('a', 'b'))))
2381 self.assertEqual(
2382 [b, a2],
2383 list(a.iterdescendants('a', 'b')))
2384
2385 self.assertEqual(
2386 [],
2387 list(c.iterdescendants(tag=('x', 'y', 'z'))))
2388 self.assertEqual(
2389 [],
2390 list(c.iterdescendants('x', 'y', 'z')))
2391
2392 self.assertEqual(
2393 [b, d, c, e, a2],
2394 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
2395 self.assertEqual(
2396 [b, d, c, e, a2],
2397 list(a.iterdescendants('x', 'y', 'z', '*')))
2398
2416
2433
2451
2475
2477 Element = self.etree.Element
2478 SubElement = self.etree.SubElement
2479
2480 a = Element('a')
2481 b = SubElement(a, 'b')
2482 c = SubElement(a, 'c')
2483 d = SubElement(b, 'd')
2484 self.assertEqual(
2485 [],
2486 list(a.itersiblings(tag='XXX')))
2487 self.assertEqual(
2488 [c],
2489 list(b.itersiblings(tag='c')))
2490 self.assertEqual(
2491 [c],
2492 list(b.itersiblings(tag='*')))
2493 self.assertEqual(
2494 [b],
2495 list(c.itersiblings(preceding=True, tag='b')))
2496 self.assertEqual(
2497 [],
2498 list(c.itersiblings(preceding=True, tag='c')))
2499
2501 Element = self.etree.Element
2502 SubElement = self.etree.SubElement
2503
2504 a = Element('a')
2505 b = SubElement(a, 'b')
2506 c = SubElement(a, 'c')
2507 d = SubElement(b, 'd')
2508 e = SubElement(a, 'e')
2509 self.assertEqual(
2510 [],
2511 list(a.itersiblings(tag=('XXX', 'YYY'))))
2512 self.assertEqual(
2513 [c, e],
2514 list(b.itersiblings(tag=('c', 'd', 'e'))))
2515 self.assertEqual(
2516 [b],
2517 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
2518 self.assertEqual(
2519 [c, b],
2520 list(e.itersiblings(preceding=True, tag=('c', '*'))))
2521
2523 parseid = self.etree.parseid
2524 XML = self.etree.XML
2525 xml_text = _bytes('''
2526 <!DOCTYPE document [
2527 <!ELEMENT document (h1,p)*>
2528 <!ELEMENT h1 (#PCDATA)>
2529 <!ATTLIST h1 myid ID #REQUIRED>
2530 <!ELEMENT p (#PCDATA)>
2531 <!ATTLIST p someid ID #REQUIRED>
2532 ]>
2533 <document>
2534 <h1 myid="chapter1">...</h1>
2535 <p id="note1" class="note">...</p>
2536 <p>Regular paragraph.</p>
2537 <p xml:id="xmlid">XML:ID paragraph.</p>
2538 <p someid="warn1" class="warning">...</p>
2539 </document>
2540 ''')
2541
2542 tree, dic = parseid(BytesIO(xml_text))
2543 root = tree.getroot()
2544 root2 = XML(xml_text)
2545 self.assertEqual(self._writeElement(root),
2546 self._writeElement(root2))
2547 expected = {
2548 "chapter1" : root[0],
2549 "xmlid" : root[3],
2550 "warn1" : root[4]
2551 }
2552 self.assertTrue("chapter1" in dic)
2553 self.assertTrue("warn1" in dic)
2554 self.assertTrue("xmlid" in dic)
2555 self._checkIDDict(dic, expected)
2556
2558 XMLDTDID = self.etree.XMLDTDID
2559 XML = self.etree.XML
2560 xml_text = _bytes('''
2561 <!DOCTYPE document [
2562 <!ELEMENT document (h1,p)*>
2563 <!ELEMENT h1 (#PCDATA)>
2564 <!ATTLIST h1 myid ID #REQUIRED>
2565 <!ELEMENT p (#PCDATA)>
2566 <!ATTLIST p someid ID #REQUIRED>
2567 ]>
2568 <document>
2569 <h1 myid="chapter1">...</h1>
2570 <p id="note1" class="note">...</p>
2571 <p>Regular paragraph.</p>
2572 <p xml:id="xmlid">XML:ID paragraph.</p>
2573 <p someid="warn1" class="warning">...</p>
2574 </document>
2575 ''')
2576
2577 root, dic = XMLDTDID(xml_text)
2578 root2 = XML(xml_text)
2579 self.assertEqual(self._writeElement(root),
2580 self._writeElement(root2))
2581 expected = {
2582 "chapter1" : root[0],
2583 "xmlid" : root[3],
2584 "warn1" : root[4]
2585 }
2586 self.assertTrue("chapter1" in dic)
2587 self.assertTrue("warn1" in dic)
2588 self.assertTrue("xmlid" in dic)
2589 self._checkIDDict(dic, expected)
2590
2592 XMLDTDID = self.etree.XMLDTDID
2593 XML = self.etree.XML
2594 xml_text = _bytes('''
2595 <document>
2596 <h1 myid="chapter1">...</h1>
2597 <p id="note1" class="note">...</p>
2598 <p>Regular paragraph.</p>
2599 <p someid="warn1" class="warning">...</p>
2600 </document>
2601 ''')
2602
2603 root, dic = XMLDTDID(xml_text)
2604 root2 = XML(xml_text)
2605 self.assertEqual(self._writeElement(root),
2606 self._writeElement(root2))
2607 expected = {}
2608 self._checkIDDict(dic, expected)
2609
2611 XMLDTDID = self.etree.XMLDTDID
2612 XML = self.etree.XML
2613 xml_text = _bytes('''
2614 <!DOCTYPE document [
2615 <!ELEMENT document (h1,p)*>
2616 <!ELEMENT h1 (#PCDATA)>
2617 <!ATTLIST h1 myid ID #REQUIRED>
2618 <!ELEMENT p (#PCDATA)>
2619 <!ATTLIST p someid ID #REQUIRED>
2620 ]>
2621 <document>
2622 <h1 myid="chapter1">...</h1>
2623 <p id="note1" class="note">...</p>
2624 <p>Regular paragraph.</p>
2625 <p xml:id="xmlid">XML:ID paragraph.</p>
2626 <p someid="warn1" class="warning">...</p>
2627 </document>
2628 ''')
2629
2630 parser = etree.XMLParser(collect_ids=False)
2631 root, dic = XMLDTDID(xml_text, parser=parser)
2632 root2 = XML(xml_text)
2633 self.assertEqual(self._writeElement(root),
2634 self._writeElement(root2))
2635 self.assertFalse(dic)
2636 self._checkIDDict(dic, {})
2637
2639 self.assertEqual(len(dic),
2640 len(expected))
2641 self.assertEqual(sorted(dic.items()),
2642 sorted(expected.items()))
2643 if sys.version_info < (3,):
2644 self.assertEqual(sorted(dic.iteritems()),
2645 sorted(expected.iteritems()))
2646 self.assertEqual(sorted(dic.keys()),
2647 sorted(expected.keys()))
2648 if sys.version_info < (3,):
2649 self.assertEqual(sorted(dic.iterkeys()),
2650 sorted(expected.iterkeys()))
2651 if sys.version_info < (3,):
2652 self.assertEqual(sorted(dic.values()),
2653 sorted(expected.values()))
2654 self.assertEqual(sorted(dic.itervalues()),
2655 sorted(expected.itervalues()))
2656
2663
2665 etree = self.etree
2666
2667 r = {'foo': 'http://ns.infrae.com/foo'}
2668 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2669 self.assertEqual(
2670 'foo',
2671 e.prefix)
2672 self.assertEqual(
2673 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
2674 self._writeElement(e))
2675
2677 etree = self.etree
2678
2679 r = {None: 'http://ns.infrae.com/foo'}
2680 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2681 self.assertEqual(
2682 None,
2683 e.prefix)
2684 self.assertEqual(
2685 '{http://ns.infrae.com/foo}bar',
2686 e.tag)
2687 self.assertEqual(
2688 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
2689 self._writeElement(e))
2690
2692 etree = self.etree
2693
2694 r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'}
2695 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2696 self.assertEqual(None, e.prefix)
2697 self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag)
2698 self.assertEqual(
2699 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'),
2700 self._writeElement(e))
2701
2703 etree = self.etree
2704
2705 r = {None: 'http://ns.infrae.com/foo',
2706 'hoi': 'http://ns.infrae.com/hoi'}
2707 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2708 e.set('{http://ns.infrae.com/hoi}test', 'value')
2709 self.assertEqual(
2710 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
2711 self._writeElement(e))
2712
2714 etree = self.etree
2715
2716 root = etree.Element('{http://test/ns}root',
2717 nsmap={None: 'http://test/ns'})
2718 sub = etree.Element('{http://test/ns}sub',
2719 nsmap={'test': 'http://test/ns'})
2720
2721 sub.attrib['{http://test/ns}attr'] = 'value'
2722 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2723 self.assertEqual(
2724 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2725 etree.tostring(sub))
2726
2727 root.append(sub)
2728 self.assertEqual(
2729 _bytes('<root xmlns="http://test/ns">'
2730 '<sub xmlns:test="http://test/ns" test:attr="value"/>'
2731 '</root>'),
2732 etree.tostring(root))
2733
2735 etree = self.etree
2736
2737 root = etree.Element('root')
2738 sub = etree.Element('{http://test/ns}sub',
2739 nsmap={'test': 'http://test/ns'})
2740
2741 sub.attrib['{http://test/ns}attr'] = 'value'
2742 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2743 self.assertEqual(
2744 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2745 etree.tostring(sub))
2746
2747 root.append(sub)
2748 self.assertEqual(
2749 _bytes('<root>'
2750 '<test:sub xmlns:test="http://test/ns" test:attr="value"/>'
2751 '</root>'),
2752 etree.tostring(root))
2753
2755 etree = self.etree
2756
2757 root = etree.Element('root')
2758 sub = etree.Element('{http://test/ns}sub',
2759 nsmap={None: 'http://test/ns'})
2760
2761 sub.attrib['{http://test/ns}attr'] = 'value'
2762 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2763 self.assertEqual(
2764 _bytes('<sub xmlns="http://test/ns" '
2765 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2766 etree.tostring(sub))
2767
2768 root.append(sub)
2769 self.assertEqual(
2770 _bytes('<root>'
2771 '<sub xmlns="http://test/ns"'
2772 ' xmlns:ns0="http://test/ns" ns0:attr="value"/>'
2773 '</root>'),
2774 etree.tostring(root))
2775
2777 etree = self.etree
2778
2779 root = etree.Element('{http://test/ns}root',
2780 nsmap={'test': 'http://test/ns',
2781 None: 'http://test/ns'})
2782 sub = etree.Element('{http://test/ns}sub',
2783 nsmap={None: 'http://test/ns'})
2784
2785 sub.attrib['{http://test/ns}attr'] = 'value'
2786 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2787 self.assertEqual(
2788 _bytes('<sub xmlns="http://test/ns" '
2789 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2790 etree.tostring(sub))
2791
2792 root.append(sub)
2793 self.assertEqual(
2794 _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">'
2795 '<test:sub test:attr="value"/>'
2796 '</test:root>'),
2797 etree.tostring(root))
2798
2800 etree = self.etree
2801 r = {None: 'http://ns.infrae.com/foo',
2802 'hoi': 'http://ns.infrae.com/hoi'}
2803 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
2804 tree = etree.ElementTree(element=e)
2805 etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
2806 self.assertEqual(
2807 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
2808 self._writeElement(e))
2809
2811 etree = self.etree
2812
2813 r = {None: 'http://ns.infrae.com/foo'}
2814 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2815 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2816
2817 e1.append(e2)
2818
2819 self.assertEqual(
2820 None,
2821 e1.prefix)
2822 self.assertEqual(
2823 None,
2824 e1[0].prefix)
2825 self.assertEqual(
2826 '{http://ns.infrae.com/foo}bar',
2827 e1.tag)
2828 self.assertEqual(
2829 '{http://ns.infrae.com/foo}bar',
2830 e1[0].tag)
2831
2833 etree = self.etree
2834
2835 r = {None: 'http://ns.infrae.com/BAR'}
2836 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
2837 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2838
2839 e1.append(e2)
2840
2841 self.assertEqual(
2842 None,
2843 e1.prefix)
2844 self.assertNotEqual(
2845 None,
2846 e2.prefix)
2847 self.assertEqual(
2848 '{http://ns.infrae.com/BAR}bar',
2849 e1.tag)
2850 self.assertEqual(
2851 '{http://ns.infrae.com/foo}bar',
2852 e2.tag)
2853
2855 ns_href = "http://a.b.c"
2856 one = self.etree.fromstring(
2857 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2858 baz = one[0][0]
2859
2860 two = self.etree.fromstring(
2861 _bytes('<root xmlns:ns="%s"/>' % ns_href))
2862 two.append(baz)
2863 del one
2864
2865 self.assertEqual('{%s}baz' % ns_href, baz.tag)
2866 self.assertEqual(
2867 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
2868 self.etree.tostring(two))
2869
2883
2900
2911
2913 xml = ('<root>' +
2914 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2915 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8')
2916 root = self.etree.fromstring(xml)
2917 self.assertEqual(xml, self.etree.tostring(root))
2918 self.etree.cleanup_namespaces(root)
2919 self.assertEqual(
2920 b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 +
2921 b'<n64:x/>' + b'</a>'*100 + b'</root>',
2922 self.etree.tostring(root))
2923
2925 xml = ('<root>' +
2926 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2927 '<n64:x xmlns:a="A" a:attr="X"/>' +
2928 '</a>'*100 +
2929 '</root>').encode('utf8')
2930 root = self.etree.fromstring(xml)
2931 self.assertEqual(xml, self.etree.tostring(root))
2932 self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'})
2933 self.assertEqual(
2934 b'<root xmlns:n64="NS64">' + b'<a>'*100 +
2935 b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>',
2936 self.etree.tostring(root))
2937
2939 xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">'
2940 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2941 '<foo>foo:bar</foo>'
2942 '</root>').encode('utf8')
2943 root = self.etree.fromstring(xml)
2944 self.assertEqual(xml, self.etree.tostring(root))
2945 self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo'])
2946 self.assertEqual(
2947 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2948 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2949 b'<foo>foo:bar</foo>'
2950 b'</root>',
2951 self.etree.tostring(root))
2952
2954 xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">'
2955 '<sub xmlns:foo="FOO">'
2956 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2957 '<foo>foo:bar</foo>'
2958 '</sub>'
2959 '</root>').encode('utf8')
2960 root = self.etree.fromstring(xml)
2961 self.assertEqual(xml, self.etree.tostring(root))
2962 self.etree.cleanup_namespaces(
2963 root,
2964 top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'},
2965 keep_ns_prefixes=['foo'])
2966 self.assertEqual(
2967 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2968 b'<sub>'
2969 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2970 b'<foo>foo:bar</foo>'
2971 b'</sub>'
2972 b'</root>',
2973 self.etree.tostring(root))
2974
2976 etree = self.etree
2977
2978 r = {None: 'http://ns.infrae.com/foo',
2979 'hoi': 'http://ns.infrae.com/hoi'}
2980 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2981 self.assertEqual(
2982 r,
2983 e.nsmap)
2984
2986 etree = self.etree
2987
2988 re = {None: 'http://ns.infrae.com/foo',
2989 'hoi': 'http://ns.infrae.com/hoi'}
2990 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
2991
2992 rs = {None: 'http://ns.infrae.com/honk',
2993 'top': 'http://ns.infrae.com/top'}
2994 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
2995
2996 r = re.copy()
2997 r.update(rs)
2998 self.assertEqual(re, e.nsmap)
2999 self.assertEqual(r, s.nsmap)
3000
3002 etree = self.etree
3003 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
3004 self.assertEqual({'hha': None}, el.nsmap)
3005
3007 Element = self.etree.Element
3008 SubElement = self.etree.SubElement
3009
3010 a = Element('a')
3011 b = SubElement(a, 'b')
3012 c = SubElement(a, 'c')
3013 d = SubElement(b, 'd')
3014 e = SubElement(c, 'e')
3015 f = SubElement(c, 'f')
3016
3017 self.assertEqual(
3018 [a, b],
3019 list(a.getiterator('a', 'b')))
3020 self.assertEqual(
3021 [],
3022 list(a.getiterator('x', 'y')))
3023 self.assertEqual(
3024 [a, f],
3025 list(a.getiterator('f', 'a')))
3026 self.assertEqual(
3027 [c, e, f],
3028 list(c.getiterator('c', '*', 'a')))
3029 self.assertEqual(
3030 [],
3031 list(a.getiterator( (), () )))
3032
3034 Element = self.etree.Element
3035 SubElement = self.etree.SubElement
3036
3037 a = Element('a')
3038 b = SubElement(a, 'b')
3039 c = SubElement(a, 'c')
3040 d = SubElement(b, 'd')
3041 e = SubElement(c, 'e')
3042 f = SubElement(c, 'f')
3043
3044 self.assertEqual(
3045 [a, b],
3046 list(a.getiterator( ('a', 'b') )))
3047 self.assertEqual(
3048 [],
3049 list(a.getiterator( ('x', 'y') )))
3050 self.assertEqual(
3051 [a, f],
3052 list(a.getiterator( ('f', 'a') )))
3053 self.assertEqual(
3054 [c, e, f],
3055 list(c.getiterator( ('c', '*', 'a') )))
3056 self.assertEqual(
3057 [],
3058 list(a.getiterator( () )))
3059
3061 Element = self.etree.Element
3062 SubElement = self.etree.SubElement
3063
3064 a = Element('{a}a')
3065 b = SubElement(a, '{a}b')
3066 c = SubElement(a, '{a}c')
3067 d = SubElement(b, '{b}d')
3068 e = SubElement(c, '{a}e')
3069 f = SubElement(c, '{b}f')
3070 g = SubElement(c, 'g')
3071
3072 self.assertEqual(
3073 [a],
3074 list(a.getiterator('{a}a')))
3075 self.assertEqual(
3076 [],
3077 list(a.getiterator('{b}a')))
3078 self.assertEqual(
3079 [],
3080 list(a.getiterator('a')))
3081 self.assertEqual(
3082 [a,b,d,c,e,f,g],
3083 list(a.getiterator('*')))
3084 self.assertEqual(
3085 [f],
3086 list(c.getiterator('{b}*')))
3087 self.assertEqual(
3088 [d, f],
3089 list(a.getiterator('{b}*')))
3090 self.assertEqual(
3091 [g],
3092 list(a.getiterator('g')))
3093 self.assertEqual(
3094 [g],
3095 list(a.getiterator('{}g')))
3096 self.assertEqual(
3097 [g],
3098 list(a.getiterator('{}*')))
3099
3101 Element = self.etree.Element
3102 Comment = self.etree.Comment
3103 SubElement = self.etree.SubElement
3104
3105 a = Element('{a}a')
3106 b = SubElement(a, '{nsA}b')
3107 c = SubElement(b, '{nsB}b')
3108 d = SubElement(a, 'b')
3109 e = SubElement(a, '{nsA}e')
3110 f = SubElement(e, '{nsB}e')
3111 g = SubElement(e, 'e')
3112 a.append(Comment('test'))
3113
3114 self.assertEqual(
3115 [b, c, d],
3116 list(a.getiterator('{*}b')))
3117 self.assertEqual(
3118 [e, f, g],
3119 list(a.getiterator('{*}e')))
3120 self.assertEqual(
3121 [a, b, c, d, e, f, g],
3122 list(a.getiterator('{*}*')))
3123
3148
3164
3181
3183 a = etree.Element("a")
3184 b = etree.SubElement(a, "b")
3185 c = etree.SubElement(a, "c")
3186 d1 = etree.SubElement(c, "d")
3187 d2 = etree.SubElement(c, "d")
3188 c.text = d1.text = 'TEXT'
3189
3190 tree = etree.ElementTree(a)
3191 self.assertEqual('.', tree.getelementpath(a))
3192 self.assertEqual('c/d[1]', tree.getelementpath(d1))
3193 self.assertEqual('c/d[2]', tree.getelementpath(d2))
3194
3195 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3196 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3197
3198 tree = etree.ElementTree(c)
3199 self.assertEqual('.', tree.getelementpath(c))
3200 self.assertEqual('d[2]', tree.getelementpath(d2))
3201 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3202
3203 tree = etree.ElementTree(b)
3204 self.assertEqual('.', tree.getelementpath(b))
3205 self.assertRaises(ValueError, tree.getelementpath, a)
3206 self.assertRaises(ValueError, tree.getelementpath, c)
3207 self.assertRaises(ValueError, tree.getelementpath, d2)
3208
3210 a = etree.Element("{http://ns1/}a")
3211 b = etree.SubElement(a, "{http://ns1/}b")
3212 c = etree.SubElement(a, "{http://ns1/}c")
3213 d1 = etree.SubElement(c, "{http://ns1/}d")
3214 d2 = etree.SubElement(c, "{http://ns2/}d")
3215 d3 = etree.SubElement(c, "{http://ns1/}d")
3216
3217 tree = etree.ElementTree(a)
3218 self.assertEqual('.', tree.getelementpath(a))
3219 self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]',
3220 tree.getelementpath(d1))
3221 self.assertEqual('{http://ns1/}c/{http://ns2/}d',
3222 tree.getelementpath(d2))
3223 self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]',
3224 tree.getelementpath(d3))
3225
3226 self.assertEqual(a, tree.find(tree.getelementpath(a)))
3227 self.assertEqual(b, tree.find(tree.getelementpath(b)))
3228 self.assertEqual(c, tree.find(tree.getelementpath(c)))
3229 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3230 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3231 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
3232
3233 tree = etree.ElementTree(c)
3234 self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1))
3235 self.assertEqual('{http://ns2/}d', tree.getelementpath(d2))
3236 self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3))
3237 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3238 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3239 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
3240
3241 tree = etree.ElementTree(b)
3242 self.assertRaises(ValueError, tree.getelementpath, d1)
3243 self.assertRaises(ValueError, tree.getelementpath, d2)
3244
3251
3258
3267
3269 XML = self.etree.XML
3270 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
3271 self.assertEqual(len(root.findall(".//{X}b")), 2)
3272 self.assertEqual(len(root.findall(".//{X}*")), 2)
3273 self.assertEqual(len(root.findall(".//b")), 3)
3274
3276 XML = self.etree.XML
3277 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3278 nsmap = {'xx': 'X'}
3279 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3280 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
3281 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3282 nsmap = {'xx': 'Y'}
3283 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
3284 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
3285 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3286
3296
3303
3305 etree = self.etree
3306 e = etree.Element('foo')
3307 for i in range(10):
3308 etree.SubElement(e, 'a%s' % i)
3309 for i in range(10):
3310 self.assertEqual(
3311 i,
3312 e.index(e[i]))
3313 self.assertEqual(
3314 3, e.index(e[3], 3))
3315 self.assertRaises(
3316 ValueError, e.index, e[3], 4)
3317 self.assertRaises(
3318 ValueError, e.index, e[3], 0, 2)
3319 self.assertRaises(
3320 ValueError, e.index, e[8], 0, -3)
3321 self.assertRaises(
3322 ValueError, e.index, e[8], -5, -3)
3323 self.assertEqual(
3324 8, e.index(e[8], 0, -1))
3325 self.assertEqual(
3326 8, e.index(e[8], -12, -1))
3327 self.assertEqual(
3328 0, e.index(e[0], -12, -1))
3329
3331 etree = self.etree
3332 e = etree.Element('foo')
3333 for i in range(10):
3334 el = etree.SubElement(e, 'a%s' % i)
3335 el.text = "text%d" % i
3336 el.tail = "tail%d" % i
3337
3338 child0 = e[0]
3339 child1 = e[1]
3340 child2 = e[2]
3341
3342 e.replace(e[0], e[1])
3343 self.assertEqual(
3344 9, len(e))
3345 self.assertEqual(
3346 child1, e[0])
3347 self.assertEqual(
3348 child1.text, "text1")
3349 self.assertEqual(
3350 child1.tail, "tail1")
3351 self.assertEqual(
3352 child0.tail, "tail0")
3353 self.assertEqual(
3354 child2, e[1])
3355
3356 e.replace(e[-1], e[0])
3357 self.assertEqual(
3358 child1, e[-1])
3359 self.assertEqual(
3360 child1.text, "text1")
3361 self.assertEqual(
3362 child1.tail, "tail1")
3363 self.assertEqual(
3364 child2, e[0])
3365
3367 etree = self.etree
3368 e = etree.Element('foo')
3369 for i in range(10):
3370 etree.SubElement(e, 'a%s' % i)
3371
3372 new_element = etree.Element("test")
3373 new_element.text = "TESTTEXT"
3374 new_element.tail = "TESTTAIL"
3375 child1 = e[1]
3376 e.replace(e[0], new_element)
3377 self.assertEqual(
3378 new_element, e[0])
3379 self.assertEqual(
3380 "TESTTEXT",
3381 e[0].text)
3382 self.assertEqual(
3383 "TESTTAIL",
3384 e[0].tail)
3385 self.assertEqual(
3386 child1, e[1])
3387
3389 Element = self.etree.Element
3390 SubElement = self.etree.SubElement
3391
3392 a = Element('a')
3393
3394 e = Element('e')
3395 f = Element('f')
3396 g = Element('g')
3397
3398 a[:] = [e, f, g]
3399 self.assertEqual(
3400 [e, f, g],
3401 list(a))
3402
3403 a[::-1] = [e, f, g]
3404 self.assertEqual(
3405 [g, f, e],
3406 list(a))
3407
3425
3443
3461
3463 Element = self.etree.Element
3464 SubElement = self.etree.SubElement
3465 try:
3466 slice
3467 except NameError:
3468 print("slice() not found")
3469 return
3470
3471 a = Element('a')
3472 b = SubElement(a, 'b')
3473 c = SubElement(a, 'c')
3474 d = SubElement(a, 'd')
3475 e = SubElement(a, 'e')
3476
3477 x = Element('x')
3478 y = Element('y')
3479 z = Element('z')
3480
3481 self.assertRaises(
3482 ValueError,
3483 operator.setitem, a, slice(1,None,2), [x, y, z])
3484
3485 self.assertEqual(
3486 [b, c, d, e],
3487 list(a))
3488
3501
3503 XML = self.etree.XML
3504 root = XML(_bytes(
3505 '<?xml version="1.0"?>\n'
3506 '<root>' + '\n' * 65536 +
3507 '<p>' + '\n' * 65536 + '</p>\n' +
3508 '<br/>\n'
3509 '</root>'))
3510
3511 if self.etree.LIBXML_VERSION >= (2, 9):
3512 expected = [2, 131074, 131076]
3513 else:
3514 expected = [2, 65535, 65535]
3515
3516 self.assertEqual(expected, [el.sourceline for el in root.iter()])
3517
3525
3534
3544
3554
3560
3568
3574
3581
3587
3589 etree = self.etree
3590 xml_header = '<?xml version="1.0" encoding="ascii"?>'
3591 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3592 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3593 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
3594
3595 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
3596
3597 tree = etree.parse(BytesIO(xml))
3598 docinfo = tree.docinfo
3599 self.assertEqual(docinfo.encoding, "ascii")
3600 self.assertEqual(docinfo.xml_version, "1.0")
3601 self.assertEqual(docinfo.public_id, pub_id)
3602 self.assertEqual(docinfo.system_url, sys_id)
3603 self.assertEqual(docinfo.root_name, 'html')
3604 self.assertEqual(docinfo.doctype, doctype_string)
3605
3621
3633
3645
3651
3653 etree = self.etree
3654 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3655 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3656 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
3657
3658 xml = _bytes('<!DOCTYPE root>\n<root/>')
3659 tree = etree.parse(BytesIO(xml))
3660 self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
3661 etree.tostring(tree, doctype=doctype_string))
3662
3664 etree = self.etree
3665 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3666 self.assertEqual(root.base, "http://no/such/url")
3667 self.assertEqual(
3668 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3669 root.base = "https://secret/url"
3670 self.assertEqual(root.base, "https://secret/url")
3671 self.assertEqual(
3672 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3673 "https://secret/url")
3674
3676 etree = self.etree
3677 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3678 self.assertEqual(root.base, "http://no/such/url")
3679 self.assertEqual(
3680 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3681 root.set('{http://www.w3.org/XML/1998/namespace}base',
3682 "https://secret/url")
3683 self.assertEqual(root.base, "https://secret/url")
3684 self.assertEqual(
3685 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3686 "https://secret/url")
3687
3693
3698
3705
3719
3721 Element = self.etree.Element
3722
3723 a = Element('a')
3724 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
3725 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
3726
3727 self.assertRaises(ValueError, Element, 'ha\0ho')
3728
3730 Element = self.etree.Element
3731
3732 a = Element('a')
3733 self.assertRaises(ValueError, setattr, a, "text",
3734 _str('ha\0ho'))
3735 self.assertRaises(ValueError, setattr, a, "tail",
3736 _str('ha\0ho'))
3737
3738 self.assertRaises(ValueError, Element,
3739 _str('ha\0ho'))
3740
3742 Element = self.etree.Element
3743
3744 a = Element('a')
3745 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
3746 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
3747
3748 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
3749 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
3750
3751 self.assertRaises(ValueError, Element, 'ha\x07ho')
3752 self.assertRaises(ValueError, Element, 'ha\x02ho')
3753
3755 Element = self.etree.Element
3756
3757 a = Element('a')
3758 self.assertRaises(ValueError, setattr, a, "text",
3759 _str('ha\x07ho'))
3760 self.assertRaises(ValueError, setattr, a, "text",
3761 _str('ha\x02ho'))
3762
3763 self.assertRaises(ValueError, setattr, a, "tail",
3764 _str('ha\x07ho'))
3765 self.assertRaises(ValueError, setattr, a, "tail",
3766 _str('ha\x02ho'))
3767
3768 self.assertRaises(ValueError, Element,
3769 _str('ha\x07ho'))
3770 self.assertRaises(ValueError, Element,
3771 _str('ha\x02ho'))
3772
3774 Element = self.etree.Element
3775
3776 a = Element('a')
3777 self.assertRaises(ValueError, setattr, a, "text",
3778 _str('ha\u1234\x07ho'))
3779 self.assertRaises(ValueError, setattr, a, "text",
3780 _str('ha\u1234\x02ho'))
3781
3782 self.assertRaises(ValueError, setattr, a, "tail",
3783 _str('ha\u1234\x07ho'))
3784 self.assertRaises(ValueError, setattr, a, "tail",
3785 _str('ha\u1234\x02ho'))
3786
3787 self.assertRaises(ValueError, Element,
3788 _str('ha\u1234\x07ho'))
3789 self.assertRaises(ValueError, Element,
3790 _str('ha\u1234\x02ho'))
3791
3805
3810
3828
3848
3850 tostring = self.etree.tostring
3851 html = self.etree.fromstring(
3852 '<html><body>'
3853 '<div><p>Some text<i>\r\n</i></p></div>\r\n'
3854 '</body></html>',
3855 parser=self.etree.HTMLParser())
3856 self.assertEqual(html.tag, 'html')
3857 div = html.find('.//div')
3858 self.assertEqual(div.tail, '\r\n')
3859 result = tostring(div, method='html')
3860 self.assertEqual(
3861 result,
3862 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3863 result = tostring(div, method='html', with_tail=True)
3864 self.assertEqual(
3865 result,
3866 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3867 result = tostring(div, method='html', with_tail=False)
3868 self.assertEqual(
3869 result,
3870 _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
3871
3893
3895 tostring = self.etree.tostring
3896 XML = self.etree.XML
3897 ElementTree = self.etree.ElementTree
3898
3899 root = XML(_bytes("<root/>"))
3900
3901 tree = ElementTree(root)
3902 self.assertEqual(None, tree.docinfo.standalone)
3903
3904 result = tostring(root, xml_declaration=True, encoding="ASCII")
3905 self.assertEqual(result, _bytes(
3906 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3907
3908 result = tostring(root, xml_declaration=True, encoding="ASCII",
3909 standalone=True)
3910 self.assertEqual(result, _bytes(
3911 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3912
3913 tree = ElementTree(XML(result))
3914 self.assertEqual(True, tree.docinfo.standalone)
3915
3916 result = tostring(root, xml_declaration=True, encoding="ASCII",
3917 standalone=False)
3918 self.assertEqual(result, _bytes(
3919 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
3920
3921 tree = ElementTree(XML(result))
3922 self.assertEqual(False, tree.docinfo.standalone)
3923
3943
3945 tostring = self.etree.tostring
3946 Element = self.etree.Element
3947 SubElement = self.etree.SubElement
3948
3949 a = Element('a')
3950 a.text = "A"
3951 a.tail = "tail"
3952 b = SubElement(a, 'b')
3953 b.text = "B"
3954 b.tail = _str("Søk på nettet")
3955 c = SubElement(a, 'c')
3956 c.text = "C"
3957
3958 result = tostring(a, method="text", encoding="UTF-16")
3959
3960 self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
3961 result)
3962
3964 tostring = self.etree.tostring
3965 Element = self.etree.Element
3966 SubElement = self.etree.SubElement
3967
3968 a = Element('a')
3969 a.text = _str('Søk på nettetA')
3970 a.tail = "tail"
3971 b = SubElement(a, 'b')
3972 b.text = "B"
3973 b.tail = _str('Søk på nettetB')
3974 c = SubElement(a, 'c')
3975 c.text = "C"
3976
3977 self.assertRaises(UnicodeEncodeError,
3978 tostring, a, method="text")
3979
3980 self.assertEqual(
3981 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
3982 tostring(a, encoding="UTF-8", method="text"))
3983
3996
4012
4016
4031
4049
4062
4064 tostring = self.etree.tostring
4065 Element = self.etree.Element
4066 SubElement = self.etree.SubElement
4067
4068 a = Element('a')
4069 b = SubElement(a, 'b')
4070 c = SubElement(a, 'c')
4071 d = SubElement(c, 'd')
4072 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
4073 self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
4074 self.assertEqual(_bytes('<b></b>'),
4075 canonicalize(tostring(b, encoding=_unicode)))
4076 self.assertEqual(_bytes('<c><d></d></c>'),
4077 canonicalize(tostring(c, encoding=_unicode)))
4078
4083
4098
4100 tostring = self.etree.tostring
4101 Element = self.etree.Element
4102 SubElement = self.etree.SubElement
4103
4104 a = Element('a')
4105 b = SubElement(a, 'b')
4106 c = SubElement(a, 'c')
4107
4108 result = tostring(a, encoding=_unicode)
4109 self.assertEqual(result, "<a><b/><c/></a>")
4110
4111 result = tostring(a, encoding=_unicode, pretty_print=False)
4112 self.assertEqual(result, "<a><b/><c/></a>")
4113
4114 result = tostring(a, encoding=_unicode, pretty_print=True)
4115 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4116
4128
4130 class SubEl(etree.ElementBase):
4131 pass
4132
4133 el1 = SubEl()
4134 el2 = SubEl()
4135 self.assertEqual('SubEl', el1.tag)
4136 self.assertEqual('SubEl', el2.tag)
4137 el1.other = el2
4138 el2.other = el1
4139
4140 del el1, el2
4141 gc.collect()
4142
4143
4157
4159 root = etree.Element('parent')
4160 c1 = etree.SubElement(root, 'child1')
4161 c2 = etree.SubElement(root, 'child2')
4162
4163 root.remove(c1)
4164 root.remove(c2)
4165 c1.addnext(c2)
4166 c1.tail = 'abc'
4167 c2.tail = 'xyz'
4168 del c1
4169
4170 c2.getprevious()
4171
4172 self.assertEqual('child1', c2.getprevious().tag)
4173 self.assertEqual('abc', c2.getprevious().tail)
4174
4175
4176
4177 - def _writeElement(self, element, encoding='us-ascii', compression=0):
4188
4189
4233
4234 res_instance = res()
4235 parser = etree.XMLParser(load_dtd = True)
4236 parser.resolvers.add(res_instance)
4237
4238 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4239 parser = parser)
4240
4241 self.include(tree)
4242
4243 called = list(res_instance.called.items())
4244 called.sort()
4245 self.assertEqual(
4246 [("dtd", True), ("include", True), ("input", True)],
4247 called)
4248
4250 data = textwrap.dedent('''
4251 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
4252 <foo/>
4253 <xi:include href="./test.xml" />
4254 </doc>
4255 ''')
4256
4257 class Resolver(etree.Resolver):
4258 called = {}
4259
4260 def resolve(self, url, id, context):
4261 if url.endswith("test_xinclude.xml"):
4262 assert not self.called.get("input")
4263 self.called["input"] = True
4264 return None
4265 elif url.endswith('/test5.xml'):
4266 assert not self.called.get("DONE")
4267 self.called["DONE"] = True
4268 return self.resolve_string('<DONE/>', context)
4269 else:
4270 _, filename = url.rsplit('/', 1)
4271 assert not self.called.get(filename)
4272 self.called[filename] = True
4273 next_data = data.replace(
4274 'test.xml', 'test%d.xml' % len(self.called))
4275 return self.resolve_string(next_data, context)
4276
4277 res_instance = Resolver()
4278 parser = etree.XMLParser(load_dtd=True)
4279 parser.resolvers.add(res_instance)
4280
4281 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4282 parser=parser)
4283
4284 self.include(tree)
4285
4286 called = list(res_instance.called.items())
4287 called.sort()
4288 self.assertEqual(
4289 [("DONE", True), ("input", True), ("test.xml", True),
4290 ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)],
4291 called)
4292
4293
4297
4298
4300 from lxml import ElementInclude
4301
4302 - def include(self, tree, loader=None, max_depth=None):
4304
4305 XINCLUDE = {}
4306
4307 XINCLUDE["Recursive1.xml"] = """\
4308 <?xml version='1.0'?>
4309 <document xmlns:xi="http://www.w3.org/2001/XInclude">
4310 <p>The following is the source code of Recursive2.xml:</p>
4311 <xi:include href="Recursive2.xml"/>
4312 </document>
4313 """
4314
4315 XINCLUDE["Recursive2.xml"] = """\
4316 <?xml version='1.0'?>
4317 <document xmlns:xi="http://www.w3.org/2001/XInclude">
4318 <p>The following is the source code of Recursive3.xml:</p>
4319 <xi:include href="Recursive3.xml"/>
4320 </document>
4321 """
4322
4323 XINCLUDE["Recursive3.xml"] = """\
4324 <?xml version='1.0'?>
4325 <document xmlns:xi="http://www.w3.org/2001/XInclude">
4326 <p>The following is the source code of Recursive1.xml:</p>
4327 <xi:include href="Recursive1.xml"/>
4328 </document>
4329 """
4330
4339
4341
4342 document = self.xinclude_loader("Recursive1.xml").getroottree()
4343 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm:
4344 self.include(document, self.xinclude_loader)
4345 self.assertEqual(str(cm.exception),
4346 "recursive include of 'Recursive2.xml' detected")
4347
4348
4349 document = self.xinclude_loader("Recursive1.xml").getroottree()
4350 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm:
4351 self.include(document, self.xinclude_loader, max_depth=None)
4352 self.assertEqual(str(cm.exception),
4353 "recursive include of 'Recursive2.xml' detected")
4354
4355 document = self.xinclude_loader("Recursive1.xml").getroottree()
4356 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm:
4357 self.include(document, self.xinclude_loader, max_depth=0)
4358 self.assertEqual(str(cm.exception),
4359 "maximum xinclude depth reached when including file Recursive2.xml")
4360
4361 document = self.xinclude_loader("Recursive1.xml").getroottree()
4362 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm:
4363 self.include(document, self.xinclude_loader, max_depth=1)
4364 self.assertEqual(str(cm.exception),
4365 "maximum xinclude depth reached when including file Recursive3.xml")
4366
4367 document = self.xinclude_loader("Recursive1.xml").getroottree()
4368 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm:
4369 self.include(document, self.xinclude_loader, max_depth=2)
4370 self.assertEqual(str(cm.exception),
4371 "maximum xinclude depth reached when including file Recursive1.xml")
4372
4373 document = self.xinclude_loader("Recursive1.xml").getroottree()
4374 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm:
4375 self.include(document, self.xinclude_loader, max_depth=3)
4376 self.assertEqual(str(cm.exception),
4377 "recursive include of 'Recursive2.xml' detected")
4378
4379
4382 tree = self.parse(_bytes('<a><b/></a>'))
4383 f = BytesIO()
4384 tree.write_c14n(f)
4385 s = f.getvalue()
4386 self.assertEqual(_bytes('<a><b></b></a>'),
4387 s)
4388
4390 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4391 f = BytesIO()
4392 tree.write_c14n(f, compression=9)
4393 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile:
4394 s = gzfile.read()
4395 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4396 s)
4397
4405
4414
4423
4425 tree = self.parse(
4426 b'<?xml version="1.0"?> <a> abc \n <b> btext </b> btail <c/> ctail </a> ')
4427 f = BytesIO()
4428 tree.write(f, method='c14n2')
4429 s = f.getvalue()
4430 self.assertEqual(b'<a> abc \n <b> btext </b> btail <c></c> ctail </a>',
4431 s)
4432
4433 f = BytesIO()
4434 tree.write(f, method='c14n2', strip_text=True)
4435 s = f.getvalue()
4436 self.assertEqual(b'<a>abc<b>btext</b>btail<c></c>ctail</a>',
4437 s)
4438
4456
4474
4486
4498
4510
4512 tree = self.parse(_bytes(
4513 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4514 f = BytesIO()
4515 tree.write_c14n(f)
4516 s = f.getvalue()
4517 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4518 s)
4519 f = BytesIO()
4520 tree.write_c14n(f, exclusive=False)
4521 s = f.getvalue()
4522 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4523 s)
4524 f = BytesIO()
4525 tree.write_c14n(f, exclusive=True)
4526 s = f.getvalue()
4527 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4528 s)
4529
4530 f = BytesIO()
4531 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
4532 s = f.getvalue()
4533 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
4534 s)
4535
4537 tree = self.parse(_bytes(
4538 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4539 s = etree.tostring(tree, method='c14n')
4540 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4541 s)
4542 s = etree.tostring(tree, method='c14n', exclusive=False)
4543 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4544 s)
4545 s = etree.tostring(tree, method='c14n', exclusive=True)
4546 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4547 s)
4548
4549 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4550 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
4551 s)
4552
4554 tree = self.parse(_bytes(
4555 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4556 s = etree.tostring(tree.getroot(), method='c14n')
4557 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4558 s)
4559 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
4560 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4561 s)
4562 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
4563 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4564 s)
4565
4566 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
4567 self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4568 s)
4569 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
4570 self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
4571 s)
4572
4573 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4574 self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4575 s)
4576
4578 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
4579 tree = self.parse(_bytes(
4580 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4581
4582 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
4583 self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4584 s)
4585
4586
4589 tree = self.parse(_bytes('<a><b/></a>'))
4590 f = BytesIO()
4591 tree.write(f)
4592 s = f.getvalue()
4593 self.assertEqual(_bytes('<a><b/></a>'),
4594 s)
4595
4597 tree = self.parse(_bytes('<a><b/></a>'))
4598 f = BytesIO()
4599 tree.write(f, doctype='HUHU')
4600 s = f.getvalue()
4601 self.assertEqual(_bytes('HUHU\n<a><b/></a>'),
4602 s)
4603
4605 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4606 f = BytesIO()
4607 tree.write(f, compression=9)
4608 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile:
4609 s = gzfile.read()
4610 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4611 s)
4612
4614 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4615 f = BytesIO()
4616 tree.write(f, compression=9, doctype='<!DOCTYPE a>')
4617 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile:
4618 s = gzfile.read()
4619 self.assertEqual(_bytes('<!DOCTYPE a>\n<a>'+'<b/>'*200+'</a>'),
4620 s)
4621
4623 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4624 f = BytesIO()
4625 tree.write(f, compression=0)
4626 s0 = f.getvalue()
4627
4628 f = BytesIO()
4629 tree.write(f)
4630 self.assertEqual(f.getvalue(), s0)
4631
4632 f = BytesIO()
4633 tree.write(f, compression=1)
4634 s = f.getvalue()
4635 self.assertTrue(len(s) <= len(s0))
4636 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile:
4637 s1 = gzfile.read()
4638
4639 f = BytesIO()
4640 tree.write(f, compression=9)
4641 s = f.getvalue()
4642 self.assertTrue(len(s) <= len(s0))
4643 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile:
4644 s9 = gzfile.read()
4645
4646 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4647 s0)
4648 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4649 s1)
4650 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4651 s9)
4652
4660
4669
4677
4686
4696
4697
4699 etree = etree
4700
4722
4724 """This can't really be tested as long as there isn't a way to
4725 reset the logging setup ...
4726 """
4727 parse = self.etree.parse
4728
4729 messages = []
4730 class Logger(self.etree.PyErrorLog):
4731 def log(self, entry, message, *args):
4732 messages.append(message)
4733
4734 self.etree.use_global_python_log(Logger())
4735 f = BytesIO('<a><b></c></b></a>')
4736 try:
4737 parse(f)
4738 except SyntaxError:
4739 pass
4740 f.close()
4741
4742 self.assertTrue([ message for message in messages
4743 if 'mismatch' in message ])
4744 self.assertTrue([ message for message in messages
4745 if ':PARSER:' in message])
4746 self.assertTrue([ message for message in messages
4747 if ':ERR_TAG_NAME_MISMATCH:' in message ])
4748 self.assertTrue([ message for message in messages
4749 if ':1:15:' in message ])
4750
4751
4753 etree = etree
4754
4758
4760 class Target(object):
4761 def start(self, tag, attrib):
4762 return 'start(%s)' % tag
4763 def end(self, tag):
4764 return 'end(%s)' % tag
4765 def close(self):
4766 return 'close()'
4767
4768 parser = self.etree.XMLPullParser(target=Target())
4769 events = parser.read_events()
4770
4771 parser.feed('<root><element>')
4772 self.assertFalse(list(events))
4773 self.assertFalse(list(events))
4774 parser.feed('</element><child>')
4775 self.assertEqual([('end', 'end(element)')], list(events))
4776 parser.feed('</child>')
4777 self.assertEqual([('end', 'end(child)')], list(events))
4778 parser.feed('</root>')
4779 self.assertEqual([('end', 'end(root)')], list(events))
4780 self.assertFalse(list(events))
4781 self.assertEqual('close()', parser.close())
4782
4784 class Target(object):
4785 def start(self, tag, attrib):
4786 return 'start(%s)' % tag
4787 def end(self, tag):
4788 return 'end(%s)' % tag
4789 def close(self):
4790 return 'close()'
4791
4792 parser = self.etree.XMLPullParser(
4793 ['start', 'end'], target=Target())
4794 events = parser.read_events()
4795
4796 parser.feed('<root><element>')
4797 self.assertEqual(
4798 [('start', 'start(root)'), ('start', 'start(element)')],
4799 list(events))
4800 self.assertFalse(list(events))
4801 parser.feed('</element><child>')
4802 self.assertEqual(
4803 [('end', 'end(element)'), ('start', 'start(child)')],
4804 list(events))
4805 parser.feed('</child>')
4806 self.assertEqual(
4807 [('end', 'end(child)')],
4808 list(events))
4809 parser.feed('</root>')
4810 self.assertEqual(
4811 [('end', 'end(root)')],
4812 list(events))
4813 self.assertFalse(list(events))
4814 self.assertEqual('close()', parser.close())
4815
4817 parser = self.etree.XMLPullParser(
4818 ['start', 'end'], target=etree.TreeBuilder())
4819 events = parser.read_events()
4820
4821 parser.feed('<root><element>')
4822 self.assert_event_tags(
4823 events, [('start', 'root'), ('start', 'element')])
4824 self.assertFalse(list(events))
4825 parser.feed('</element><child>')
4826 self.assert_event_tags(
4827 events, [('end', 'element'), ('start', 'child')])
4828 parser.feed('</child>')
4829 self.assert_event_tags(
4830 events, [('end', 'child')])
4831 parser.feed('</root>')
4832 self.assert_event_tags(
4833 events, [('end', 'root')])
4834 self.assertFalse(list(events))
4835 root = parser.close()
4836 self.assertEqual('root', root.tag)
4837
4839 class Target(etree.TreeBuilder):
4840 def end(self, tag):
4841 el = super(Target, self).end(tag)
4842 el.tag += '-huhu'
4843 return el
4844
4845 parser = self.etree.XMLPullParser(
4846 ['start', 'end'], target=Target())
4847 events = parser.read_events()
4848
4849 parser.feed('<root><element>')
4850 self.assert_event_tags(
4851 events, [('start', 'root'), ('start', 'element')])
4852 self.assertFalse(list(events))
4853 parser.feed('</element><child>')
4854 self.assert_event_tags(
4855 events, [('end', 'element-huhu'), ('start', 'child')])
4856 parser.feed('</child>')
4857 self.assert_event_tags(
4858 events, [('end', 'child-huhu')])
4859 parser.feed('</root>')
4860 self.assert_event_tags(
4861 events, [('end', 'root-huhu')])
4862 self.assertFalse(list(events))
4863 root = parser.close()
4864 self.assertEqual('root-huhu', root.tag)
4865
4866
4895
4896
4897 if __name__ == '__main__':
4898 print('to test use test.py %s' % __file__)
4899