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 from collections import OrderedDict
13 import os.path
14 import unittest
15 import copy
16 import sys
17 import re
18 import gc
19 import operator
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(12, 4, -1)]
290 values = ["TEST-%d" % i for i in range(12, 4, -1)]
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 attr_order = [
300 ('attr_99', 'TOAST-1'),
301 ('attr_98', 'TOAST-2'),
302 ]
303 ordered_dict_types = [OrderedDict, lambda x:x]
304 if sys.version_info >= (3, 6):
305 ordered_dict_types.append(dict)
306 else:
307
308 attr_order.sort()
309 attr_order += items
310 expected_keys = [attr[0] for attr in attr_order]
311 expected_values = [attr[1] for attr in attr_order]
312 expected_items = list(zip(expected_keys, expected_values))
313
314 for dict_type in ordered_dict_types:
315 root2 = Element("root2", dict_type(root.attrib),
316 attr_99='TOAST-1', attr_98='TOAST-2')
317
318 try:
319 self.assertSequenceEqual(expected_keys, root2.attrib.keys())
320 self.assertSequenceEqual(expected_values, root2.attrib.values())
321 self.assertSequenceEqual(expected_items, root2.attrib.items())
322 except AssertionError as exc:
323 exc.args = ("Order of '%s': %s" % (dict_type.__name__, exc.args[0]),) + exc.args[1:]
324 raise
325
326 self.assertEqual(keys, root.attrib.keys())
327 self.assertEqual(values, root.attrib.values())
328
330
331
332 Element = self.etree.Element
333 root = Element("root")
334 self.assertRaises(TypeError, root.set, "newattr", 5)
335 self.assertRaises(TypeError, root.set, "newattr", object)
336 self.assertRaises(TypeError, root.set, "newattr", None)
337 self.assertRaises(TypeError, root.set, "newattr")
338
352
374
376 XML = self.etree.XML
377 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
378
379 root = XML(xml)
380 self.etree.strip_elements(root, 'a')
381 self.assertEqual(_bytes('<test><x></x></test>'),
382 self._writeElement(root))
383
384 root = XML(xml)
385 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
386 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'),
387 self._writeElement(root))
388
389 root = XML(xml)
390 self.etree.strip_elements(root, 'c')
391 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
392 self._writeElement(root))
393
395 XML = self.etree.XML
396 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>')
397
398 root = XML(xml)
399 self.etree.strip_elements(root, 'a')
400 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>'),
401 self._writeElement(root))
402
403 root = XML(xml)
404 self.etree.strip_elements(root, '{urn:a}b', 'c')
405 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>'),
406 self._writeElement(root))
407
408 root = XML(xml)
409 self.etree.strip_elements(root, '{urn:a}*', 'c')
410 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
411 self._writeElement(root))
412
413 root = XML(xml)
414 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
415 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
416 self._writeElement(root))
417
436
462
489
516
535
548
559
565
567 XML = self.etree.XML
568 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
569 self.assertEqual(root[0].target, "mypi")
570 self.assertEqual(root[0].get('my'), "1")
571 self.assertEqual(root[0].get('test'), " abc ")
572 self.assertEqual(root[0].get('quotes'), "' '")
573 self.assertEqual(root[0].get('only'), None)
574 self.assertEqual(root[0].get('names'), None)
575 self.assertEqual(root[0].get('nope'), None)
576
578 XML = self.etree.XML
579 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
580 self.assertEqual(root[0].target, "mypi")
581 self.assertEqual(root[0].attrib['my'], "1")
582 self.assertEqual(root[0].attrib['test'], " abc ")
583 self.assertEqual(root[0].attrib['quotes'], "' '")
584 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
585 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
586 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
587
589
590 ProcessingInstruction = self.etree.ProcessingInstruction
591
592 a = ProcessingInstruction("PI", "ONE")
593 b = copy.deepcopy(a)
594 b.text = "ANOTHER"
595
596 self.assertEqual('ONE', a.text)
597 self.assertEqual('ANOTHER', b.text)
598
614
629
640
652
671
676
689
700
701 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
702 events = list(iterparse(f, events=('end', 'comment')))
703 root = events[-1][1]
704 self.assertEqual(6, len(events))
705 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'],
706 [ name(*item) for item in events ])
707 self.assertEqual(
708 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
709 tostring(root))
710
722
723 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
724 events = list(iterparse(f, events=('end', 'pi')))
725 root = events[-2][1]
726 self.assertEqual(8, len(events))
727 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
728 ('pid','d'), 'a', ('pie','e')],
729 [ name(*item) for item in events ])
730 self.assertEqual(
731 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
732 tostring(ElementTree(root)))
733
748
754
756 iterparse = self.etree.iterparse
757 f = BytesIO('<a><b><c/></a>')
758 it = iterparse(f, events=('start', 'end'), recover=True)
759 events = [(ev, el.tag) for ev, el in it]
760 root = it.root
761 self.assertTrue(root is not None)
762
763 self.assertEqual(1, events.count(('start', 'a')))
764 self.assertEqual(1, events.count(('end', 'a')))
765
766 self.assertEqual(1, events.count(('start', 'b')))
767 self.assertEqual(1, events.count(('end', 'b')))
768
769 self.assertEqual(1, events.count(('start', 'c')))
770 self.assertEqual(1, events.count(('end', 'c')))
771
773 iterparse = self.etree.iterparse
774 f = BytesIO('<a><b><c/></d><b><c/></a></b>')
775 it = iterparse(f, events=('start', 'end'), recover=True)
776 events = [(ev, el.tag) for ev, el in it]
777 root = it.root
778 self.assertTrue(root is not None)
779
780 self.assertEqual(1, events.count(('start', 'a')))
781 self.assertEqual(1, events.count(('end', 'a')))
782
783 self.assertEqual(2, events.count(('start', 'b')))
784 self.assertEqual(2, events.count(('end', 'b')))
785
786 self.assertEqual(2, events.count(('start', 'c')))
787 self.assertEqual(2, events.count(('end', 'c')))
788
790 iterparse = self.etree.iterparse
791 f = BytesIO("""
792 <a> \n \n <b> b test </b> \n
793
794 \n\t <c> \n </c> </a> \n """)
795 iterator = iterparse(f, remove_blank_text=True)
796 text = [ (element.text, element.tail)
797 for event, element in iterator ]
798 self.assertEqual(
799 [(" b test ", None), (" \n ", None), (None, None)],
800 text)
801
803 iterparse = self.etree.iterparse
804 f = BytesIO('<a><b><d/></b><c/></a>')
805
806 iterator = iterparse(f, tag="b", events=('start', 'end'))
807 events = list(iterator)
808 root = iterator.root
809 self.assertEqual(
810 [('start', root[0]), ('end', root[0])],
811 events)
812
814 iterparse = self.etree.iterparse
815 f = BytesIO('<a><b><d/></b><c/></a>')
816
817 iterator = iterparse(f, tag="*", events=('start', 'end'))
818 events = list(iterator)
819 self.assertEqual(
820 8,
821 len(events))
822
824 iterparse = self.etree.iterparse
825 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
826
827 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
828 events = list(iterator)
829 root = iterator.root
830 self.assertEqual(
831 [('start', root[0]), ('end', root[0])],
832 events)
833
835 iterparse = self.etree.iterparse
836 f = BytesIO('<a><b><d/></b><c/></a>')
837 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
838 events = list(iterator)
839 root = iterator.root
840 self.assertEqual(
841 [('start', root[0]), ('end', root[0])],
842 events)
843
844 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
845 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
846 events = list(iterator)
847 root = iterator.root
848 self.assertEqual([], events)
849
851 iterparse = self.etree.iterparse
852 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
853 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
854 events = list(iterator)
855 self.assertEqual(8, len(events))
856
858 iterparse = self.etree.iterparse
859 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
860 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
861 events = list(iterator)
862 self.assertEqual([], events)
863
864 f = BytesIO('<a><b><d/></b><c/></a>')
865 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
866 events = list(iterator)
867 self.assertEqual(8, len(events))
868
870 text = _str('Søk på nettet')
871 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
872 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
873 ).encode('iso-8859-1')
874
875 self.assertRaises(self.etree.ParseError,
876 list, self.etree.iterparse(BytesIO(xml_latin1)))
877
879 text = _str('Søk på nettet', encoding="UTF-8")
880 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
881 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
882 ).encode('iso-8859-1')
883
884 iterator = self.etree.iterparse(BytesIO(xml_latin1),
885 encoding="iso-8859-1")
886 self.assertEqual(1, len(list(iterator)))
887
888 a = iterator.root
889 self.assertEqual(a.text, text)
890
892 tostring = self.etree.tostring
893 f = BytesIO('<root><![CDATA[test]]></root>')
894 context = self.etree.iterparse(f, strip_cdata=False)
895 content = [ el.text for event,el in context ]
896
897 self.assertEqual(['test'], content)
898 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
899 tostring(context.root))
900
904
909
928
929
930
953
954
955
957 assertEqual = self.assertEqual
958 assertFalse = self.assertFalse
959
960 events = []
961 class Target(object):
962 def start(self, tag, attrib):
963 events.append("start")
964 assertFalse(attrib)
965 assertEqual("TAG", tag)
966 def end(self, tag):
967 events.append("end")
968 assertEqual("TAG", tag)
969 def close(self):
970 return "DONE"
971
972 parser = self.etree.XMLParser(target=Target())
973 tree = self.etree.ElementTree()
974
975 self.assertRaises(TypeError,
976 tree.parse, BytesIO("<TAG/>"), parser=parser)
977 self.assertEqual(["start", "end"], events)
978
980
981 events = []
982 class Target(object):
983 def start(self, tag, attrib):
984 events.append("start-" + tag)
985 def end(self, tag):
986 events.append("end-" + tag)
987 if tag == 'a':
988 raise ValueError("dead and gone")
989 def data(self, data):
990 events.append("data-" + data)
991 def close(self):
992 events.append("close")
993 return "DONE"
994
995 parser = self.etree.XMLParser(target=Target())
996
997 try:
998 parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
999 done = parser.close()
1000 self.fail("error expected, but parsing succeeded")
1001 except ValueError:
1002 done = 'value error received as expected'
1003
1004 self.assertEqual(["start-root", "data-A", "start-a",
1005 "data-ca", "end-a", "close"],
1006 events)
1007
1009
1010 events = []
1011 class Target(object):
1012 def start(self, tag, attrib):
1013 events.append("start-" + tag)
1014 def end(self, tag):
1015 events.append("end-" + tag)
1016 if tag == 'a':
1017 raise ValueError("dead and gone")
1018 def data(self, data):
1019 events.append("data-" + data)
1020 def close(self):
1021 events.append("close")
1022 return "DONE"
1023
1024 parser = self.etree.XMLParser(target=Target())
1025
1026 try:
1027 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
1028 parser=parser)
1029 self.fail("error expected, but parsing succeeded")
1030 except ValueError:
1031 done = 'value error received as expected'
1032
1033 self.assertEqual(["start-root", "data-A", "start-a",
1034 "data-ca", "end-a", "close"],
1035 events)
1036
1038
1039 events = []
1040 class Target(object):
1041 def start(self, tag, attrib):
1042 events.append("start-" + tag)
1043 def end(self, tag):
1044 events.append("end-" + tag)
1045 def data(self, data):
1046 events.append("data-" + data)
1047 def comment(self, text):
1048 events.append("comment-" + text)
1049 def close(self):
1050 return "DONE"
1051
1052 parser = self.etree.XMLParser(target=Target(), collect_ids=False)
1053
1054 parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->'))
1055 parser.feed(_bytes('<sub xml:id="321"/>B</root>'))
1056 done = parser.close()
1057
1058 self.assertEqual("DONE", done)
1059 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1060 "start-sub", "end-sub", "data-B", "end-root"],
1061 events)
1062
1068 def end(self, tag):
1069 events.append("end-" + tag)
1070 def data(self, data):
1071 events.append("data-" + data)
1072 def comment(self, text):
1073 events.append("comment-" + text)
1074 def close(self):
1075 return "DONE"
1076
1077 parser = self.etree.XMLParser(target=Target())
1078
1079 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
1080 done = parser.close()
1081
1082 self.assertEqual("DONE", done)
1083 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1084 "start-sub", "end-sub", "comment-c", "data-B",
1085 "end-root", "comment-d"],
1086 events)
1087
1089 events = []
1090 class Target(object):
1091 def start(self, tag, attrib):
1092 events.append("start-" + tag)
1093 def end(self, tag):
1094 events.append("end-" + tag)
1095 def data(self, data):
1096 events.append("data-" + data)
1097 def pi(self, target, data):
1098 events.append("pi-" + target + "-" + data)
1099 def close(self):
1100 return "DONE"
1101
1102 parser = self.etree.XMLParser(target=Target())
1103
1104 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
1105 done = parser.close()
1106
1107 self.assertEqual("DONE", done)
1108 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b",
1109 "data-B", "end-root", "pi-test-c"],
1110 events)
1111
1113 events = []
1114 class Target(object):
1115 def start(self, tag, attrib):
1116 events.append("start-" + tag)
1117 def end(self, tag):
1118 events.append("end-" + tag)
1119 def data(self, data):
1120 events.append("data-" + data)
1121 def close(self):
1122 return "DONE"
1123
1124 parser = self.etree.XMLParser(target=Target(),
1125 strip_cdata=False)
1126
1127 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
1128 done = parser.close()
1129
1130 self.assertEqual("DONE", done)
1131 self.assertEqual(["start-root", "data-A", "start-a",
1132 "data-ca", "end-a", "data-B", "end-root"],
1133 events)
1134
1136 events = []
1137 class Target(object):
1138 def start(self, tag, attrib):
1139 events.append("start-" + tag)
1140 def end(self, tag):
1141 events.append("end-" + tag)
1142 def data(self, data):
1143 events.append("data-" + data)
1144 def close(self):
1145 events.append("close")
1146 return "DONE"
1147
1148 parser = self.etree.XMLParser(target=Target(),
1149 recover=True)
1150
1151 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
1152 done = parser.close()
1153
1154 self.assertEqual("DONE", done)
1155 self.assertEqual(["start-root", "data-A", "start-a",
1156 "data-ca", "end-a", "data-B",
1157 "end-root", "close"],
1158 events)
1159
1169
1179
1188
1203
1219
1221 iterwalk = self.etree.iterwalk
1222 root = self.etree.XML(
1223 b'<?C0?><a><?Ca?><b><?Cb?></b><?Cc?><c/></a><?C99?>')
1224
1225 iterator = iterwalk(root, events=('start', 'end', 'pi'))
1226 events = list(iterator)
1227 self.assertEqual(
1228 [('start', root), ('pi', root[0]),
1229 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]),
1230 ('pi', root[2]), ('start', root[3]), ('end', root[3]),
1231 ('end', root),
1232 ],
1233 events)
1234
1236 iterwalk = self.etree.iterwalk
1237 root = self.etree.XML(
1238 b'<?C0?><a><?Ca?><b><?Cb?></b><?Cc?><c/></a><?C99?>')
1239
1240 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'pi'))
1241 events = list(iterator)
1242 self.assertEqual(
1243 [('pi', root.getprevious()),
1244 ('start', root), ('pi', root[0]),
1245 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]),
1246 ('pi', root[2]), ('start', root[3]), ('end', root[3]),
1247 ('end', root), ('pi', root.getnext()),
1248 ],
1249 events)
1250
1268
1283
1293
1295 iterwalk = self.etree.iterwalk
1296 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1297
1298 iterator = iterwalk(root, events=('start','end'))
1299 events = list(iterator)
1300 self.assertEqual(
1301 [('start', root), ('start', root[0]), ('end', root[0]),
1302 ('start', root[1]), ('end', root[1]), ('end', root)],
1303 events)
1304
1314
1324
1338
1349
1351 iterwalk = self.etree.iterwalk
1352 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
1353
1354 attr_name = '{testns}bla'
1355 events = []
1356 iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
1357 for event, elem in iterator:
1358 events.append(event)
1359 if event == 'start':
1360 if elem.tag != '{ns1}a':
1361 elem.set(attr_name, 'value')
1362
1363 self.assertEqual(
1364 ['start-ns', 'start', 'start', 'start-ns', 'start',
1365 'end', 'end-ns', 'end', 'end', 'end-ns'],
1366 events)
1367
1368 self.assertEqual(
1369 None,
1370 root.get(attr_name))
1371 self.assertEqual(
1372 'value',
1373 root[0].get(attr_name))
1374
1387
1389 iterwalk = self.etree.iterwalk
1390 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>'))
1391
1392 iterator = iterwalk(root, events=('start', 'end'))
1393 tags = []
1394 for event, elem in iterator:
1395 tags.append((event, elem.tag))
1396 if elem.tag in ('b', 'e'):
1397
1398 iterator.skip_subtree()
1399
1400 self.assertEqual(
1401 [('start', 'a'),
1402 ('start', 'b'), ('end', 'b'),
1403 ('start', 'd'),
1404 ('start', 'e'), ('end', 'e'),
1405 ('end', 'd'),
1406 ('end', 'a')],
1407 tags)
1408
1410 iterwalk = self.etree.iterwalk
1411 root = self.etree.XML(_bytes(
1412 '<a xmlns="ns1"><b xmlns="nsb"><c xmlns="ns2"/></b><d xmlns="ns2"><e/></d></a>'))
1413
1414 events = []
1415 iterator = iterwalk(root, events=('start','start-ns','end-ns'))
1416 for event, elem in iterator:
1417 if event in ('start-ns', 'end-ns'):
1418 events.append((event, elem))
1419 if event == 'start-ns' and elem == ('', 'nsb'):
1420 events.append('skip')
1421 iterator.skip_subtree()
1422 else:
1423 events.append((event, elem.tag))
1424
1425 self.assertEqual(
1426 [('start-ns', ('', 'ns1')),
1427 ('start', '{ns1}a'),
1428 ('start-ns', ('', 'nsb')),
1429 'skip',
1430 ('start', '{nsb}b'),
1431 ('end-ns', None),
1432 ('start-ns', ('', 'ns2')),
1433 ('start', '{ns2}d'),
1434 ('start', '{ns2}e'),
1435 ('end-ns', None),
1436 ('end-ns', None)
1437 ],
1438 events)
1439
1450
1452 parse = self.etree.parse
1453 parser = self.etree.XMLParser(dtd_validation=True)
1454 assertEqual = self.assertEqual
1455 test_url = _str("__nosuch.dtd")
1456
1457 class MyResolver(self.etree.Resolver):
1458 def resolve(self, url, id, context):
1459 assertEqual(url, test_url)
1460 return self.resolve_string(
1461 _str('''<!ENTITY myentity "%s">
1462 <!ELEMENT doc ANY>''') % url, context)
1463
1464 parser.resolvers.add(MyResolver())
1465
1466 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1467 tree = parse(StringIO(xml), parser)
1468 root = tree.getroot()
1469 self.assertEqual(root.text, test_url)
1470
1472 parse = self.etree.parse
1473 parser = self.etree.XMLParser(dtd_validation=True)
1474 assertEqual = self.assertEqual
1475 test_url = _str("__nosuch.dtd")
1476
1477 class MyResolver(self.etree.Resolver):
1478 def resolve(self, url, id, context):
1479 assertEqual(url, test_url)
1480 return self.resolve_string(
1481 (_str('''<!ENTITY myentity "%s">
1482 <!ELEMENT doc ANY>''') % url).encode('utf-8'),
1483 context)
1484
1485 parser.resolvers.add(MyResolver())
1486
1487 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1488 tree = parse(StringIO(xml), parser)
1489 root = tree.getroot()
1490 self.assertEqual(root.text, test_url)
1491
1493 parse = self.etree.parse
1494 parser = self.etree.XMLParser(dtd_validation=True)
1495 assertEqual = self.assertEqual
1496 test_url = _str("__nosuch.dtd")
1497
1498 class MyResolver(self.etree.Resolver):
1499 def resolve(self, url, id, context):
1500 assertEqual(url, test_url)
1501 return self.resolve_file(
1502 SillyFileLike(
1503 _str('''<!ENTITY myentity "%s">
1504 <!ELEMENT doc ANY>''') % url), context)
1505
1506 parser.resolvers.add(MyResolver())
1507
1508 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1509 tree = parse(StringIO(xml), parser)
1510 root = tree.getroot()
1511 self.assertEqual(root.text, test_url)
1512
1514 parse = self.etree.parse
1515 parser = self.etree.XMLParser(attribute_defaults=True)
1516 assertEqual = self.assertEqual
1517 test_url = _str("__nosuch.dtd")
1518
1519 class MyResolver(self.etree.Resolver):
1520 def resolve(self, url, id, context):
1521 assertEqual(url, test_url)
1522 return self.resolve_filename(
1523 fileInTestDir('test.dtd'), context)
1524
1525 parser.resolvers.add(MyResolver())
1526
1527 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1528 tree = parse(StringIO(xml), parser)
1529 root = tree.getroot()
1530 self.assertEqual(
1531 root.attrib, {'default': 'valueA'})
1532 self.assertEqual(
1533 root[0].attrib, {'default': 'valueB'})
1534
1549
1550 parser.resolvers.add(MyResolver())
1551
1552 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1553 tree = parse(StringIO(xml), parser,
1554 base_url=fileUrlInTestDir('__test.xml'))
1555 root = tree.getroot()
1556 self.assertEqual(
1557 root.attrib, {'default': 'valueA'})
1558 self.assertEqual(
1559 root[0].attrib, {'default': 'valueB'})
1560
1562 parse = self.etree.parse
1563 parser = self.etree.XMLParser(attribute_defaults=True)
1564 assertEqual = self.assertEqual
1565 test_url = _str("__nosuch.dtd")
1566
1567 class MyResolver(self.etree.Resolver):
1568 def resolve(self, url, id, context):
1569 assertEqual(url, test_url)
1570 return self.resolve_file(
1571 open(fileInTestDir('test.dtd'), 'rb'), context)
1572
1573 parser.resolvers.add(MyResolver())
1574
1575 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1576 tree = parse(StringIO(xml), parser)
1577 root = tree.getroot()
1578 self.assertEqual(
1579 root.attrib, {'default': 'valueA'})
1580 self.assertEqual(
1581 root[0].attrib, {'default': 'valueB'})
1582
1584 parse = self.etree.parse
1585 parser = self.etree.XMLParser(load_dtd=True)
1586 assertEqual = self.assertEqual
1587 test_url = _str("__nosuch.dtd")
1588
1589 class check(object):
1590 resolved = False
1591
1592 class MyResolver(self.etree.Resolver):
1593 def resolve(self, url, id, context):
1594 assertEqual(url, test_url)
1595 check.resolved = True
1596 return self.resolve_empty(context)
1597
1598 parser.resolvers.add(MyResolver())
1599
1600 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1601 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
1602 self.assertTrue(check.resolved)
1603
1610
1611 class MyResolver(self.etree.Resolver):
1612 def resolve(self, url, id, context):
1613 raise _LocalException
1614
1615 parser.resolvers.add(MyResolver())
1616
1617 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
1618 self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
1619
1636
1638 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]>
1639 <root>
1640 <child1/>
1641 <child2/>
1642 <child3> </child3>
1643 </root>''')
1644
1645 parser = self.etree.XMLParser(resolve_entities=False)
1646 root = etree.fromstring(xml, parser)
1647 self.assertEqual([ el.tag for el in root ],
1648 ['child1', 'child2', 'child3'])
1649
1650 root[0] = root[-1]
1651 self.assertEqual([ el.tag for el in root ],
1652 ['child3', 'child2'])
1653 self.assertEqual(root[0][0].text, ' ')
1654 self.assertEqual(root[0][0].name, 'nbsp')
1655
1671
1689
1696
1698 Entity = self.etree.Entity
1699 self.assertRaises(ValueError, Entity, 'a b c')
1700 self.assertRaises(ValueError, Entity, 'a,b')
1701 self.assertRaises(ValueError, Entity, 'a\0b')
1702 self.assertRaises(ValueError, Entity, '#abc')
1703 self.assertRaises(ValueError, Entity, '#xxyz')
1704
1717
1738
1751
1763
1772
1781
1782
1792
1801
1803 Element = self.etree.Element
1804 SubElement = self.etree.SubElement
1805 root = Element('root')
1806 self.assertRaises(ValueError, root.append, root)
1807 child = SubElement(root, 'child')
1808 self.assertRaises(ValueError, child.append, root)
1809 child2 = SubElement(child, 'child2')
1810 self.assertRaises(ValueError, child2.append, root)
1811 self.assertRaises(ValueError, child2.append, child)
1812 self.assertEqual('child2', root[0][0].tag)
1813
1826
1839
1850
1861
1871
1881
1897
1913
1919
1934
1947
1962
1975
1990
2003
2018
2031
2032
2040
2041
2051
2052
2067
2068
2078
2079
2090
2117
2118
2120 self.assertRaises(TypeError, self.etree.dump, None)
2121
2134
2147
2168
2177
2179 XML = self.etree.XML
2180
2181 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
2182 result = []
2183 for el in root.iterchildren(reversed=True):
2184 result.append(el.tag)
2185 self.assertEqual(['three', 'two', 'one'], result)
2186
2195
2204
2213
2215 XML = self.etree.XML
2216
2217 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2218 result = []
2219 for el in root.iterchildren(tag=['two', 'three']):
2220 result.append(el.text)
2221 self.assertEqual(['Two', 'Bla', None], result)
2222
2224 XML = self.etree.XML
2225
2226 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2227 result = []
2228 for el in root.iterchildren('two', 'three'):
2229 result.append(el.text)
2230 self.assertEqual(['Two', 'Bla', None], result)
2231
2233 XML = self.etree.XML
2234
2235 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2236 result = []
2237 for el in root.iterchildren(reversed=True, tag=['two', 'three']):
2238 result.append(el.text)
2239 self.assertEqual([None, 'Bla', 'Two'], result)
2240
2261
2283
2285 Element = self.etree.Element
2286 SubElement = self.etree.SubElement
2287
2288 a = Element('a')
2289 b = SubElement(a, 'b')
2290 c = SubElement(a, 'c')
2291 d = SubElement(b, 'd')
2292 self.assertEqual(
2293 [b, a],
2294 list(d.iterancestors(tag=('a', 'b'))))
2295 self.assertEqual(
2296 [b, a],
2297 list(d.iterancestors('a', 'b')))
2298
2299 self.assertEqual(
2300 [],
2301 list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
2302 self.assertEqual(
2303 [],
2304 list(d.iterancestors('w', 'x', 'y', 'z')))
2305
2306 self.assertEqual(
2307 [],
2308 list(d.iterancestors(tag=('d', 'x'))))
2309 self.assertEqual(
2310 [],
2311 list(d.iterancestors('d', 'x')))
2312
2313 self.assertEqual(
2314 [b, a],
2315 list(d.iterancestors(tag=('b', '*'))))
2316 self.assertEqual(
2317 [b, a],
2318 list(d.iterancestors('b', '*')))
2319
2320 self.assertEqual(
2321 [b],
2322 list(d.iterancestors(tag=('b', 'c'))))
2323 self.assertEqual(
2324 [b],
2325 list(d.iterancestors('b', 'c')))
2326
2343
2345 Element = self.etree.Element
2346 SubElement = self.etree.SubElement
2347
2348 a = Element('a')
2349 b = SubElement(a, 'b')
2350 c = SubElement(a, 'c')
2351 d = SubElement(b, 'd')
2352 e = SubElement(c, 'e')
2353
2354 self.assertEqual(
2355 [],
2356 list(a.iterdescendants('a')))
2357 self.assertEqual(
2358 [],
2359 list(a.iterdescendants(tag='a')))
2360
2361 a2 = SubElement(e, 'a')
2362 self.assertEqual(
2363 [a2],
2364 list(a.iterdescendants('a')))
2365
2366 self.assertEqual(
2367 [a2],
2368 list(c.iterdescendants('a')))
2369 self.assertEqual(
2370 [a2],
2371 list(c.iterdescendants(tag='a')))
2372
2374 Element = self.etree.Element
2375 SubElement = self.etree.SubElement
2376
2377 a = Element('a')
2378 b = SubElement(a, 'b')
2379 c = SubElement(a, 'c')
2380 d = SubElement(b, 'd')
2381 e = SubElement(c, 'e')
2382
2383 self.assertEqual(
2384 [b, e],
2385 list(a.iterdescendants(tag=('a', 'b', 'e'))))
2386 self.assertEqual(
2387 [b, e],
2388 list(a.iterdescendants('a', 'b', 'e')))
2389
2390 a2 = SubElement(e, 'a')
2391 self.assertEqual(
2392 [b, a2],
2393 list(a.iterdescendants(tag=('a', 'b'))))
2394 self.assertEqual(
2395 [b, a2],
2396 list(a.iterdescendants('a', 'b')))
2397
2398 self.assertEqual(
2399 [],
2400 list(c.iterdescendants(tag=('x', 'y', 'z'))))
2401 self.assertEqual(
2402 [],
2403 list(c.iterdescendants('x', 'y', 'z')))
2404
2405 self.assertEqual(
2406 [b, d, c, e, a2],
2407 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
2408 self.assertEqual(
2409 [b, d, c, e, a2],
2410 list(a.iterdescendants('x', 'y', 'z', '*')))
2411
2429
2446
2464
2488
2490 Element = self.etree.Element
2491 SubElement = self.etree.SubElement
2492
2493 a = Element('a')
2494 b = SubElement(a, 'b')
2495 c = SubElement(a, 'c')
2496 d = SubElement(b, 'd')
2497 self.assertEqual(
2498 [],
2499 list(a.itersiblings(tag='XXX')))
2500 self.assertEqual(
2501 [c],
2502 list(b.itersiblings(tag='c')))
2503 self.assertEqual(
2504 [c],
2505 list(b.itersiblings(tag='*')))
2506 self.assertEqual(
2507 [b],
2508 list(c.itersiblings(preceding=True, tag='b')))
2509 self.assertEqual(
2510 [],
2511 list(c.itersiblings(preceding=True, tag='c')))
2512
2514 Element = self.etree.Element
2515 SubElement = self.etree.SubElement
2516
2517 a = Element('a')
2518 b = SubElement(a, 'b')
2519 c = SubElement(a, 'c')
2520 d = SubElement(b, 'd')
2521 e = SubElement(a, 'e')
2522 self.assertEqual(
2523 [],
2524 list(a.itersiblings(tag=('XXX', 'YYY'))))
2525 self.assertEqual(
2526 [c, e],
2527 list(b.itersiblings(tag=('c', 'd', 'e'))))
2528 self.assertEqual(
2529 [b],
2530 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
2531 self.assertEqual(
2532 [c, b],
2533 list(e.itersiblings(preceding=True, tag=('c', '*'))))
2534
2536 parseid = self.etree.parseid
2537 XML = self.etree.XML
2538 xml_text = _bytes('''
2539 <!DOCTYPE document [
2540 <!ELEMENT document (h1,p)*>
2541 <!ELEMENT h1 (#PCDATA)>
2542 <!ATTLIST h1 myid ID #REQUIRED>
2543 <!ELEMENT p (#PCDATA)>
2544 <!ATTLIST p someid ID #REQUIRED>
2545 ]>
2546 <document>
2547 <h1 myid="chapter1">...</h1>
2548 <p id="note1" class="note">...</p>
2549 <p>Regular paragraph.</p>
2550 <p xml:id="xmlid">XML:ID paragraph.</p>
2551 <p someid="warn1" class="warning">...</p>
2552 </document>
2553 ''')
2554
2555 tree, dic = parseid(BytesIO(xml_text))
2556 root = tree.getroot()
2557 root2 = XML(xml_text)
2558 self.assertEqual(self._writeElement(root),
2559 self._writeElement(root2))
2560 expected = {
2561 "chapter1" : root[0],
2562 "xmlid" : root[3],
2563 "warn1" : root[4]
2564 }
2565 self.assertTrue("chapter1" in dic)
2566 self.assertTrue("warn1" in dic)
2567 self.assertTrue("xmlid" in dic)
2568 self._checkIDDict(dic, expected)
2569
2571 XMLDTDID = self.etree.XMLDTDID
2572 XML = self.etree.XML
2573 xml_text = _bytes('''
2574 <!DOCTYPE document [
2575 <!ELEMENT document (h1,p)*>
2576 <!ELEMENT h1 (#PCDATA)>
2577 <!ATTLIST h1 myid ID #REQUIRED>
2578 <!ELEMENT p (#PCDATA)>
2579 <!ATTLIST p someid ID #REQUIRED>
2580 ]>
2581 <document>
2582 <h1 myid="chapter1">...</h1>
2583 <p id="note1" class="note">...</p>
2584 <p>Regular paragraph.</p>
2585 <p xml:id="xmlid">XML:ID paragraph.</p>
2586 <p someid="warn1" class="warning">...</p>
2587 </document>
2588 ''')
2589
2590 root, dic = XMLDTDID(xml_text)
2591 root2 = XML(xml_text)
2592 self.assertEqual(self._writeElement(root),
2593 self._writeElement(root2))
2594 expected = {
2595 "chapter1" : root[0],
2596 "xmlid" : root[3],
2597 "warn1" : root[4]
2598 }
2599 self.assertTrue("chapter1" in dic)
2600 self.assertTrue("warn1" in dic)
2601 self.assertTrue("xmlid" in dic)
2602 self._checkIDDict(dic, expected)
2603
2605 XMLDTDID = self.etree.XMLDTDID
2606 XML = self.etree.XML
2607 xml_text = _bytes('''
2608 <document>
2609 <h1 myid="chapter1">...</h1>
2610 <p id="note1" class="note">...</p>
2611 <p>Regular paragraph.</p>
2612 <p someid="warn1" class="warning">...</p>
2613 </document>
2614 ''')
2615
2616 root, dic = XMLDTDID(xml_text)
2617 root2 = XML(xml_text)
2618 self.assertEqual(self._writeElement(root),
2619 self._writeElement(root2))
2620 expected = {}
2621 self._checkIDDict(dic, expected)
2622
2624 XMLDTDID = self.etree.XMLDTDID
2625 XML = self.etree.XML
2626 xml_text = _bytes('''
2627 <!DOCTYPE document [
2628 <!ELEMENT document (h1,p)*>
2629 <!ELEMENT h1 (#PCDATA)>
2630 <!ATTLIST h1 myid ID #REQUIRED>
2631 <!ELEMENT p (#PCDATA)>
2632 <!ATTLIST p someid ID #REQUIRED>
2633 ]>
2634 <document>
2635 <h1 myid="chapter1">...</h1>
2636 <p id="note1" class="note">...</p>
2637 <p>Regular paragraph.</p>
2638 <p xml:id="xmlid">XML:ID paragraph.</p>
2639 <p someid="warn1" class="warning">...</p>
2640 </document>
2641 ''')
2642
2643 parser = etree.XMLParser(collect_ids=False)
2644 root, dic = XMLDTDID(xml_text, parser=parser)
2645 root2 = XML(xml_text)
2646 self.assertEqual(self._writeElement(root),
2647 self._writeElement(root2))
2648 self.assertFalse(dic)
2649 self._checkIDDict(dic, {})
2650
2652 self.assertEqual(len(dic),
2653 len(expected))
2654 self.assertEqual(sorted(dic.items()),
2655 sorted(expected.items()))
2656 if sys.version_info < (3,):
2657 self.assertEqual(sorted(dic.iteritems()),
2658 sorted(expected.iteritems()))
2659 self.assertEqual(sorted(dic.keys()),
2660 sorted(expected.keys()))
2661 if sys.version_info < (3,):
2662 self.assertEqual(sorted(dic.iterkeys()),
2663 sorted(expected.iterkeys()))
2664 if sys.version_info < (3,):
2665 self.assertEqual(sorted(dic.values()),
2666 sorted(expected.values()))
2667 self.assertEqual(sorted(dic.itervalues()),
2668 sorted(expected.itervalues()))
2669
2676
2678 etree = self.etree
2679
2680 r = {'foo': 'http://ns.infrae.com/foo'}
2681 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2682 self.assertEqual(
2683 'foo',
2684 e.prefix)
2685 self.assertEqual(
2686 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
2687 self._writeElement(e))
2688
2690 etree = self.etree
2691
2692 r = {None: 'http://ns.infrae.com/foo'}
2693 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2694 self.assertEqual(
2695 None,
2696 e.prefix)
2697 self.assertEqual(
2698 '{http://ns.infrae.com/foo}bar',
2699 e.tag)
2700 self.assertEqual(
2701 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
2702 self._writeElement(e))
2703
2705 etree = self.etree
2706
2707 r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'}
2708 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2709 self.assertEqual(None, e.prefix)
2710 self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag)
2711 self.assertEqual(
2712 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'),
2713 self._writeElement(e))
2714
2716 etree = self.etree
2717
2718 r = {None: 'http://ns.infrae.com/foo',
2719 'hoi': 'http://ns.infrae.com/hoi'}
2720 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2721 e.set('{http://ns.infrae.com/hoi}test', 'value')
2722 self.assertEqual(
2723 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
2724 self._writeElement(e))
2725
2727 etree = self.etree
2728
2729 root = etree.Element('{http://test/ns}root',
2730 nsmap={None: 'http://test/ns'})
2731 sub = etree.Element('{http://test/ns}sub',
2732 nsmap={'test': 'http://test/ns'})
2733
2734 sub.attrib['{http://test/ns}attr'] = 'value'
2735 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2736 self.assertEqual(
2737 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2738 etree.tostring(sub))
2739
2740 root.append(sub)
2741 self.assertEqual(
2742 _bytes('<root xmlns="http://test/ns">'
2743 '<sub xmlns:test="http://test/ns" test:attr="value"/>'
2744 '</root>'),
2745 etree.tostring(root))
2746
2748 etree = self.etree
2749
2750 root = etree.Element('root')
2751 sub = etree.Element('{http://test/ns}sub',
2752 nsmap={'test': 'http://test/ns'})
2753
2754 sub.attrib['{http://test/ns}attr'] = 'value'
2755 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2756 self.assertEqual(
2757 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2758 etree.tostring(sub))
2759
2760 root.append(sub)
2761 self.assertEqual(
2762 _bytes('<root>'
2763 '<test:sub xmlns:test="http://test/ns" test:attr="value"/>'
2764 '</root>'),
2765 etree.tostring(root))
2766
2768 etree = self.etree
2769
2770 root = etree.Element('root')
2771 sub = etree.Element('{http://test/ns}sub',
2772 nsmap={None: 'http://test/ns'})
2773
2774 sub.attrib['{http://test/ns}attr'] = 'value'
2775 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2776 self.assertEqual(
2777 _bytes('<sub xmlns="http://test/ns" '
2778 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2779 etree.tostring(sub))
2780
2781 root.append(sub)
2782 self.assertEqual(
2783 _bytes('<root>'
2784 '<sub xmlns="http://test/ns"'
2785 ' xmlns:ns0="http://test/ns" ns0:attr="value"/>'
2786 '</root>'),
2787 etree.tostring(root))
2788
2790 etree = self.etree
2791
2792 root = etree.Element('{http://test/ns}root',
2793 nsmap={'test': 'http://test/ns',
2794 None: 'http://test/ns'})
2795 sub = etree.Element('{http://test/ns}sub',
2796 nsmap={None: 'http://test/ns'})
2797
2798 sub.attrib['{http://test/ns}attr'] = 'value'
2799 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2800 self.assertEqual(
2801 _bytes('<sub xmlns="http://test/ns" '
2802 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2803 etree.tostring(sub))
2804
2805 root.append(sub)
2806 self.assertEqual(
2807 _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">'
2808 '<test:sub test:attr="value"/>'
2809 '</test:root>'),
2810 etree.tostring(root))
2811
2813 etree = self.etree
2814 r = {None: 'http://ns.infrae.com/foo',
2815 'hoi': 'http://ns.infrae.com/hoi'}
2816 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
2817 tree = etree.ElementTree(element=e)
2818 etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
2819 self.assertEqual(
2820 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
2821 self._writeElement(e))
2822
2824 etree = self.etree
2825
2826 r = {None: 'http://ns.infrae.com/foo'}
2827 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2828 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2829
2830 e1.append(e2)
2831
2832 self.assertEqual(
2833 None,
2834 e1.prefix)
2835 self.assertEqual(
2836 None,
2837 e1[0].prefix)
2838 self.assertEqual(
2839 '{http://ns.infrae.com/foo}bar',
2840 e1.tag)
2841 self.assertEqual(
2842 '{http://ns.infrae.com/foo}bar',
2843 e1[0].tag)
2844
2846 etree = self.etree
2847
2848 r = {None: 'http://ns.infrae.com/BAR'}
2849 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
2850 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2851
2852 e1.append(e2)
2853
2854 self.assertEqual(
2855 None,
2856 e1.prefix)
2857 self.assertNotEqual(
2858 None,
2859 e2.prefix)
2860 self.assertEqual(
2861 '{http://ns.infrae.com/BAR}bar',
2862 e1.tag)
2863 self.assertEqual(
2864 '{http://ns.infrae.com/foo}bar',
2865 e2.tag)
2866
2868 ns_href = "http://a.b.c"
2869 one = self.etree.fromstring(
2870 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2871 baz = one[0][0]
2872
2873 two = self.etree.fromstring(
2874 _bytes('<root xmlns:ns="%s"/>' % ns_href))
2875 two.append(baz)
2876 del one
2877
2878 self.assertEqual('{%s}baz' % ns_href, baz.tag)
2879 self.assertEqual(
2880 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
2881 self.etree.tostring(two))
2882
2896
2913
2924
2926 xml = ('<root>' +
2927 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2928 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8')
2929 root = self.etree.fromstring(xml)
2930 self.assertEqual(xml, self.etree.tostring(root))
2931 self.etree.cleanup_namespaces(root)
2932 self.assertEqual(
2933 b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 +
2934 b'<n64:x/>' + b'</a>'*100 + b'</root>',
2935 self.etree.tostring(root))
2936
2938 xml = ('<root>' +
2939 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2940 '<n64:x xmlns:a="A" a:attr="X"/>' +
2941 '</a>'*100 +
2942 '</root>').encode('utf8')
2943 root = self.etree.fromstring(xml)
2944 self.assertEqual(xml, self.etree.tostring(root))
2945 self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'})
2946 self.assertEqual(
2947 b'<root xmlns:n64="NS64">' + b'<a>'*100 +
2948 b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>',
2949 self.etree.tostring(root))
2950
2952 xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">'
2953 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2954 '<foo>foo:bar</foo>'
2955 '</root>').encode('utf8')
2956 root = self.etree.fromstring(xml)
2957 self.assertEqual(xml, self.etree.tostring(root))
2958 self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo'])
2959 self.assertEqual(
2960 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2961 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2962 b'<foo>foo:bar</foo>'
2963 b'</root>',
2964 self.etree.tostring(root))
2965
2967 xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">'
2968 '<sub xmlns:foo="FOO">'
2969 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2970 '<foo>foo:bar</foo>'
2971 '</sub>'
2972 '</root>').encode('utf8')
2973 root = self.etree.fromstring(xml)
2974 self.assertEqual(xml, self.etree.tostring(root))
2975 self.etree.cleanup_namespaces(
2976 root,
2977 top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'},
2978 keep_ns_prefixes=['foo'])
2979 self.assertEqual(
2980 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2981 b'<sub>'
2982 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2983 b'<foo>foo:bar</foo>'
2984 b'</sub>'
2985 b'</root>',
2986 self.etree.tostring(root))
2987
2989 etree = self.etree
2990
2991 r = {None: 'http://ns.infrae.com/foo',
2992 'hoi': 'http://ns.infrae.com/hoi'}
2993 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2994 self.assertEqual(
2995 r,
2996 e.nsmap)
2997
2999 etree = self.etree
3000
3001 re = {None: 'http://ns.infrae.com/foo',
3002 'hoi': 'http://ns.infrae.com/hoi'}
3003 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
3004
3005 rs = {None: 'http://ns.infrae.com/honk',
3006 'top': 'http://ns.infrae.com/top'}
3007 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
3008
3009 r = re.copy()
3010 r.update(rs)
3011 self.assertEqual(re, e.nsmap)
3012 self.assertEqual(r, s.nsmap)
3013
3015 etree = self.etree
3016 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
3017 self.assertEqual({'hha': None}, el.nsmap)
3018
3020 Element = self.etree.Element
3021 SubElement = self.etree.SubElement
3022
3023 a = Element('a')
3024 b = SubElement(a, 'b')
3025 c = SubElement(a, 'c')
3026 d = SubElement(b, 'd')
3027 e = SubElement(c, 'e')
3028 f = SubElement(c, 'f')
3029
3030 self.assertEqual(
3031 [a, b],
3032 list(a.getiterator('a', 'b')))
3033 self.assertEqual(
3034 [],
3035 list(a.getiterator('x', 'y')))
3036 self.assertEqual(
3037 [a, f],
3038 list(a.getiterator('f', 'a')))
3039 self.assertEqual(
3040 [c, e, f],
3041 list(c.getiterator('c', '*', 'a')))
3042 self.assertEqual(
3043 [],
3044 list(a.getiterator( (), () )))
3045
3047 Element = self.etree.Element
3048 SubElement = self.etree.SubElement
3049
3050 a = Element('a')
3051 b = SubElement(a, 'b')
3052 c = SubElement(a, 'c')
3053 d = SubElement(b, 'd')
3054 e = SubElement(c, 'e')
3055 f = SubElement(c, 'f')
3056
3057 self.assertEqual(
3058 [a, b],
3059 list(a.getiterator( ('a', 'b') )))
3060 self.assertEqual(
3061 [],
3062 list(a.getiterator( ('x', 'y') )))
3063 self.assertEqual(
3064 [a, f],
3065 list(a.getiterator( ('f', 'a') )))
3066 self.assertEqual(
3067 [c, e, f],
3068 list(c.getiterator( ('c', '*', 'a') )))
3069 self.assertEqual(
3070 [],
3071 list(a.getiterator( () )))
3072
3074 Element = self.etree.Element
3075 SubElement = self.etree.SubElement
3076
3077 a = Element('{a}a')
3078 b = SubElement(a, '{a}b')
3079 c = SubElement(a, '{a}c')
3080 d = SubElement(b, '{b}d')
3081 e = SubElement(c, '{a}e')
3082 f = SubElement(c, '{b}f')
3083 g = SubElement(c, 'g')
3084
3085 self.assertEqual(
3086 [a],
3087 list(a.getiterator('{a}a')))
3088 self.assertEqual(
3089 [],
3090 list(a.getiterator('{b}a')))
3091 self.assertEqual(
3092 [],
3093 list(a.getiterator('a')))
3094 self.assertEqual(
3095 [a,b,d,c,e,f,g],
3096 list(a.getiterator('*')))
3097 self.assertEqual(
3098 [f],
3099 list(c.getiterator('{b}*')))
3100 self.assertEqual(
3101 [d, f],
3102 list(a.getiterator('{b}*')))
3103 self.assertEqual(
3104 [g],
3105 list(a.getiterator('g')))
3106 self.assertEqual(
3107 [g],
3108 list(a.getiterator('{}g')))
3109 self.assertEqual(
3110 [g],
3111 list(a.getiterator('{}*')))
3112
3114 Element = self.etree.Element
3115 Comment = self.etree.Comment
3116 SubElement = self.etree.SubElement
3117
3118 a = Element('{a}a')
3119 b = SubElement(a, '{nsA}b')
3120 c = SubElement(b, '{nsB}b')
3121 d = SubElement(a, 'b')
3122 e = SubElement(a, '{nsA}e')
3123 f = SubElement(e, '{nsB}e')
3124 g = SubElement(e, 'e')
3125 a.append(Comment('test'))
3126
3127 self.assertEqual(
3128 [b, c, d],
3129 list(a.getiterator('{*}b')))
3130 self.assertEqual(
3131 [e, f, g],
3132 list(a.getiterator('{*}e')))
3133 self.assertEqual(
3134 [a, b, c, d, e, f, g],
3135 list(a.getiterator('{*}*')))
3136
3161
3177
3194
3196 a = etree.Element("a")
3197 b = etree.SubElement(a, "b")
3198 c = etree.SubElement(a, "c")
3199 d1 = etree.SubElement(c, "d")
3200 d2 = etree.SubElement(c, "d")
3201 c.text = d1.text = 'TEXT'
3202
3203 tree = etree.ElementTree(a)
3204 self.assertEqual('.', tree.getelementpath(a))
3205 self.assertEqual('c/d[1]', tree.getelementpath(d1))
3206 self.assertEqual('c/d[2]', tree.getelementpath(d2))
3207
3208 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3209 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3210
3211 tree = etree.ElementTree(c)
3212 self.assertEqual('.', tree.getelementpath(c))
3213 self.assertEqual('d[2]', tree.getelementpath(d2))
3214 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3215
3216 tree = etree.ElementTree(b)
3217 self.assertEqual('.', tree.getelementpath(b))
3218 self.assertRaises(ValueError, tree.getelementpath, a)
3219 self.assertRaises(ValueError, tree.getelementpath, c)
3220 self.assertRaises(ValueError, tree.getelementpath, d2)
3221
3223 a = etree.Element("{http://ns1/}a")
3224 b = etree.SubElement(a, "{http://ns1/}b")
3225 c = etree.SubElement(a, "{http://ns1/}c")
3226 d1 = etree.SubElement(c, "{http://ns1/}d")
3227 d2 = etree.SubElement(c, "{http://ns2/}d")
3228 d3 = etree.SubElement(c, "{http://ns1/}d")
3229
3230 tree = etree.ElementTree(a)
3231 self.assertEqual('.', tree.getelementpath(a))
3232 self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]',
3233 tree.getelementpath(d1))
3234 self.assertEqual('{http://ns1/}c/{http://ns2/}d',
3235 tree.getelementpath(d2))
3236 self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]',
3237 tree.getelementpath(d3))
3238
3239 self.assertEqual(a, tree.find(tree.getelementpath(a)))
3240 self.assertEqual(b, tree.find(tree.getelementpath(b)))
3241 self.assertEqual(c, tree.find(tree.getelementpath(c)))
3242 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3243 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3244 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
3245
3246 tree = etree.ElementTree(c)
3247 self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1))
3248 self.assertEqual('{http://ns2/}d', tree.getelementpath(d2))
3249 self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3))
3250 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3251 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3252 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
3253
3254 tree = etree.ElementTree(b)
3255 self.assertRaises(ValueError, tree.getelementpath, d1)
3256 self.assertRaises(ValueError, tree.getelementpath, d2)
3257
3264
3271
3280
3282 XML = self.etree.XML
3283 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
3284 self.assertEqual(len(root.findall(".//{X}b")), 2)
3285 self.assertEqual(len(root.findall(".//{X}*")), 2)
3286 self.assertEqual(len(root.findall(".//b")), 3)
3287
3289 XML = self.etree.XML
3290 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3291 nsmap = {'xx': 'X'}
3292 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3293 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
3294 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3295 nsmap = {'xx': 'Y'}
3296 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
3297 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
3298 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3299
3309
3316
3318 etree = self.etree
3319 e = etree.Element('foo')
3320 for i in range(10):
3321 etree.SubElement(e, 'a%s' % i)
3322 for i in range(10):
3323 self.assertEqual(
3324 i,
3325 e.index(e[i]))
3326 self.assertEqual(
3327 3, e.index(e[3], 3))
3328 self.assertRaises(
3329 ValueError, e.index, e[3], 4)
3330 self.assertRaises(
3331 ValueError, e.index, e[3], 0, 2)
3332 self.assertRaises(
3333 ValueError, e.index, e[8], 0, -3)
3334 self.assertRaises(
3335 ValueError, e.index, e[8], -5, -3)
3336 self.assertEqual(
3337 8, e.index(e[8], 0, -1))
3338 self.assertEqual(
3339 8, e.index(e[8], -12, -1))
3340 self.assertEqual(
3341 0, e.index(e[0], -12, -1))
3342
3344 etree = self.etree
3345 e = etree.Element('foo')
3346 for i in range(10):
3347 el = etree.SubElement(e, 'a%s' % i)
3348 el.text = "text%d" % i
3349 el.tail = "tail%d" % i
3350
3351 child0 = e[0]
3352 child1 = e[1]
3353 child2 = e[2]
3354
3355 e.replace(e[0], e[1])
3356 self.assertEqual(
3357 9, len(e))
3358 self.assertEqual(
3359 child1, e[0])
3360 self.assertEqual(
3361 child1.text, "text1")
3362 self.assertEqual(
3363 child1.tail, "tail1")
3364 self.assertEqual(
3365 child0.tail, "tail0")
3366 self.assertEqual(
3367 child2, e[1])
3368
3369 e.replace(e[-1], e[0])
3370 self.assertEqual(
3371 child1, e[-1])
3372 self.assertEqual(
3373 child1.text, "text1")
3374 self.assertEqual(
3375 child1.tail, "tail1")
3376 self.assertEqual(
3377 child2, e[0])
3378
3380 etree = self.etree
3381 e = etree.Element('foo')
3382 for i in range(10):
3383 etree.SubElement(e, 'a%s' % i)
3384
3385 new_element = etree.Element("test")
3386 new_element.text = "TESTTEXT"
3387 new_element.tail = "TESTTAIL"
3388 child1 = e[1]
3389 e.replace(e[0], new_element)
3390 self.assertEqual(
3391 new_element, e[0])
3392 self.assertEqual(
3393 "TESTTEXT",
3394 e[0].text)
3395 self.assertEqual(
3396 "TESTTAIL",
3397 e[0].tail)
3398 self.assertEqual(
3399 child1, e[1])
3400
3402 Element = self.etree.Element
3403 SubElement = self.etree.SubElement
3404
3405 a = Element('a')
3406
3407 e = Element('e')
3408 f = Element('f')
3409 g = Element('g')
3410
3411 a[:] = [e, f, g]
3412 self.assertEqual(
3413 [e, f, g],
3414 list(a))
3415
3416 a[::-1] = [e, f, g]
3417 self.assertEqual(
3418 [g, f, e],
3419 list(a))
3420
3438
3456
3474
3476 Element = self.etree.Element
3477 SubElement = self.etree.SubElement
3478 try:
3479 slice
3480 except NameError:
3481 print("slice() not found")
3482 return
3483
3484 a = Element('a')
3485 b = SubElement(a, 'b')
3486 c = SubElement(a, 'c')
3487 d = SubElement(a, 'd')
3488 e = SubElement(a, 'e')
3489
3490 x = Element('x')
3491 y = Element('y')
3492 z = Element('z')
3493
3494 self.assertRaises(
3495 ValueError,
3496 operator.setitem, a, slice(1,None,2), [x, y, z])
3497
3498 self.assertEqual(
3499 [b, c, d, e],
3500 list(a))
3501
3514
3516 XML = self.etree.XML
3517 root = XML(_bytes(
3518 '<?xml version="1.0"?>\n'
3519 '<root>' + '\n' * 65536 +
3520 '<p>' + '\n' * 65536 + '</p>\n' +
3521 '<br/>\n'
3522 '</root>'))
3523
3524 if self.etree.LIBXML_VERSION >= (2, 9):
3525 expected = [2, 131074, 131076]
3526 else:
3527 expected = [2, 65535, 65535]
3528
3529 self.assertEqual(expected, [el.sourceline for el in root.iter()])
3530
3538
3547
3557
3567
3573
3581
3587
3594
3600
3602 etree = self.etree
3603 xml_header = '<?xml version="1.0" encoding="ascii"?>'
3604 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3605 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3606 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
3607
3608 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
3609
3610 tree = etree.parse(BytesIO(xml))
3611 docinfo = tree.docinfo
3612 self.assertEqual(docinfo.encoding, "ascii")
3613 self.assertEqual(docinfo.xml_version, "1.0")
3614 self.assertEqual(docinfo.public_id, pub_id)
3615 self.assertEqual(docinfo.system_url, sys_id)
3616 self.assertEqual(docinfo.root_name, 'html')
3617 self.assertEqual(docinfo.doctype, doctype_string)
3618
3634
3646
3658
3664
3666 etree = self.etree
3667 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3668 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3669 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
3670
3671 xml = _bytes('<!DOCTYPE root>\n<root/>')
3672 tree = etree.parse(BytesIO(xml))
3673 self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
3674 etree.tostring(tree, doctype=doctype_string))
3675
3677 etree = self.etree
3678 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3679 self.assertEqual(root.base, "http://no/such/url")
3680 self.assertEqual(
3681 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3682 root.base = "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
3689 etree = self.etree
3690 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3691 self.assertEqual(root.base, "http://no/such/url")
3692 self.assertEqual(
3693 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3694 root.set('{http://www.w3.org/XML/1998/namespace}base',
3695 "https://secret/url")
3696 self.assertEqual(root.base, "https://secret/url")
3697 self.assertEqual(
3698 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3699 "https://secret/url")
3700
3706
3711
3718
3732
3734 Element = self.etree.Element
3735
3736 a = Element('a')
3737 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
3738 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
3739
3740 self.assertRaises(ValueError, Element, 'ha\0ho')
3741
3743 Element = self.etree.Element
3744
3745 a = Element('a')
3746 self.assertRaises(ValueError, setattr, a, "text",
3747 _str('ha\0ho'))
3748 self.assertRaises(ValueError, setattr, a, "tail",
3749 _str('ha\0ho'))
3750
3751 self.assertRaises(ValueError, Element,
3752 _str('ha\0ho'))
3753
3755 Element = self.etree.Element
3756
3757 a = Element('a')
3758 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
3759 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
3760
3761 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
3762 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
3763
3764 self.assertRaises(ValueError, Element, 'ha\x07ho')
3765 self.assertRaises(ValueError, Element, 'ha\x02ho')
3766
3768 Element = self.etree.Element
3769
3770 a = Element('a')
3771 self.assertRaises(ValueError, setattr, a, "text",
3772 _str('ha\x07ho'))
3773 self.assertRaises(ValueError, setattr, a, "text",
3774 _str('ha\x02ho'))
3775
3776 self.assertRaises(ValueError, setattr, a, "tail",
3777 _str('ha\x07ho'))
3778 self.assertRaises(ValueError, setattr, a, "tail",
3779 _str('ha\x02ho'))
3780
3781 self.assertRaises(ValueError, Element,
3782 _str('ha\x07ho'))
3783 self.assertRaises(ValueError, Element,
3784 _str('ha\x02ho'))
3785
3787 Element = self.etree.Element
3788
3789 a = Element('a')
3790 self.assertRaises(ValueError, setattr, a, "text",
3791 _str('ha\u1234\x07ho'))
3792 self.assertRaises(ValueError, setattr, a, "text",
3793 _str('ha\u1234\x02ho'))
3794
3795 self.assertRaises(ValueError, setattr, a, "tail",
3796 _str('ha\u1234\x07ho'))
3797 self.assertRaises(ValueError, setattr, a, "tail",
3798 _str('ha\u1234\x02ho'))
3799
3800 self.assertRaises(ValueError, Element,
3801 _str('ha\u1234\x07ho'))
3802 self.assertRaises(ValueError, Element,
3803 _str('ha\u1234\x02ho'))
3804
3818
3823
3841
3861
3863 tostring = self.etree.tostring
3864 html = self.etree.fromstring(
3865 '<html><body>'
3866 '<div><p>Some text<i>\r\n</i></p></div>\r\n'
3867 '</body></html>',
3868 parser=self.etree.HTMLParser())
3869 self.assertEqual(html.tag, 'html')
3870 div = html.find('.//div')
3871 self.assertEqual(div.tail, '\r\n')
3872 result = tostring(div, method='html')
3873 self.assertEqual(
3874 result,
3875 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3876 result = tostring(div, method='html', with_tail=True)
3877 self.assertEqual(
3878 result,
3879 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3880 result = tostring(div, method='html', with_tail=False)
3881 self.assertEqual(
3882 result,
3883 _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
3884
3906
3908 tostring = self.etree.tostring
3909 XML = self.etree.XML
3910 ElementTree = self.etree.ElementTree
3911
3912 root = XML(_bytes("<root/>"))
3913
3914 tree = ElementTree(root)
3915 self.assertEqual(None, tree.docinfo.standalone)
3916
3917 result = tostring(root, xml_declaration=True, encoding="ASCII")
3918 self.assertEqual(result, _bytes(
3919 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3920
3921 result = tostring(root, xml_declaration=True, encoding="ASCII",
3922 standalone=True)
3923 self.assertEqual(result, _bytes(
3924 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3925
3926 tree = ElementTree(XML(result))
3927 self.assertEqual(True, tree.docinfo.standalone)
3928
3929 result = tostring(root, xml_declaration=True, encoding="ASCII",
3930 standalone=False)
3931 self.assertEqual(result, _bytes(
3932 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
3933
3934 tree = ElementTree(XML(result))
3935 self.assertEqual(False, tree.docinfo.standalone)
3936
3956
3958 tostring = self.etree.tostring
3959 Element = self.etree.Element
3960 SubElement = self.etree.SubElement
3961
3962 a = Element('a')
3963 a.text = "A"
3964 a.tail = "tail"
3965 b = SubElement(a, 'b')
3966 b.text = "B"
3967 b.tail = _str("Søk på nettet")
3968 c = SubElement(a, 'c')
3969 c.text = "C"
3970
3971 result = tostring(a, method="text", encoding="UTF-16")
3972
3973 self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
3974 result)
3975
3977 tostring = self.etree.tostring
3978 Element = self.etree.Element
3979 SubElement = self.etree.SubElement
3980
3981 a = Element('a')
3982 a.text = _str('Søk på nettetA')
3983 a.tail = "tail"
3984 b = SubElement(a, 'b')
3985 b.text = "B"
3986 b.tail = _str('Søk på nettetB')
3987 c = SubElement(a, 'c')
3988 c.text = "C"
3989
3990 self.assertRaises(UnicodeEncodeError,
3991 tostring, a, method="text")
3992
3993 self.assertEqual(
3994 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
3995 tostring(a, encoding="UTF-8", method="text"))
3996
4009
4025
4029
4044
4062
4075
4077 tostring = self.etree.tostring
4078 Element = self.etree.Element
4079 SubElement = self.etree.SubElement
4080
4081 a = Element('a')
4082 b = SubElement(a, 'b')
4083 c = SubElement(a, 'c')
4084 d = SubElement(c, 'd')
4085 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
4086 self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
4087 self.assertEqual(_bytes('<b></b>'),
4088 canonicalize(tostring(b, encoding=_unicode)))
4089 self.assertEqual(_bytes('<c><d></d></c>'),
4090 canonicalize(tostring(c, encoding=_unicode)))
4091
4096
4111
4113 tostring = self.etree.tostring
4114 Element = self.etree.Element
4115 SubElement = self.etree.SubElement
4116
4117 a = Element('a')
4118 b = SubElement(a, 'b')
4119 c = SubElement(a, 'c')
4120
4121 result = tostring(a, encoding=_unicode)
4122 self.assertEqual(result, "<a><b/><c/></a>")
4123
4124 result = tostring(a, encoding=_unicode, pretty_print=False)
4125 self.assertEqual(result, "<a><b/><c/></a>")
4126
4127 result = tostring(a, encoding=_unicode, pretty_print=True)
4128 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4129
4141
4143 class SubEl(etree.ElementBase):
4144 pass
4145
4146 el1 = SubEl()
4147 el2 = SubEl()
4148 self.assertEqual('SubEl', el1.tag)
4149 self.assertEqual('SubEl', el2.tag)
4150 el1.other = el2
4151 el2.other = el1
4152
4153 del el1, el2
4154 gc.collect()
4155
4156
4170
4172 root = etree.Element('parent')
4173 c1 = etree.SubElement(root, 'child1')
4174 c2 = etree.SubElement(root, 'child2')
4175
4176 root.remove(c1)
4177 root.remove(c2)
4178 c1.addnext(c2)
4179 c1.tail = 'abc'
4180 c2.tail = 'xyz'
4181 del c1
4182
4183 c2.getprevious()
4184
4185 self.assertEqual('child1', c2.getprevious().tag)
4186 self.assertEqual('abc', c2.getprevious().tail)
4187
4188
4189
4190 - def _writeElement(self, element, encoding='us-ascii', compression=0):
4201
4202
4246
4247 res_instance = res()
4248 parser = etree.XMLParser(load_dtd = True)
4249 parser.resolvers.add(res_instance)
4250
4251 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4252 parser = parser)
4253
4254 self.include(tree)
4255
4256 called = list(res_instance.called.items())
4257 called.sort()
4258 self.assertEqual(
4259 [("dtd", True), ("include", True), ("input", True)],
4260 called)
4261
4263 data = textwrap.dedent('''
4264 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
4265 <foo/>
4266 <xi:include href="./test.xml" />
4267 </doc>
4268 ''')
4269
4270 class Resolver(etree.Resolver):
4271 called = {}
4272
4273 def resolve(self, url, id, context):
4274 if url.endswith("test_xinclude.xml"):
4275 assert not self.called.get("input")
4276 self.called["input"] = True
4277 return None
4278 elif url.endswith('/test5.xml'):
4279 assert not self.called.get("DONE")
4280 self.called["DONE"] = True
4281 return self.resolve_string('<DONE/>', context)
4282 else:
4283 _, filename = url.rsplit('/', 1)
4284 assert not self.called.get(filename)
4285 self.called[filename] = True
4286 next_data = data.replace(
4287 'test.xml', 'test%d.xml' % len(self.called))
4288 return self.resolve_string(next_data, context)
4289
4290 res_instance = Resolver()
4291 parser = etree.XMLParser(load_dtd=True)
4292 parser.resolvers.add(res_instance)
4293
4294 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4295 parser=parser)
4296
4297 self.include(tree)
4298
4299 called = list(res_instance.called.items())
4300 called.sort()
4301 self.assertEqual(
4302 [("DONE", True), ("input", True), ("test.xml", True),
4303 ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)],
4304 called)
4305
4306
4310
4311
4313 from lxml import ElementInclude
4314
4315 - def include(self, tree, loader=None, max_depth=None):
4317
4318 XINCLUDE = {}
4319
4320 XINCLUDE["Recursive1.xml"] = """\
4321 <?xml version='1.0'?>
4322 <document xmlns:xi="http://www.w3.org/2001/XInclude">
4323 <p>The following is the source code of Recursive2.xml:</p>
4324 <xi:include href="Recursive2.xml"/>
4325 </document>
4326 """
4327
4328 XINCLUDE["Recursive2.xml"] = """\
4329 <?xml version='1.0'?>
4330 <document xmlns:xi="http://www.w3.org/2001/XInclude">
4331 <p>The following is the source code of Recursive3.xml:</p>
4332 <xi:include href="Recursive3.xml"/>
4333 </document>
4334 """
4335
4336 XINCLUDE["Recursive3.xml"] = """\
4337 <?xml version='1.0'?>
4338 <document xmlns:xi="http://www.w3.org/2001/XInclude">
4339 <p>The following is the source code of Recursive1.xml:</p>
4340 <xi:include href="Recursive1.xml"/>
4341 </document>
4342 """
4343
4352
4354
4355 document = self.xinclude_loader("Recursive1.xml").getroottree()
4356 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm:
4357 self.include(document, self.xinclude_loader)
4358 self.assertEqual(str(cm.exception),
4359 "recursive include of 'Recursive2.xml' detected")
4360
4361
4362 document = self.xinclude_loader("Recursive1.xml").getroottree()
4363 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm:
4364 self.include(document, self.xinclude_loader, max_depth=None)
4365 self.assertEqual(str(cm.exception),
4366 "recursive include of 'Recursive2.xml' detected")
4367
4368 document = self.xinclude_loader("Recursive1.xml").getroottree()
4369 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm:
4370 self.include(document, self.xinclude_loader, max_depth=0)
4371 self.assertEqual(str(cm.exception),
4372 "maximum xinclude depth reached when including file Recursive2.xml")
4373
4374 document = self.xinclude_loader("Recursive1.xml").getroottree()
4375 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm:
4376 self.include(document, self.xinclude_loader, max_depth=1)
4377 self.assertEqual(str(cm.exception),
4378 "maximum xinclude depth reached when including file Recursive3.xml")
4379
4380 document = self.xinclude_loader("Recursive1.xml").getroottree()
4381 with self.assertRaises(self.ElementInclude.LimitedRecursiveIncludeError) as cm:
4382 self.include(document, self.xinclude_loader, max_depth=2)
4383 self.assertEqual(str(cm.exception),
4384 "maximum xinclude depth reached when including file Recursive1.xml")
4385
4386 document = self.xinclude_loader("Recursive1.xml").getroottree()
4387 with self.assertRaises(self.ElementInclude.FatalIncludeError) as cm:
4388 self.include(document, self.xinclude_loader, max_depth=3)
4389 self.assertEqual(str(cm.exception),
4390 "recursive include of 'Recursive2.xml' detected")
4391
4392
4395 tree = self.parse(_bytes('<a><b/></a>'))
4396 f = BytesIO()
4397 tree.write_c14n(f)
4398 s = f.getvalue()
4399 self.assertEqual(_bytes('<a><b></b></a>'),
4400 s)
4401
4403 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4404 f = BytesIO()
4405 tree.write_c14n(f, compression=9)
4406 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile:
4407 s = gzfile.read()
4408 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4409 s)
4410
4418
4427
4436
4438 tree = self.parse(
4439 b'<?xml version="1.0"?> <a> abc \n <b> btext </b> btail <c/> ctail </a> ')
4440 f = BytesIO()
4441 tree.write(f, method='c14n2')
4442 s = f.getvalue()
4443 self.assertEqual(b'<a> abc \n <b> btext </b> btail <c></c> ctail </a>',
4444 s)
4445
4446 f = BytesIO()
4447 tree.write(f, method='c14n2', strip_text=True)
4448 s = f.getvalue()
4449 self.assertEqual(b'<a>abc<b>btext</b>btail<c></c>ctail</a>',
4450 s)
4451
4469
4487
4499
4511
4523
4525 tree = self.parse(_bytes(
4526 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4527 f = BytesIO()
4528 tree.write_c14n(f)
4529 s = f.getvalue()
4530 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4531 s)
4532 f = BytesIO()
4533 tree.write_c14n(f, exclusive=False)
4534 s = f.getvalue()
4535 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4536 s)
4537 f = BytesIO()
4538 tree.write_c14n(f, exclusive=True)
4539 s = f.getvalue()
4540 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4541 s)
4542
4543 f = BytesIO()
4544 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
4545 s = f.getvalue()
4546 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
4547 s)
4548
4550 tree = self.parse(_bytes(
4551 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4552 s = etree.tostring(tree, method='c14n')
4553 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4554 s)
4555 s = etree.tostring(tree, method='c14n', exclusive=False)
4556 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4557 s)
4558 s = etree.tostring(tree, method='c14n', exclusive=True)
4559 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4560 s)
4561
4562 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4563 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
4564 s)
4565
4567 tree = self.parse(_bytes(
4568 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4569 s = etree.tostring(tree.getroot(), method='c14n')
4570 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4571 s)
4572 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
4573 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4574 s)
4575 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
4576 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4577 s)
4578
4579 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
4580 self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4581 s)
4582 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
4583 self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
4584 s)
4585
4586 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4587 self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4588 s)
4589
4591 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
4592 tree = self.parse(_bytes(
4593 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4594
4595 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
4596 self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4597 s)
4598
4599
4602 tree = self.parse(_bytes('<a><b/></a>'))
4603 f = BytesIO()
4604 tree.write(f)
4605 s = f.getvalue()
4606 self.assertEqual(_bytes('<a><b/></a>'),
4607 s)
4608
4610 tree = self.parse(_bytes('<a><b/></a>'))
4611 f = BytesIO()
4612 tree.write(f, doctype='HUHU')
4613 s = f.getvalue()
4614 self.assertEqual(_bytes('HUHU\n<a><b/></a>'),
4615 s)
4616
4618 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4619 f = BytesIO()
4620 tree.write(f, compression=9)
4621 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile:
4622 s = gzfile.read()
4623 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4624 s)
4625
4627 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4628 f = BytesIO()
4629 tree.write(f, compression=9, doctype='<!DOCTYPE a>')
4630 with gzip.GzipFile(fileobj=BytesIO(f.getvalue())) as gzfile:
4631 s = gzfile.read()
4632 self.assertEqual(_bytes('<!DOCTYPE a>\n<a>'+'<b/>'*200+'</a>'),
4633 s)
4634
4636 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4637 f = BytesIO()
4638 tree.write(f, compression=0)
4639 s0 = f.getvalue()
4640
4641 f = BytesIO()
4642 tree.write(f)
4643 self.assertEqual(f.getvalue(), s0)
4644
4645 f = BytesIO()
4646 tree.write(f, compression=1)
4647 s = f.getvalue()
4648 self.assertTrue(len(s) <= len(s0))
4649 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile:
4650 s1 = gzfile.read()
4651
4652 f = BytesIO()
4653 tree.write(f, compression=9)
4654 s = f.getvalue()
4655 self.assertTrue(len(s) <= len(s0))
4656 with gzip.GzipFile(fileobj=BytesIO(s)) as gzfile:
4657 s9 = gzfile.read()
4658
4659 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4660 s0)
4661 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4662 s1)
4663 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4664 s9)
4665
4673
4682
4690
4699
4709
4710
4712 etree = etree
4713
4735
4737 """This can't really be tested as long as there isn't a way to
4738 reset the logging setup ...
4739 """
4740 parse = self.etree.parse
4741
4742 messages = []
4743 class Logger(self.etree.PyErrorLog):
4744 def log(self, entry, message, *args):
4745 messages.append(message)
4746
4747 self.etree.use_global_python_log(Logger())
4748 f = BytesIO('<a><b></c></b></a>')
4749 try:
4750 parse(f)
4751 except SyntaxError:
4752 pass
4753 f.close()
4754
4755 self.assertTrue([ message for message in messages
4756 if 'mismatch' in message ])
4757 self.assertTrue([ message for message in messages
4758 if ':PARSER:' in message])
4759 self.assertTrue([ message for message in messages
4760 if ':ERR_TAG_NAME_MISMATCH:' in message ])
4761 self.assertTrue([ message for message in messages
4762 if ':1:15:' in message ])
4763
4764
4766 etree = etree
4767
4771
4773 class Target(object):
4774 def start(self, tag, attrib):
4775 return 'start(%s)' % tag
4776 def end(self, tag):
4777 return 'end(%s)' % tag
4778 def close(self):
4779 return 'close()'
4780
4781 parser = self.etree.XMLPullParser(target=Target())
4782 events = parser.read_events()
4783
4784 parser.feed('<root><element>')
4785 self.assertFalse(list(events))
4786 self.assertFalse(list(events))
4787 parser.feed('</element><child>')
4788 self.assertEqual([('end', 'end(element)')], list(events))
4789 parser.feed('</child>')
4790 self.assertEqual([('end', 'end(child)')], list(events))
4791 parser.feed('</root>')
4792 self.assertEqual([('end', 'end(root)')], list(events))
4793 self.assertFalse(list(events))
4794 self.assertEqual('close()', parser.close())
4795
4797 class Target(object):
4798 def start(self, tag, attrib):
4799 return 'start(%s)' % tag
4800 def end(self, tag):
4801 return 'end(%s)' % tag
4802 def close(self):
4803 return 'close()'
4804
4805 parser = self.etree.XMLPullParser(
4806 ['start', 'end'], target=Target())
4807 events = parser.read_events()
4808
4809 parser.feed('<root><element>')
4810 self.assertEqual(
4811 [('start', 'start(root)'), ('start', 'start(element)')],
4812 list(events))
4813 self.assertFalse(list(events))
4814 parser.feed('</element><child>')
4815 self.assertEqual(
4816 [('end', 'end(element)'), ('start', 'start(child)')],
4817 list(events))
4818 parser.feed('</child>')
4819 self.assertEqual(
4820 [('end', 'end(child)')],
4821 list(events))
4822 parser.feed('</root>')
4823 self.assertEqual(
4824 [('end', 'end(root)')],
4825 list(events))
4826 self.assertFalse(list(events))
4827 self.assertEqual('close()', parser.close())
4828
4830 parser = self.etree.XMLPullParser(
4831 ['start', 'end'], target=etree.TreeBuilder())
4832 events = parser.read_events()
4833
4834 parser.feed('<root><element>')
4835 self.assert_event_tags(
4836 events, [('start', 'root'), ('start', 'element')])
4837 self.assertFalse(list(events))
4838 parser.feed('</element><child>')
4839 self.assert_event_tags(
4840 events, [('end', 'element'), ('start', 'child')])
4841 parser.feed('</child>')
4842 self.assert_event_tags(
4843 events, [('end', 'child')])
4844 parser.feed('</root>')
4845 self.assert_event_tags(
4846 events, [('end', 'root')])
4847 self.assertFalse(list(events))
4848 root = parser.close()
4849 self.assertEqual('root', root.tag)
4850
4852 class Target(etree.TreeBuilder):
4853 def end(self, tag):
4854 el = super(Target, self).end(tag)
4855 el.tag += '-huhu'
4856 return el
4857
4858 parser = self.etree.XMLPullParser(
4859 ['start', 'end'], target=Target())
4860 events = parser.read_events()
4861
4862 parser.feed('<root><element>')
4863 self.assert_event_tags(
4864 events, [('start', 'root'), ('start', 'element')])
4865 self.assertFalse(list(events))
4866 parser.feed('</element><child>')
4867 self.assert_event_tags(
4868 events, [('end', 'element-huhu'), ('start', 'child')])
4869 parser.feed('</child>')
4870 self.assert_event_tags(
4871 events, [('end', 'child-huhu')])
4872 parser.feed('</root>')
4873 self.assert_event_tags(
4874 events, [('end', 'root-huhu')])
4875 self.assertFalse(list(events))
4876 root = parser.close()
4877 self.assertEqual('root-huhu', root.tag)
4878
4879
4908
4909
4910 if __name__ == '__main__':
4911 print('to test use test.py %s' % __file__)
4912