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
26 from .common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
27 from .common_imports import canonicalize, sorted, _str, _bytes
28
29 print("")
30 print("TESTED VERSION: %s" % etree.__version__)
31 print(" Python: " + repr(sys.version_info))
32 print(" lxml.etree: " + repr(etree.LXML_VERSION))
33 print(" libxml used: " + repr(etree.LIBXML_VERSION))
34 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION))
35 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION))
36 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
37 print("")
38
39 try:
40 _unicode = unicode
41 except NameError:
42
43 _unicode = str
44
45
47 """Tests only for etree, not ElementTree"""
48 etree = etree
49
60
69
77
84
86 Element = self.etree.Element
87 el = Element('name')
88 self.assertRaises(ValueError, Element, '{}')
89 self.assertRaises(ValueError, setattr, el, 'tag', '{}')
90
91 self.assertRaises(ValueError, Element, '{test}')
92 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
93
101
103 Element = self.etree.Element
104 self.assertRaises(ValueError, Element, "p'name")
105 self.assertRaises(ValueError, Element, 'p"name')
106
107 self.assertRaises(ValueError, Element, "{test}p'name")
108 self.assertRaises(ValueError, Element, '{test}p"name')
109
110 el = Element('name')
111 self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
112 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
113
115 Element = self.etree.Element
116 self.assertRaises(ValueError, Element, ' name ')
117 self.assertRaises(ValueError, Element, 'na me')
118 self.assertRaises(ValueError, Element, '{test} name')
119
120 el = Element('name')
121 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
122
130
138
140 Element = self.etree.Element
141 SubElement = self.etree.SubElement
142
143 el = Element('name')
144 self.assertRaises(ValueError, SubElement, el, "p'name")
145 self.assertRaises(ValueError, SubElement, el, "{test}p'name")
146
147 self.assertRaises(ValueError, SubElement, el, 'p"name')
148 self.assertRaises(ValueError, SubElement, el, '{test}p"name')
149
158
167
169 QName = self.etree.QName
170 self.assertRaises(ValueError, QName, '')
171 self.assertRaises(ValueError, QName, 'test', '')
172
174 QName = self.etree.QName
175 self.assertRaises(ValueError, QName, 'p:name')
176 self.assertRaises(ValueError, QName, 'test', 'p:name')
177
179 QName = self.etree.QName
180 self.assertRaises(ValueError, QName, ' name ')
181 self.assertRaises(ValueError, QName, 'na me')
182 self.assertRaises(ValueError, QName, 'test', ' name')
183
191
193
194 QName = self.etree.QName
195 qname1 = QName('http://myns', 'a')
196 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
197
198 qname2 = QName(a)
199 self.assertEqual(a.tag, qname1.text)
200 self.assertEqual(qname1.text, qname2.text)
201 self.assertEqual(qname1, qname2)
202
204
205 etree = self.etree
206 qname = etree.QName('http://myns', 'a')
207 a = etree.Element(qname, nsmap={'p' : 'http://myns'})
208 a.text = qname
209
210 self.assertEqual("p:a", a.text)
211
220
235
241
251
263
265 Element = self.etree.Element
266
267 keys = ["attr%d" % i for i in range(10)]
268 values = ["TEST-%d" % i for i in range(10)]
269 items = list(zip(keys, values))
270
271 root = Element("root")
272 for key, value in items:
273 root.set(key, value)
274 self.assertEqual(keys, root.attrib.keys())
275 self.assertEqual(values, root.attrib.values())
276
277 root2 = Element("root2", root.attrib,
278 attr_99='TOAST-1', attr_98='TOAST-2')
279 self.assertEqual(['attr_98', 'attr_99'] + keys,
280 root2.attrib.keys())
281 self.assertEqual(['TOAST-2', 'TOAST-1'] + values,
282 root2.attrib.values())
283
284 self.assertEqual(keys, root.attrib.keys())
285 self.assertEqual(values, root.attrib.values())
286
288
289
290 Element = self.etree.Element
291 root = Element("root")
292 self.assertRaises(TypeError, root.set, "newattr", 5)
293 self.assertRaises(TypeError, root.set, "newattr", object)
294 self.assertRaises(TypeError, root.set, "newattr", None)
295 self.assertRaises(TypeError, root.set, "newattr")
296
310
332
334 XML = self.etree.XML
335 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
336
337 root = XML(xml)
338 self.etree.strip_elements(root, 'a')
339 self.assertEqual(_bytes('<test><x></x></test>'),
340 self._writeElement(root))
341
342 root = XML(xml)
343 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
344 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'),
345 self._writeElement(root))
346
347 root = XML(xml)
348 self.etree.strip_elements(root, 'c')
349 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
350 self._writeElement(root))
351
353 XML = self.etree.XML
354 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>')
355
356 root = XML(xml)
357 self.etree.strip_elements(root, 'a')
358 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>'),
359 self._writeElement(root))
360
361 root = XML(xml)
362 self.etree.strip_elements(root, '{urn:a}b', 'c')
363 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>'),
364 self._writeElement(root))
365
366 root = XML(xml)
367 self.etree.strip_elements(root, '{urn:a}*', 'c')
368 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
369 self._writeElement(root))
370
371 root = XML(xml)
372 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
373 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
374 self._writeElement(root))
375
394
420
447
474
493
506
517
523
525 XML = self.etree.XML
526 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
527 self.assertEqual(root[0].target, "mypi")
528 self.assertEqual(root[0].get('my'), "1")
529 self.assertEqual(root[0].get('test'), " abc ")
530 self.assertEqual(root[0].get('quotes'), "' '")
531 self.assertEqual(root[0].get('only'), None)
532 self.assertEqual(root[0].get('names'), None)
533 self.assertEqual(root[0].get('nope'), None)
534
536 XML = self.etree.XML
537 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
538 self.assertEqual(root[0].target, "mypi")
539 self.assertEqual(root[0].attrib['my'], "1")
540 self.assertEqual(root[0].attrib['test'], " abc ")
541 self.assertEqual(root[0].attrib['quotes'], "' '")
542 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
543 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
544 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
545
547
548 ProcessingInstruction = self.etree.ProcessingInstruction
549
550 a = ProcessingInstruction("PI", "ONE")
551 b = copy.deepcopy(a)
552 b.text = "ANOTHER"
553
554 self.assertEqual('ONE', a.text)
555 self.assertEqual('ANOTHER', b.text)
556
572
587
598
610
629
634
647
658
659 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
660 events = list(iterparse(f, events=('end', 'comment')))
661 root = events[-1][1]
662 self.assertEqual(6, len(events))
663 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'],
664 [ name(*item) for item in events ])
665 self.assertEqual(
666 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
667 tostring(root))
668
680
681 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
682 events = list(iterparse(f, events=('end', 'pi')))
683 root = events[-2][1]
684 self.assertEqual(8, len(events))
685 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
686 ('pid','d'), 'a', ('pie','e')],
687 [ name(*item) for item in events ])
688 self.assertEqual(
689 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
690 tostring(ElementTree(root)))
691
706
712
714 iterparse = self.etree.iterparse
715 f = BytesIO('<a><b><c/></a>')
716 it = iterparse(f, events=('start', 'end'), recover=True)
717 events = [(ev, el.tag) for ev, el in it]
718 root = it.root
719 self.assertTrue(root is not None)
720
721 self.assertEqual(1, events.count(('start', 'a')))
722 self.assertEqual(1, events.count(('end', 'a')))
723
724 self.assertEqual(1, events.count(('start', 'b')))
725 self.assertEqual(1, events.count(('end', 'b')))
726
727 self.assertEqual(1, events.count(('start', 'c')))
728 self.assertEqual(1, events.count(('end', 'c')))
729
731 iterparse = self.etree.iterparse
732 f = BytesIO('<a><b><c/></d><b><c/></a></b>')
733 it = iterparse(f, events=('start', 'end'), recover=True)
734 events = [(ev, el.tag) for ev, el in it]
735 root = it.root
736 self.assertTrue(root is not None)
737
738 self.assertEqual(1, events.count(('start', 'a')))
739 self.assertEqual(1, events.count(('end', 'a')))
740
741 self.assertEqual(2, events.count(('start', 'b')))
742 self.assertEqual(2, events.count(('end', 'b')))
743
744 self.assertEqual(2, events.count(('start', 'c')))
745 self.assertEqual(2, events.count(('end', 'c')))
746
748 iterparse = self.etree.iterparse
749 f = BytesIO("""
750 <a> \n \n <b> b test </b> \n
751
752 \n\t <c> \n </c> </a> \n """)
753 iterator = iterparse(f, remove_blank_text=True)
754 text = [ (element.text, element.tail)
755 for event, element in iterator ]
756 self.assertEqual(
757 [(" b test ", None), (" \n ", None), (None, None)],
758 text)
759
761 iterparse = self.etree.iterparse
762 f = BytesIO('<a><b><d/></b><c/></a>')
763
764 iterator = iterparse(f, tag="b", events=('start', 'end'))
765 events = list(iterator)
766 root = iterator.root
767 self.assertEqual(
768 [('start', root[0]), ('end', root[0])],
769 events)
770
772 iterparse = self.etree.iterparse
773 f = BytesIO('<a><b><d/></b><c/></a>')
774
775 iterator = iterparse(f, tag="*", events=('start', 'end'))
776 events = list(iterator)
777 self.assertEqual(
778 8,
779 len(events))
780
782 iterparse = self.etree.iterparse
783 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
784
785 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
786 events = list(iterator)
787 root = iterator.root
788 self.assertEqual(
789 [('start', root[0]), ('end', root[0])],
790 events)
791
793 iterparse = self.etree.iterparse
794 f = BytesIO('<a><b><d/></b><c/></a>')
795 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
796 events = list(iterator)
797 root = iterator.root
798 self.assertEqual(
799 [('start', root[0]), ('end', root[0])],
800 events)
801
802 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
803 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
804 events = list(iterator)
805 root = iterator.root
806 self.assertEqual([], events)
807
809 iterparse = self.etree.iterparse
810 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
811 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
812 events = list(iterator)
813 self.assertEqual(8, len(events))
814
816 iterparse = self.etree.iterparse
817 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
818 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
819 events = list(iterator)
820 self.assertEqual([], events)
821
822 f = BytesIO('<a><b><d/></b><c/></a>')
823 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
824 events = list(iterator)
825 self.assertEqual(8, len(events))
826
828 text = _str('Søk på nettet')
829 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
830 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
831 ).encode('iso-8859-1')
832
833 self.assertRaises(self.etree.ParseError,
834 list, self.etree.iterparse(BytesIO(xml_latin1)))
835
837 text = _str('Søk på nettet', encoding="UTF-8")
838 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
839 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
840 ).encode('iso-8859-1')
841
842 iterator = self.etree.iterparse(BytesIO(xml_latin1),
843 encoding="iso-8859-1")
844 self.assertEqual(1, len(list(iterator)))
845
846 a = iterator.root
847 self.assertEqual(a.text, text)
848
850 tostring = self.etree.tostring
851 f = BytesIO('<root><![CDATA[test]]></root>')
852 context = self.etree.iterparse(f, strip_cdata=False)
853 content = [ el.text for event,el in context ]
854
855 self.assertEqual(['test'], content)
856 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
857 tostring(context.root))
858
862
867
886
887
888
911
912
913
924 def end(self, tag):
925 events.append("end")
926 assertEqual("TAG", tag)
927 def close(self):
928 return "DONE"
929
930 parser = self.etree.XMLParser(target=Target())
931 tree = self.etree.ElementTree()
932
933 self.assertRaises(TypeError,
934 tree.parse, BytesIO("<TAG/>"), parser=parser)
935 self.assertEqual(["start", "end"], events)
936
938
939 events = []
940 class Target(object):
941 def start(self, tag, attrib):
942 events.append("start-" + tag)
943 def end(self, tag):
944 events.append("end-" + tag)
945 if tag == 'a':
946 raise ValueError("dead and gone")
947 def data(self, data):
948 events.append("data-" + data)
949 def close(self):
950 events.append("close")
951 return "DONE"
952
953 parser = self.etree.XMLParser(target=Target())
954
955 try:
956 parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
957 done = parser.close()
958 self.fail("error expected, but parsing succeeded")
959 except ValueError:
960 done = 'value error received as expected'
961
962 self.assertEqual(["start-root", "data-A", "start-a",
963 "data-ca", "end-a", "close"],
964 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 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
986 parser=parser)
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 def data(self, data):
1004 events.append("data-" + data)
1005 def comment(self, text):
1006 events.append("comment-" + text)
1007 def close(self):
1008 return "DONE"
1009
1010 parser = self.etree.XMLParser(target=Target(), collect_ids=False)
1011
1012 parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->'))
1013 parser.feed(_bytes('<sub xml:id="321"/>B</root>'))
1014 done = parser.close()
1015
1016 self.assertEqual("DONE", done)
1017 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1018 "start-sub", "end-sub", "data-B", "end-root"],
1019 events)
1020
1026 def end(self, tag):
1027 events.append("end-" + tag)
1028 def data(self, data):
1029 events.append("data-" + data)
1030 def comment(self, text):
1031 events.append("comment-" + text)
1032 def close(self):
1033 return "DONE"
1034
1035 parser = self.etree.XMLParser(target=Target())
1036
1037 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
1038 done = parser.close()
1039
1040 self.assertEqual("DONE", done)
1041 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1042 "start-sub", "end-sub", "comment-c", "data-B",
1043 "end-root", "comment-d"],
1044 events)
1045
1047 events = []
1048 class Target(object):
1049 def start(self, tag, attrib):
1050 events.append("start-" + tag)
1051 def end(self, tag):
1052 events.append("end-" + tag)
1053 def data(self, data):
1054 events.append("data-" + data)
1055 def pi(self, target, data):
1056 events.append("pi-" + target + "-" + data)
1057 def close(self):
1058 return "DONE"
1059
1060 parser = self.etree.XMLParser(target=Target())
1061
1062 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
1063 done = parser.close()
1064
1065 self.assertEqual("DONE", done)
1066 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b",
1067 "data-B", "end-root", "pi-test-c"],
1068 events)
1069
1071 events = []
1072 class Target(object):
1073 def start(self, tag, attrib):
1074 events.append("start-" + tag)
1075 def end(self, tag):
1076 events.append("end-" + tag)
1077 def data(self, data):
1078 events.append("data-" + data)
1079 def close(self):
1080 return "DONE"
1081
1082 parser = self.etree.XMLParser(target=Target(),
1083 strip_cdata=False)
1084
1085 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
1086 done = parser.close()
1087
1088 self.assertEqual("DONE", done)
1089 self.assertEqual(["start-root", "data-A", "start-a",
1090 "data-ca", "end-a", "data-B", "end-root"],
1091 events)
1092
1094 events = []
1095 class Target(object):
1096 def start(self, tag, attrib):
1097 events.append("start-" + tag)
1098 def end(self, tag):
1099 events.append("end-" + tag)
1100 def data(self, data):
1101 events.append("data-" + data)
1102 def close(self):
1103 events.append("close")
1104 return "DONE"
1105
1106 parser = self.etree.XMLParser(target=Target(),
1107 recover=True)
1108
1109 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
1110 done = parser.close()
1111
1112 self.assertEqual("DONE", done)
1113 self.assertEqual(["start-root", "data-A", "start-a",
1114 "data-ca", "end-a", "data-B",
1115 "end-root", "close"],
1116 events)
1117
1127
1137
1146
1156
1158 iterwalk = self.etree.iterwalk
1159 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1160
1161 iterator = iterwalk(root, events=('start','end'))
1162 events = list(iterator)
1163 self.assertEqual(
1164 [('start', root), ('start', root[0]), ('end', root[0]),
1165 ('start', root[1]), ('end', root[1]), ('end', root)],
1166 events)
1167
1178
1180 iterwalk = self.etree.iterwalk
1181 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
1182
1183 attr_name = '{testns}bla'
1184 events = []
1185 iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
1186 for event, elem in iterator:
1187 events.append(event)
1188 if event == 'start':
1189 if elem.tag != '{ns1}a':
1190 elem.set(attr_name, 'value')
1191
1192 self.assertEqual(
1193 ['start-ns', 'start', 'start', 'start-ns', 'start',
1194 'end', 'end-ns', 'end', 'end', 'end-ns'],
1195 events)
1196
1197 self.assertEqual(
1198 None,
1199 root.get(attr_name))
1200 self.assertEqual(
1201 'value',
1202 root[0].get(attr_name))
1203
1214
1216 parse = self.etree.parse
1217 parser = self.etree.XMLParser(dtd_validation=True)
1218 assertEqual = self.assertEqual
1219 test_url = _str("__nosuch.dtd")
1220
1221 class MyResolver(self.etree.Resolver):
1222 def resolve(self, url, id, context):
1223 assertEqual(url, test_url)
1224 return self.resolve_string(
1225 _str('''<!ENTITY myentity "%s">
1226 <!ELEMENT doc ANY>''') % url, context)
1227
1228 parser.resolvers.add(MyResolver())
1229
1230 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1231 tree = parse(StringIO(xml), parser)
1232 root = tree.getroot()
1233 self.assertEqual(root.text, test_url)
1234
1236 parse = self.etree.parse
1237 parser = self.etree.XMLParser(dtd_validation=True)
1238 assertEqual = self.assertEqual
1239 test_url = _str("__nosuch.dtd")
1240
1241 class MyResolver(self.etree.Resolver):
1242 def resolve(self, url, id, context):
1243 assertEqual(url, test_url)
1244 return self.resolve_string(
1245 (_str('''<!ENTITY myentity "%s">
1246 <!ELEMENT doc ANY>''') % url).encode('utf-8'),
1247 context)
1248
1249 parser.resolvers.add(MyResolver())
1250
1251 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1252 tree = parse(StringIO(xml), parser)
1253 root = tree.getroot()
1254 self.assertEqual(root.text, test_url)
1255
1257 parse = self.etree.parse
1258 parser = self.etree.XMLParser(dtd_validation=True)
1259 assertEqual = self.assertEqual
1260 test_url = _str("__nosuch.dtd")
1261
1262 class MyResolver(self.etree.Resolver):
1263 def resolve(self, url, id, context):
1264 assertEqual(url, test_url)
1265 return self.resolve_file(
1266 SillyFileLike(
1267 _str('''<!ENTITY myentity "%s">
1268 <!ELEMENT doc ANY>''') % url), context)
1269
1270 parser.resolvers.add(MyResolver())
1271
1272 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1273 tree = parse(StringIO(xml), parser)
1274 root = tree.getroot()
1275 self.assertEqual(root.text, test_url)
1276
1278 parse = self.etree.parse
1279 parser = self.etree.XMLParser(attribute_defaults=True)
1280 assertEqual = self.assertEqual
1281 test_url = _str("__nosuch.dtd")
1282
1283 class MyResolver(self.etree.Resolver):
1284 def resolve(self, url, id, context):
1285 assertEqual(url, test_url)
1286 return self.resolve_filename(
1287 fileInTestDir('test.dtd'), context)
1288
1289 parser.resolvers.add(MyResolver())
1290
1291 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1292 tree = parse(StringIO(xml), parser)
1293 root = tree.getroot()
1294 self.assertEqual(
1295 root.attrib, {'default': 'valueA'})
1296 self.assertEqual(
1297 root[0].attrib, {'default': 'valueB'})
1298
1313
1314 parser.resolvers.add(MyResolver())
1315
1316 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1317 tree = parse(StringIO(xml), parser,
1318 base_url=fileUrlInTestDir('__test.xml'))
1319 root = tree.getroot()
1320 self.assertEqual(
1321 root.attrib, {'default': 'valueA'})
1322 self.assertEqual(
1323 root[0].attrib, {'default': 'valueB'})
1324
1326 parse = self.etree.parse
1327 parser = self.etree.XMLParser(attribute_defaults=True)
1328 assertEqual = self.assertEqual
1329 test_url = _str("__nosuch.dtd")
1330
1331 class MyResolver(self.etree.Resolver):
1332 def resolve(self, url, id, context):
1333 assertEqual(url, test_url)
1334 return self.resolve_file(
1335 open(fileInTestDir('test.dtd'), 'rb'), context)
1336
1337 parser.resolvers.add(MyResolver())
1338
1339 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1340 tree = parse(StringIO(xml), parser)
1341 root = tree.getroot()
1342 self.assertEqual(
1343 root.attrib, {'default': 'valueA'})
1344 self.assertEqual(
1345 root[0].attrib, {'default': 'valueB'})
1346
1348 parse = self.etree.parse
1349 parser = self.etree.XMLParser(load_dtd=True)
1350 assertEqual = self.assertEqual
1351 test_url = _str("__nosuch.dtd")
1352
1353 class check(object):
1354 resolved = False
1355
1356 class MyResolver(self.etree.Resolver):
1357 def resolve(self, url, id, context):
1358 assertEqual(url, test_url)
1359 check.resolved = True
1360 return self.resolve_empty(context)
1361
1362 parser.resolvers.add(MyResolver())
1363
1364 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1365 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
1366 self.assertTrue(check.resolved)
1367
1374
1375 class MyResolver(self.etree.Resolver):
1376 def resolve(self, url, id, context):
1377 raise _LocalException
1378
1379 parser.resolvers.add(MyResolver())
1380
1381 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
1382 self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
1383
1384 if etree.LIBXML_VERSION > (2,6,20):
1401
1403 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]>
1404 <root>
1405 <child1/>
1406 <child2/>
1407 <child3> </child3>
1408 </root>''')
1409
1410 parser = self.etree.XMLParser(resolve_entities=False)
1411 root = etree.fromstring(xml, parser)
1412 self.assertEqual([ el.tag for el in root ],
1413 ['child1', 'child2', 'child3'])
1414
1415 root[0] = root[-1]
1416 self.assertEqual([ el.tag for el in root ],
1417 ['child3', 'child2'])
1418 self.assertEqual(root[0][0].text, ' ')
1419 self.assertEqual(root[0][0].name, 'nbsp')
1420
1436
1443
1445 Entity = self.etree.Entity
1446 self.assertRaises(ValueError, Entity, 'a b c')
1447 self.assertRaises(ValueError, Entity, 'a,b')
1448 self.assertRaises(ValueError, Entity, 'a\0b')
1449 self.assertRaises(ValueError, Entity, '#abc')
1450 self.assertRaises(ValueError, Entity, '#xxyz')
1451
1464
1485
1498
1510
1519
1528
1529
1539
1548
1550 Element = self.etree.Element
1551 SubElement = self.etree.SubElement
1552 root = Element('root')
1553 self.assertRaises(ValueError, root.append, root)
1554 child = SubElement(root, 'child')
1555 self.assertRaises(ValueError, child.append, root)
1556 child2 = SubElement(child, 'child2')
1557 self.assertRaises(ValueError, child2.append, root)
1558 self.assertRaises(ValueError, child2.append, child)
1559 self.assertEqual('child2', root[0][0].tag)
1560
1573
1586
1597
1608
1618
1628
1644
1660
1666
1681
1694
1709
1722
1737
1750
1765
1778
1779
1787
1788
1798
1799
1814
1815
1825
1826
1837
1864
1865
1867 self.assertRaises(TypeError, self.etree.dump, None)
1868
1881
1894
1915
1924
1933
1942
1951
1960
1962 XML = self.etree.XML
1963
1964 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
1965 result = []
1966 for el in root.iterchildren(tag=['two', 'three']):
1967 result.append(el.text)
1968 self.assertEqual(['Two', 'Bla', None], result)
1969
1971 XML = self.etree.XML
1972
1973 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
1974 result = []
1975 for el in root.iterchildren('two', 'three'):
1976 result.append(el.text)
1977 self.assertEqual(['Two', 'Bla', None], result)
1978
1987
2008
2030
2032 Element = self.etree.Element
2033 SubElement = self.etree.SubElement
2034
2035 a = Element('a')
2036 b = SubElement(a, 'b')
2037 c = SubElement(a, 'c')
2038 d = SubElement(b, 'd')
2039 self.assertEqual(
2040 [b, a],
2041 list(d.iterancestors(tag=('a', 'b'))))
2042 self.assertEqual(
2043 [b, a],
2044 list(d.iterancestors('a', 'b')))
2045
2046 self.assertEqual(
2047 [],
2048 list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
2049 self.assertEqual(
2050 [],
2051 list(d.iterancestors('w', 'x', 'y', 'z')))
2052
2053 self.assertEqual(
2054 [],
2055 list(d.iterancestors(tag=('d', 'x'))))
2056 self.assertEqual(
2057 [],
2058 list(d.iterancestors('d', 'x')))
2059
2060 self.assertEqual(
2061 [b, a],
2062 list(d.iterancestors(tag=('b', '*'))))
2063 self.assertEqual(
2064 [b, a],
2065 list(d.iterancestors('b', '*')))
2066
2067 self.assertEqual(
2068 [b],
2069 list(d.iterancestors(tag=('b', 'c'))))
2070 self.assertEqual(
2071 [b],
2072 list(d.iterancestors('b', 'c')))
2073
2090
2092 Element = self.etree.Element
2093 SubElement = self.etree.SubElement
2094
2095 a = Element('a')
2096 b = SubElement(a, 'b')
2097 c = SubElement(a, 'c')
2098 d = SubElement(b, 'd')
2099 e = SubElement(c, 'e')
2100
2101 self.assertEqual(
2102 [],
2103 list(a.iterdescendants('a')))
2104 self.assertEqual(
2105 [],
2106 list(a.iterdescendants(tag='a')))
2107
2108 a2 = SubElement(e, 'a')
2109 self.assertEqual(
2110 [a2],
2111 list(a.iterdescendants('a')))
2112
2113 self.assertEqual(
2114 [a2],
2115 list(c.iterdescendants('a')))
2116 self.assertEqual(
2117 [a2],
2118 list(c.iterdescendants(tag='a')))
2119
2121 Element = self.etree.Element
2122 SubElement = self.etree.SubElement
2123
2124 a = Element('a')
2125 b = SubElement(a, 'b')
2126 c = SubElement(a, 'c')
2127 d = SubElement(b, 'd')
2128 e = SubElement(c, 'e')
2129
2130 self.assertEqual(
2131 [b, e],
2132 list(a.iterdescendants(tag=('a', 'b', 'e'))))
2133 self.assertEqual(
2134 [b, e],
2135 list(a.iterdescendants('a', 'b', 'e')))
2136
2137 a2 = SubElement(e, 'a')
2138 self.assertEqual(
2139 [b, a2],
2140 list(a.iterdescendants(tag=('a', 'b'))))
2141 self.assertEqual(
2142 [b, a2],
2143 list(a.iterdescendants('a', 'b')))
2144
2145 self.assertEqual(
2146 [],
2147 list(c.iterdescendants(tag=('x', 'y', 'z'))))
2148 self.assertEqual(
2149 [],
2150 list(c.iterdescendants('x', 'y', 'z')))
2151
2152 self.assertEqual(
2153 [b, d, c, e, a2],
2154 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
2155 self.assertEqual(
2156 [b, d, c, e, a2],
2157 list(a.iterdescendants('x', 'y', 'z', '*')))
2158
2176
2193
2211
2235
2237 Element = self.etree.Element
2238 SubElement = self.etree.SubElement
2239
2240 a = Element('a')
2241 b = SubElement(a, 'b')
2242 c = SubElement(a, 'c')
2243 d = SubElement(b, 'd')
2244 self.assertEqual(
2245 [],
2246 list(a.itersiblings(tag='XXX')))
2247 self.assertEqual(
2248 [c],
2249 list(b.itersiblings(tag='c')))
2250 self.assertEqual(
2251 [c],
2252 list(b.itersiblings(tag='*')))
2253 self.assertEqual(
2254 [b],
2255 list(c.itersiblings(preceding=True, tag='b')))
2256 self.assertEqual(
2257 [],
2258 list(c.itersiblings(preceding=True, tag='c')))
2259
2261 Element = self.etree.Element
2262 SubElement = self.etree.SubElement
2263
2264 a = Element('a')
2265 b = SubElement(a, 'b')
2266 c = SubElement(a, 'c')
2267 d = SubElement(b, 'd')
2268 e = SubElement(a, 'e')
2269 self.assertEqual(
2270 [],
2271 list(a.itersiblings(tag=('XXX', 'YYY'))))
2272 self.assertEqual(
2273 [c, e],
2274 list(b.itersiblings(tag=('c', 'd', 'e'))))
2275 self.assertEqual(
2276 [b],
2277 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
2278 self.assertEqual(
2279 [c, b],
2280 list(e.itersiblings(preceding=True, tag=('c', '*'))))
2281
2283 parseid = self.etree.parseid
2284 XML = self.etree.XML
2285 xml_text = _bytes('''
2286 <!DOCTYPE document [
2287 <!ELEMENT document (h1,p)*>
2288 <!ELEMENT h1 (#PCDATA)>
2289 <!ATTLIST h1 myid ID #REQUIRED>
2290 <!ELEMENT p (#PCDATA)>
2291 <!ATTLIST p someid ID #REQUIRED>
2292 ]>
2293 <document>
2294 <h1 myid="chapter1">...</h1>
2295 <p id="note1" class="note">...</p>
2296 <p>Regular paragraph.</p>
2297 <p xml:id="xmlid">XML:ID paragraph.</p>
2298 <p someid="warn1" class="warning">...</p>
2299 </document>
2300 ''')
2301
2302 tree, dic = parseid(BytesIO(xml_text))
2303 root = tree.getroot()
2304 root2 = XML(xml_text)
2305 self.assertEqual(self._writeElement(root),
2306 self._writeElement(root2))
2307 expected = {
2308 "chapter1" : root[0],
2309 "xmlid" : root[3],
2310 "warn1" : root[4]
2311 }
2312 self.assertTrue("chapter1" in dic)
2313 self.assertTrue("warn1" in dic)
2314 self.assertTrue("xmlid" in dic)
2315 self._checkIDDict(dic, expected)
2316
2318 XMLDTDID = self.etree.XMLDTDID
2319 XML = self.etree.XML
2320 xml_text = _bytes('''
2321 <!DOCTYPE document [
2322 <!ELEMENT document (h1,p)*>
2323 <!ELEMENT h1 (#PCDATA)>
2324 <!ATTLIST h1 myid ID #REQUIRED>
2325 <!ELEMENT p (#PCDATA)>
2326 <!ATTLIST p someid ID #REQUIRED>
2327 ]>
2328 <document>
2329 <h1 myid="chapter1">...</h1>
2330 <p id="note1" class="note">...</p>
2331 <p>Regular paragraph.</p>
2332 <p xml:id="xmlid">XML:ID paragraph.</p>
2333 <p someid="warn1" class="warning">...</p>
2334 </document>
2335 ''')
2336
2337 root, dic = XMLDTDID(xml_text)
2338 root2 = XML(xml_text)
2339 self.assertEqual(self._writeElement(root),
2340 self._writeElement(root2))
2341 expected = {
2342 "chapter1" : root[0],
2343 "xmlid" : root[3],
2344 "warn1" : root[4]
2345 }
2346 self.assertTrue("chapter1" in dic)
2347 self.assertTrue("warn1" in dic)
2348 self.assertTrue("xmlid" in dic)
2349 self._checkIDDict(dic, expected)
2350
2352 XMLDTDID = self.etree.XMLDTDID
2353 XML = self.etree.XML
2354 xml_text = _bytes('''
2355 <document>
2356 <h1 myid="chapter1">...</h1>
2357 <p id="note1" class="note">...</p>
2358 <p>Regular paragraph.</p>
2359 <p someid="warn1" class="warning">...</p>
2360 </document>
2361 ''')
2362
2363 root, dic = XMLDTDID(xml_text)
2364 root2 = XML(xml_text)
2365 self.assertEqual(self._writeElement(root),
2366 self._writeElement(root2))
2367 expected = {}
2368 self._checkIDDict(dic, expected)
2369
2371 XMLDTDID = self.etree.XMLDTDID
2372 XML = self.etree.XML
2373 xml_text = _bytes('''
2374 <!DOCTYPE document [
2375 <!ELEMENT document (h1,p)*>
2376 <!ELEMENT h1 (#PCDATA)>
2377 <!ATTLIST h1 myid ID #REQUIRED>
2378 <!ELEMENT p (#PCDATA)>
2379 <!ATTLIST p someid ID #REQUIRED>
2380 ]>
2381 <document>
2382 <h1 myid="chapter1">...</h1>
2383 <p id="note1" class="note">...</p>
2384 <p>Regular paragraph.</p>
2385 <p xml:id="xmlid">XML:ID paragraph.</p>
2386 <p someid="warn1" class="warning">...</p>
2387 </document>
2388 ''')
2389
2390 parser = etree.XMLParser(collect_ids=False)
2391 root, dic = XMLDTDID(xml_text, parser=parser)
2392 root2 = XML(xml_text)
2393 self.assertEqual(self._writeElement(root),
2394 self._writeElement(root2))
2395 self.assertFalse(dic)
2396 self._checkIDDict(dic, {})
2397
2399 self.assertEqual(len(dic),
2400 len(expected))
2401 self.assertEqual(sorted(dic.items()),
2402 sorted(expected.items()))
2403 if sys.version_info < (3,):
2404 self.assertEqual(sorted(dic.iteritems()),
2405 sorted(expected.iteritems()))
2406 self.assertEqual(sorted(dic.keys()),
2407 sorted(expected.keys()))
2408 if sys.version_info < (3,):
2409 self.assertEqual(sorted(dic.iterkeys()),
2410 sorted(expected.iterkeys()))
2411 if sys.version_info < (3,):
2412 self.assertEqual(sorted(dic.values()),
2413 sorted(expected.values()))
2414 self.assertEqual(sorted(dic.itervalues()),
2415 sorted(expected.itervalues()))
2416
2418 etree = self.etree
2419
2420 r = {'foo': 'http://ns.infrae.com/foo'}
2421 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2422 self.assertEqual(
2423 'foo',
2424 e.prefix)
2425 self.assertEqual(
2426 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
2427 self._writeElement(e))
2428
2430 etree = self.etree
2431
2432 r = {None: 'http://ns.infrae.com/foo'}
2433 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2434 self.assertEqual(
2435 None,
2436 e.prefix)
2437 self.assertEqual(
2438 '{http://ns.infrae.com/foo}bar',
2439 e.tag)
2440 self.assertEqual(
2441 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
2442 self._writeElement(e))
2443
2445 etree = self.etree
2446
2447 r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'}
2448 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2449 self.assertEqual(None, e.prefix)
2450 self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag)
2451 self.assertEqual(
2452 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'),
2453 self._writeElement(e))
2454
2456 etree = self.etree
2457
2458 r = {None: 'http://ns.infrae.com/foo',
2459 'hoi': 'http://ns.infrae.com/hoi'}
2460 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2461 e.set('{http://ns.infrae.com/hoi}test', 'value')
2462 self.assertEqual(
2463 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
2464 self._writeElement(e))
2465
2467 etree = self.etree
2468
2469 root = etree.Element('{http://test/ns}root',
2470 nsmap={None: 'http://test/ns'})
2471 sub = etree.Element('{http://test/ns}sub',
2472 nsmap={'test': 'http://test/ns'})
2473
2474 sub.attrib['{http://test/ns}attr'] = 'value'
2475 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2476 self.assertEqual(
2477 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2478 etree.tostring(sub))
2479
2480 root.append(sub)
2481 self.assertEqual(
2482 _bytes('<root xmlns="http://test/ns">'
2483 '<sub xmlns:test="http://test/ns" test:attr="value"/>'
2484 '</root>'),
2485 etree.tostring(root))
2486
2488 etree = self.etree
2489
2490 root = etree.Element('root')
2491 sub = etree.Element('{http://test/ns}sub',
2492 nsmap={'test': 'http://test/ns'})
2493
2494 sub.attrib['{http://test/ns}attr'] = 'value'
2495 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2496 self.assertEqual(
2497 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2498 etree.tostring(sub))
2499
2500 root.append(sub)
2501 self.assertEqual(
2502 _bytes('<root>'
2503 '<test:sub xmlns:test="http://test/ns" test:attr="value"/>'
2504 '</root>'),
2505 etree.tostring(root))
2506
2508 etree = self.etree
2509
2510 root = etree.Element('root')
2511 sub = etree.Element('{http://test/ns}sub',
2512 nsmap={None: 'http://test/ns'})
2513
2514 sub.attrib['{http://test/ns}attr'] = 'value'
2515 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2516 self.assertEqual(
2517 _bytes('<sub xmlns="http://test/ns" '
2518 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2519 etree.tostring(sub))
2520
2521 root.append(sub)
2522 self.assertEqual(
2523 _bytes('<root>'
2524 '<sub xmlns="http://test/ns"'
2525 ' xmlns:ns0="http://test/ns" ns0:attr="value"/>'
2526 '</root>'),
2527 etree.tostring(root))
2528
2530 etree = self.etree
2531
2532 root = etree.Element('{http://test/ns}root',
2533 nsmap={'test': 'http://test/ns',
2534 None: 'http://test/ns'})
2535 sub = etree.Element('{http://test/ns}sub',
2536 nsmap={None: 'http://test/ns'})
2537
2538 sub.attrib['{http://test/ns}attr'] = 'value'
2539 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2540 self.assertEqual(
2541 _bytes('<sub xmlns="http://test/ns" '
2542 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2543 etree.tostring(sub))
2544
2545 root.append(sub)
2546 self.assertEqual(
2547 _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">'
2548 '<test:sub test:attr="value"/>'
2549 '</test:root>'),
2550 etree.tostring(root))
2551
2553 etree = self.etree
2554 r = {None: 'http://ns.infrae.com/foo',
2555 'hoi': 'http://ns.infrae.com/hoi'}
2556 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
2557 tree = etree.ElementTree(element=e)
2558 etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
2559 self.assertEqual(
2560 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
2561 self._writeElement(e))
2562
2564 etree = self.etree
2565
2566 r = {None: 'http://ns.infrae.com/foo'}
2567 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2568 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2569
2570 e1.append(e2)
2571
2572 self.assertEqual(
2573 None,
2574 e1.prefix)
2575 self.assertEqual(
2576 None,
2577 e1[0].prefix)
2578 self.assertEqual(
2579 '{http://ns.infrae.com/foo}bar',
2580 e1.tag)
2581 self.assertEqual(
2582 '{http://ns.infrae.com/foo}bar',
2583 e1[0].tag)
2584
2586 etree = self.etree
2587
2588 r = {None: 'http://ns.infrae.com/BAR'}
2589 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
2590 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2591
2592 e1.append(e2)
2593
2594 self.assertEqual(
2595 None,
2596 e1.prefix)
2597 self.assertNotEqual(
2598 None,
2599 e2.prefix)
2600 self.assertEqual(
2601 '{http://ns.infrae.com/BAR}bar',
2602 e1.tag)
2603 self.assertEqual(
2604 '{http://ns.infrae.com/foo}bar',
2605 e2.tag)
2606
2608 ns_href = "http://a.b.c"
2609 one = self.etree.fromstring(
2610 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2611 baz = one[0][0]
2612
2613 two = self.etree.fromstring(
2614 _bytes('<root xmlns:ns="%s"/>' % ns_href))
2615 two.append(baz)
2616 del one
2617
2618 self.assertEqual('{%s}baz' % ns_href, baz.tag)
2619 self.assertEqual(
2620 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
2621 self.etree.tostring(two))
2622
2636
2653
2664
2666 xml = ('<root>' +
2667 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2668 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8')
2669 root = self.etree.fromstring(xml)
2670 self.assertEqual(xml, self.etree.tostring(root))
2671 self.etree.cleanup_namespaces(root)
2672 self.assertEqual(
2673 b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 +
2674 b'<n64:x/>' + b'</a>'*100 + b'</root>',
2675 self.etree.tostring(root))
2676
2678 xml = ('<root>' +
2679 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2680 '<n64:x xmlns:a="A" a:attr="X"/>' +
2681 '</a>'*100 +
2682 '</root>').encode('utf8')
2683 root = self.etree.fromstring(xml)
2684 self.assertEqual(xml, self.etree.tostring(root))
2685 self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'})
2686 self.assertEqual(
2687 b'<root xmlns:n64="NS64">' + b'<a>'*100 +
2688 b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>',
2689 self.etree.tostring(root))
2690
2692 xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">'
2693 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2694 '<foo>foo:bar</foo>'
2695 '</root>').encode('utf8')
2696 root = self.etree.fromstring(xml)
2697 self.assertEqual(xml, self.etree.tostring(root))
2698 self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo'])
2699 self.assertEqual(
2700 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2701 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2702 b'<foo>foo:bar</foo>'
2703 b'</root>',
2704 self.etree.tostring(root))
2705
2707 xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">'
2708 '<sub xmlns:foo="FOO">'
2709 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2710 '<foo>foo:bar</foo>'
2711 '</sub>'
2712 '</root>').encode('utf8')
2713 root = self.etree.fromstring(xml)
2714 self.assertEqual(xml, self.etree.tostring(root))
2715 self.etree.cleanup_namespaces(
2716 root,
2717 top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'},
2718 keep_ns_prefixes=['foo'])
2719 self.assertEqual(
2720 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2721 b'<sub>'
2722 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2723 b'<foo>foo:bar</foo>'
2724 b'</sub>'
2725 b'</root>',
2726 self.etree.tostring(root))
2727
2729 etree = self.etree
2730
2731 r = {None: 'http://ns.infrae.com/foo',
2732 'hoi': 'http://ns.infrae.com/hoi'}
2733 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2734 self.assertEqual(
2735 r,
2736 e.nsmap)
2737
2739 etree = self.etree
2740
2741 re = {None: 'http://ns.infrae.com/foo',
2742 'hoi': 'http://ns.infrae.com/hoi'}
2743 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
2744
2745 rs = {None: 'http://ns.infrae.com/honk',
2746 'top': 'http://ns.infrae.com/top'}
2747 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
2748
2749 r = re.copy()
2750 r.update(rs)
2751 self.assertEqual(re, e.nsmap)
2752 self.assertEqual(r, s.nsmap)
2753
2755 etree = self.etree
2756 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
2757 self.assertEqual({'hha': None}, el.nsmap)
2758
2760 Element = self.etree.Element
2761 SubElement = self.etree.SubElement
2762
2763 a = Element('a')
2764 b = SubElement(a, 'b')
2765 c = SubElement(a, 'c')
2766 d = SubElement(b, 'd')
2767 e = SubElement(c, 'e')
2768 f = SubElement(c, 'f')
2769
2770 self.assertEqual(
2771 [a, b],
2772 list(a.getiterator('a', 'b')))
2773 self.assertEqual(
2774 [],
2775 list(a.getiterator('x', 'y')))
2776 self.assertEqual(
2777 [a, f],
2778 list(a.getiterator('f', 'a')))
2779 self.assertEqual(
2780 [c, e, f],
2781 list(c.getiterator('c', '*', 'a')))
2782 self.assertEqual(
2783 [],
2784 list(a.getiterator( (), () )))
2785
2787 Element = self.etree.Element
2788 SubElement = self.etree.SubElement
2789
2790 a = Element('a')
2791 b = SubElement(a, 'b')
2792 c = SubElement(a, 'c')
2793 d = SubElement(b, 'd')
2794 e = SubElement(c, 'e')
2795 f = SubElement(c, 'f')
2796
2797 self.assertEqual(
2798 [a, b],
2799 list(a.getiterator( ('a', 'b') )))
2800 self.assertEqual(
2801 [],
2802 list(a.getiterator( ('x', 'y') )))
2803 self.assertEqual(
2804 [a, f],
2805 list(a.getiterator( ('f', 'a') )))
2806 self.assertEqual(
2807 [c, e, f],
2808 list(c.getiterator( ('c', '*', 'a') )))
2809 self.assertEqual(
2810 [],
2811 list(a.getiterator( () )))
2812
2814 Element = self.etree.Element
2815 SubElement = self.etree.SubElement
2816
2817 a = Element('{a}a')
2818 b = SubElement(a, '{a}b')
2819 c = SubElement(a, '{a}c')
2820 d = SubElement(b, '{b}d')
2821 e = SubElement(c, '{a}e')
2822 f = SubElement(c, '{b}f')
2823 g = SubElement(c, 'g')
2824
2825 self.assertEqual(
2826 [a],
2827 list(a.getiterator('{a}a')))
2828 self.assertEqual(
2829 [],
2830 list(a.getiterator('{b}a')))
2831 self.assertEqual(
2832 [],
2833 list(a.getiterator('a')))
2834 self.assertEqual(
2835 [a,b,d,c,e,f,g],
2836 list(a.getiterator('*')))
2837 self.assertEqual(
2838 [f],
2839 list(c.getiterator('{b}*')))
2840 self.assertEqual(
2841 [d, f],
2842 list(a.getiterator('{b}*')))
2843 self.assertEqual(
2844 [g],
2845 list(a.getiterator('g')))
2846 self.assertEqual(
2847 [g],
2848 list(a.getiterator('{}g')))
2849 self.assertEqual(
2850 [g],
2851 list(a.getiterator('{}*')))
2852
2854 Element = self.etree.Element
2855 SubElement = self.etree.SubElement
2856
2857 a = Element('{a}a')
2858 b = SubElement(a, '{nsA}b')
2859 c = SubElement(b, '{nsB}b')
2860 d = SubElement(a, 'b')
2861 e = SubElement(a, '{nsA}e')
2862 f = SubElement(e, '{nsB}e')
2863 g = SubElement(e, 'e')
2864
2865 self.assertEqual(
2866 [b, c, d],
2867 list(a.getiterator('{*}b')))
2868 self.assertEqual(
2869 [e, f, g],
2870 list(a.getiterator('{*}e')))
2871 self.assertEqual(
2872 [a, b, c, d, e, f, g],
2873 list(a.getiterator('{*}*')))
2874
2899
2915
2932
2934 a = etree.Element("a")
2935 b = etree.SubElement(a, "b")
2936 c = etree.SubElement(a, "c")
2937 d1 = etree.SubElement(c, "d")
2938 d2 = etree.SubElement(c, "d")
2939 c.text = d1.text = 'TEXT'
2940
2941 tree = etree.ElementTree(a)
2942 self.assertEqual('.', tree.getelementpath(a))
2943 self.assertEqual('c/d[1]', tree.getelementpath(d1))
2944 self.assertEqual('c/d[2]', tree.getelementpath(d2))
2945
2946 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
2947 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
2948
2949 tree = etree.ElementTree(c)
2950 self.assertEqual('.', tree.getelementpath(c))
2951 self.assertEqual('d[2]', tree.getelementpath(d2))
2952 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
2953
2954 tree = etree.ElementTree(b)
2955 self.assertEqual('.', tree.getelementpath(b))
2956 self.assertRaises(ValueError, tree.getelementpath, a)
2957 self.assertRaises(ValueError, tree.getelementpath, c)
2958 self.assertRaises(ValueError, tree.getelementpath, d2)
2959
2961 a = etree.Element("{http://ns1/}a")
2962 b = etree.SubElement(a, "{http://ns1/}b")
2963 c = etree.SubElement(a, "{http://ns1/}c")
2964 d1 = etree.SubElement(c, "{http://ns1/}d")
2965 d2 = etree.SubElement(c, "{http://ns2/}d")
2966 d3 = etree.SubElement(c, "{http://ns1/}d")
2967
2968 tree = etree.ElementTree(a)
2969 self.assertEqual('.', tree.getelementpath(a))
2970 self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]',
2971 tree.getelementpath(d1))
2972 self.assertEqual('{http://ns1/}c/{http://ns2/}d',
2973 tree.getelementpath(d2))
2974 self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]',
2975 tree.getelementpath(d3))
2976
2977 self.assertEqual(a, tree.find(tree.getelementpath(a)))
2978 self.assertEqual(b, tree.find(tree.getelementpath(b)))
2979 self.assertEqual(c, tree.find(tree.getelementpath(c)))
2980 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
2981 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
2982 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
2983
2984 tree = etree.ElementTree(c)
2985 self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1))
2986 self.assertEqual('{http://ns2/}d', tree.getelementpath(d2))
2987 self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3))
2988 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
2989 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
2990 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
2991
2992 tree = etree.ElementTree(b)
2993 self.assertRaises(ValueError, tree.getelementpath, d1)
2994 self.assertRaises(ValueError, tree.getelementpath, d2)
2995
3002
3009
3018
3020 XML = self.etree.XML
3021 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
3022 self.assertEqual(len(root.findall(".//{X}b")), 2)
3023 self.assertEqual(len(root.findall(".//{X}*")), 2)
3024 self.assertEqual(len(root.findall(".//b")), 3)
3025
3027 XML = self.etree.XML
3028 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3029 nsmap = {'xx': 'X'}
3030 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3031 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
3032 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3033 nsmap = {'xx': 'Y'}
3034 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
3035 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
3036 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3037
3039 XML = self.etree.XML
3040 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3041 nsmap = {'xx': 'X'}
3042 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3043 nsmap = {'xx': 'X', None: 'Y'}
3044 self.assertRaises(ValueError, root.findall, ".//xx:b", namespaces=nsmap)
3045 nsmap = {'xx': 'X', '': 'Y'}
3046 self.assertRaises(ValueError, root.findall, ".//xx:b", namespaces=nsmap)
3047
3054
3056 etree = self.etree
3057 e = etree.Element('foo')
3058 for i in range(10):
3059 etree.SubElement(e, 'a%s' % i)
3060 for i in range(10):
3061 self.assertEqual(
3062 i,
3063 e.index(e[i]))
3064 self.assertEqual(
3065 3, e.index(e[3], 3))
3066 self.assertRaises(
3067 ValueError, e.index, e[3], 4)
3068 self.assertRaises(
3069 ValueError, e.index, e[3], 0, 2)
3070 self.assertRaises(
3071 ValueError, e.index, e[8], 0, -3)
3072 self.assertRaises(
3073 ValueError, e.index, e[8], -5, -3)
3074 self.assertEqual(
3075 8, e.index(e[8], 0, -1))
3076 self.assertEqual(
3077 8, e.index(e[8], -12, -1))
3078 self.assertEqual(
3079 0, e.index(e[0], -12, -1))
3080
3082 etree = self.etree
3083 e = etree.Element('foo')
3084 for i in range(10):
3085 el = etree.SubElement(e, 'a%s' % i)
3086 el.text = "text%d" % i
3087 el.tail = "tail%d" % i
3088
3089 child0 = e[0]
3090 child1 = e[1]
3091 child2 = e[2]
3092
3093 e.replace(e[0], e[1])
3094 self.assertEqual(
3095 9, len(e))
3096 self.assertEqual(
3097 child1, e[0])
3098 self.assertEqual(
3099 child1.text, "text1")
3100 self.assertEqual(
3101 child1.tail, "tail1")
3102 self.assertEqual(
3103 child0.tail, "tail0")
3104 self.assertEqual(
3105 child2, e[1])
3106
3107 e.replace(e[-1], e[0])
3108 self.assertEqual(
3109 child1, e[-1])
3110 self.assertEqual(
3111 child1.text, "text1")
3112 self.assertEqual(
3113 child1.tail, "tail1")
3114 self.assertEqual(
3115 child2, e[0])
3116
3118 etree = self.etree
3119 e = etree.Element('foo')
3120 for i in range(10):
3121 etree.SubElement(e, 'a%s' % i)
3122
3123 new_element = etree.Element("test")
3124 new_element.text = "TESTTEXT"
3125 new_element.tail = "TESTTAIL"
3126 child1 = e[1]
3127 e.replace(e[0], new_element)
3128 self.assertEqual(
3129 new_element, e[0])
3130 self.assertEqual(
3131 "TESTTEXT",
3132 e[0].text)
3133 self.assertEqual(
3134 "TESTTAIL",
3135 e[0].tail)
3136 self.assertEqual(
3137 child1, e[1])
3138
3154
3172
3190
3208
3210 Element = self.etree.Element
3211 SubElement = self.etree.SubElement
3212 try:
3213 slice
3214 except NameError:
3215 print("slice() not found")
3216 return
3217
3218 a = Element('a')
3219 b = SubElement(a, 'b')
3220 c = SubElement(a, 'c')
3221 d = SubElement(a, 'd')
3222 e = SubElement(a, 'e')
3223
3224 x = Element('x')
3225 y = Element('y')
3226 z = Element('z')
3227
3228 self.assertRaises(
3229 ValueError,
3230 operator.setitem, a, slice(1,None,2), [x, y, z])
3231
3232 self.assertEqual(
3233 [b, c, d, e],
3234 list(a))
3235
3248
3250 XML = self.etree.XML
3251 root = XML(_bytes(
3252 '<?xml version="1.0"?>\n'
3253 '<root>' + '\n' * 65536 +
3254 '<p>' + '\n' * 65536 + '</p>\n' +
3255 '<br/>\n'
3256 '</root>'))
3257
3258 if self.etree.LIBXML_VERSION >= (2, 9):
3259 expected = [2, 131074, 131076]
3260 else:
3261 expected = [2, 65535, 65535]
3262
3263 self.assertEqual(expected, [el.sourceline for el in root.iter()])
3264
3272
3281
3291
3301
3307
3315
3321
3328
3334
3336 etree = self.etree
3337 xml_header = '<?xml version="1.0" encoding="ascii"?>'
3338 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3339 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3340 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
3341
3342 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
3343
3344 tree = etree.parse(BytesIO(xml))
3345 docinfo = tree.docinfo
3346 self.assertEqual(docinfo.encoding, "ascii")
3347 self.assertEqual(docinfo.xml_version, "1.0")
3348 self.assertEqual(docinfo.public_id, pub_id)
3349 self.assertEqual(docinfo.system_url, sys_id)
3350 self.assertEqual(docinfo.root_name, 'html')
3351 self.assertEqual(docinfo.doctype, doctype_string)
3352
3368
3380
3392
3398
3400 etree = self.etree
3401 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3402 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3403 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
3404
3405 xml = _bytes('<!DOCTYPE root>\n<root/>')
3406 tree = etree.parse(BytesIO(xml))
3407 self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
3408 etree.tostring(tree, doctype=doctype_string))
3409
3411 etree = self.etree
3412 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3413 self.assertEqual(root.base, "http://no/such/url")
3414 self.assertEqual(
3415 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3416 root.base = "https://secret/url"
3417 self.assertEqual(root.base, "https://secret/url")
3418 self.assertEqual(
3419 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3420 "https://secret/url")
3421
3423 etree = self.etree
3424 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3425 self.assertEqual(root.base, "http://no/such/url")
3426 self.assertEqual(
3427 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3428 root.set('{http://www.w3.org/XML/1998/namespace}base',
3429 "https://secret/url")
3430 self.assertEqual(root.base, "https://secret/url")
3431 self.assertEqual(
3432 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3433 "https://secret/url")
3434
3440
3445
3452
3466
3468 Element = self.etree.Element
3469
3470 a = Element('a')
3471 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
3472 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
3473
3474 self.assertRaises(ValueError, Element, 'ha\0ho')
3475
3477 Element = self.etree.Element
3478
3479 a = Element('a')
3480 self.assertRaises(ValueError, setattr, a, "text",
3481 _str('ha\0ho'))
3482 self.assertRaises(ValueError, setattr, a, "tail",
3483 _str('ha\0ho'))
3484
3485 self.assertRaises(ValueError, Element,
3486 _str('ha\0ho'))
3487
3489 Element = self.etree.Element
3490
3491 a = Element('a')
3492 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
3493 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
3494
3495 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
3496 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
3497
3498 self.assertRaises(ValueError, Element, 'ha\x07ho')
3499 self.assertRaises(ValueError, Element, 'ha\x02ho')
3500
3502 Element = self.etree.Element
3503
3504 a = Element('a')
3505 self.assertRaises(ValueError, setattr, a, "text",
3506 _str('ha\x07ho'))
3507 self.assertRaises(ValueError, setattr, a, "text",
3508 _str('ha\x02ho'))
3509
3510 self.assertRaises(ValueError, setattr, a, "tail",
3511 _str('ha\x07ho'))
3512 self.assertRaises(ValueError, setattr, a, "tail",
3513 _str('ha\x02ho'))
3514
3515 self.assertRaises(ValueError, Element,
3516 _str('ha\x07ho'))
3517 self.assertRaises(ValueError, Element,
3518 _str('ha\x02ho'))
3519
3521 Element = self.etree.Element
3522
3523 a = Element('a')
3524 self.assertRaises(ValueError, setattr, a, "text",
3525 _str('ha\u1234\x07ho'))
3526 self.assertRaises(ValueError, setattr, a, "text",
3527 _str('ha\u1234\x02ho'))
3528
3529 self.assertRaises(ValueError, setattr, a, "tail",
3530 _str('ha\u1234\x07ho'))
3531 self.assertRaises(ValueError, setattr, a, "tail",
3532 _str('ha\u1234\x02ho'))
3533
3534 self.assertRaises(ValueError, Element,
3535 _str('ha\u1234\x07ho'))
3536 self.assertRaises(ValueError, Element,
3537 _str('ha\u1234\x02ho'))
3538
3552
3557
3575
3595
3597 tostring = self.etree.tostring
3598 html = self.etree.fromstring(
3599 '<html><body>'
3600 '<div><p>Some text<i>\r\n</i></p></div>\r\n'
3601 '</body></html>',
3602 parser=self.etree.HTMLParser())
3603 self.assertEqual(html.tag, 'html')
3604 div = html.find('.//div')
3605 self.assertEqual(div.tail, '\r\n')
3606 result = tostring(div, method='html')
3607 self.assertEqual(
3608 result,
3609 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3610 result = tostring(div, method='html', with_tail=True)
3611 self.assertEqual(
3612 result,
3613 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3614 result = tostring(div, method='html', with_tail=False)
3615 self.assertEqual(
3616 result,
3617 _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
3618
3640
3642 tostring = self.etree.tostring
3643 XML = self.etree.XML
3644 ElementTree = self.etree.ElementTree
3645
3646 root = XML(_bytes("<root/>"))
3647
3648 tree = ElementTree(root)
3649 self.assertEqual(None, tree.docinfo.standalone)
3650
3651 result = tostring(root, xml_declaration=True, encoding="ASCII")
3652 self.assertEqual(result, _bytes(
3653 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3654
3655 result = tostring(root, xml_declaration=True, encoding="ASCII",
3656 standalone=True)
3657 self.assertEqual(result, _bytes(
3658 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3659
3660 tree = ElementTree(XML(result))
3661 self.assertEqual(True, tree.docinfo.standalone)
3662
3663 result = tostring(root, xml_declaration=True, encoding="ASCII",
3664 standalone=False)
3665 self.assertEqual(result, _bytes(
3666 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
3667
3668 tree = ElementTree(XML(result))
3669 self.assertEqual(False, tree.docinfo.standalone)
3670
3690
3692 tostring = self.etree.tostring
3693 Element = self.etree.Element
3694 SubElement = self.etree.SubElement
3695
3696 a = Element('a')
3697 a.text = "A"
3698 a.tail = "tail"
3699 b = SubElement(a, 'b')
3700 b.text = "B"
3701 b.tail = _str("Søk på nettet")
3702 c = SubElement(a, 'c')
3703 c.text = "C"
3704
3705 result = tostring(a, method="text", encoding="UTF-16")
3706
3707 self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
3708 result)
3709
3711 tostring = self.etree.tostring
3712 Element = self.etree.Element
3713 SubElement = self.etree.SubElement
3714
3715 a = Element('a')
3716 a.text = _str('Søk på nettetA')
3717 a.tail = "tail"
3718 b = SubElement(a, 'b')
3719 b.text = "B"
3720 b.tail = _str('Søk på nettetB')
3721 c = SubElement(a, 'c')
3722 c.text = "C"
3723
3724 self.assertRaises(UnicodeEncodeError,
3725 tostring, a, method="text")
3726
3727 self.assertEqual(
3728 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
3729 tostring(a, encoding="UTF-8", method="text"))
3730
3743
3759
3763
3778
3796
3809
3811 tostring = self.etree.tostring
3812 Element = self.etree.Element
3813 SubElement = self.etree.SubElement
3814
3815 a = Element('a')
3816 b = SubElement(a, 'b')
3817 c = SubElement(a, 'c')
3818 d = SubElement(c, 'd')
3819 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
3820 self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
3821 self.assertEqual(_bytes('<b></b>'),
3822 canonicalize(tostring(b, encoding=_unicode)))
3823 self.assertEqual(_bytes('<c><d></d></c>'),
3824 canonicalize(tostring(c, encoding=_unicode)))
3825
3830
3845
3847 tostring = self.etree.tostring
3848 Element = self.etree.Element
3849 SubElement = self.etree.SubElement
3850
3851 a = Element('a')
3852 b = SubElement(a, 'b')
3853 c = SubElement(a, 'c')
3854
3855 result = tostring(a, encoding=_unicode)
3856 self.assertEqual(result, "<a><b/><c/></a>")
3857
3858 result = tostring(a, encoding=_unicode, pretty_print=False)
3859 self.assertEqual(result, "<a><b/><c/></a>")
3860
3861 result = tostring(a, encoding=_unicode, pretty_print=True)
3862 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
3863
3875
3877 class SubEl(etree.ElementBase):
3878 pass
3879
3880 el1 = SubEl()
3881 el2 = SubEl()
3882 self.assertEqual('SubEl', el1.tag)
3883 self.assertEqual('SubEl', el2.tag)
3884 el1.other = el2
3885 el2.other = el1
3886
3887 del el1, el2
3888 gc.collect()
3889
3890
3904
3906 root = etree.Element('parent')
3907 c1 = etree.SubElement(root, 'child1')
3908 c2 = etree.SubElement(root, 'child2')
3909
3910 root.remove(c1)
3911 root.remove(c2)
3912 c1.addnext(c2)
3913 c1.tail = 'abc'
3914 c2.tail = 'xyz'
3915 del c1
3916
3917 c2.getprevious()
3918
3919 self.assertEqual('child1', c2.getprevious().tag)
3920 self.assertEqual('abc', c2.getprevious().tail)
3921
3922
3923
3924 - def _writeElement(self, element, encoding='us-ascii', compression=0):
3935
3936
3980
3981 res_instance = res()
3982 parser = etree.XMLParser(load_dtd = True)
3983 parser.resolvers.add(res_instance)
3984
3985 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
3986 parser = parser)
3987
3988 self.include(tree)
3989
3990 called = list(res_instance.called.items())
3991 called.sort()
3992 self.assertEqual(
3993 [("dtd", True), ("include", True), ("input", True)],
3994 called)
3995
3997 data = textwrap.dedent('''
3998 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
3999 <foo/>
4000 <xi:include href="./test.xml" />
4001 </doc>
4002 ''')
4003
4004 class Resolver(etree.Resolver):
4005 called = {}
4006
4007 def resolve(self, url, id, context):
4008 if url.endswith("test_xinclude.xml"):
4009 assert not self.called.get("input")
4010 self.called["input"] = True
4011 return None
4012 elif url.endswith('/test5.xml'):
4013 assert not self.called.get("DONE")
4014 self.called["DONE"] = True
4015 return self.resolve_string('<DONE/>', context)
4016 else:
4017 _, filename = url.rsplit('/', 1)
4018 assert not self.called.get(filename)
4019 self.called[filename] = True
4020 next_data = data.replace(
4021 'test.xml', 'test%d.xml' % len(self.called))
4022 return self.resolve_string(next_data, context)
4023
4024 res_instance = Resolver()
4025 parser = etree.XMLParser(load_dtd=True)
4026 parser.resolvers.add(res_instance)
4027
4028 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4029 parser=parser)
4030
4031 self.include(tree)
4032
4033 called = list(res_instance.called.items())
4034 called.sort()
4035 self.assertEqual(
4036 [("DONE", True), ("input", True), ("test.xml", True),
4037 ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)],
4038 called)
4039
4040
4044
4045
4050
4051
4054 tree = self.parse(_bytes('<a><b/></a>'))
4055 f = BytesIO()
4056 tree.write_c14n(f)
4057 s = f.getvalue()
4058 self.assertEqual(_bytes('<a><b></b></a>'),
4059 s)
4060
4062 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4063 f = BytesIO()
4064 tree.write_c14n(f, compression=9)
4065 gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
4066 try:
4067 s = gzfile.read()
4068 finally:
4069 gzfile.close()
4070 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4071 s)
4072
4084
4100
4118
4130
4142
4144 tree = self.parse(_bytes(
4145 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4146 f = BytesIO()
4147 tree.write_c14n(f)
4148 s = f.getvalue()
4149 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4150 s)
4151 f = BytesIO()
4152 tree.write_c14n(f, exclusive=False)
4153 s = f.getvalue()
4154 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4155 s)
4156 f = BytesIO()
4157 tree.write_c14n(f, exclusive=True)
4158 s = f.getvalue()
4159 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4160 s)
4161
4162 f = BytesIO()
4163 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
4164 s = f.getvalue()
4165 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
4166 s)
4167
4169 tree = self.parse(_bytes(
4170 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4171 s = etree.tostring(tree, method='c14n')
4172 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4173 s)
4174 s = etree.tostring(tree, method='c14n', exclusive=False)
4175 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4176 s)
4177 s = etree.tostring(tree, method='c14n', exclusive=True)
4178 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4179 s)
4180
4181 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4182 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
4183 s)
4184
4186 tree = self.parse(_bytes(
4187 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4188 s = etree.tostring(tree.getroot(), method='c14n')
4189 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4190 s)
4191 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
4192 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4193 s)
4194 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
4195 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4196 s)
4197
4198 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
4199 self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4200 s)
4201 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
4202 self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
4203 s)
4204
4205 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4206 self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4207 s)
4208
4210 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
4211 tree = self.parse(_bytes(
4212 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4213
4214 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
4215 self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4216 s)
4217
4218
4221 tree = self.parse(_bytes('<a><b/></a>'))
4222 f = BytesIO()
4223 tree.write(f)
4224 s = f.getvalue()
4225 self.assertEqual(_bytes('<a><b/></a>'),
4226 s)
4227
4229 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4230 f = BytesIO()
4231 tree.write(f, compression=9)
4232 gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
4233 try:
4234 s = gzfile.read()
4235 finally:
4236 gzfile.close()
4237 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4238 s)
4239
4241 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4242 f = BytesIO()
4243 tree.write(f, compression=0)
4244 s0 = f.getvalue()
4245
4246 f = BytesIO()
4247 tree.write(f)
4248 self.assertEqual(f.getvalue(), s0)
4249
4250 f = BytesIO()
4251 tree.write(f, compression=1)
4252 s = f.getvalue()
4253 self.assertTrue(len(s) <= len(s0))
4254 gzfile = gzip.GzipFile(fileobj=BytesIO(s))
4255 try:
4256 s1 = gzfile.read()
4257 finally:
4258 gzfile.close()
4259
4260 f = BytesIO()
4261 tree.write(f, compression=9)
4262 s = f.getvalue()
4263 self.assertTrue(len(s) <= len(s0))
4264 gzfile = gzip.GzipFile(fileobj=BytesIO(s))
4265 try:
4266 s9 = gzfile.read()
4267 finally:
4268 gzfile.close()
4269
4270 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4271 s0)
4272 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4273 s1)
4274 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4275 s9)
4276
4288
4304
4316
4329
4331 etree = etree
4332
4354
4356 """This can't really be tested as long as there isn't a way to
4357 reset the logging setup ...
4358 """
4359 parse = self.etree.parse
4360
4361 messages = []
4362 class Logger(self.etree.PyErrorLog):
4363 def log(self, entry, message, *args):
4364 messages.append(message)
4365
4366 self.etree.use_global_python_log(Logger())
4367 f = BytesIO('<a><b></c></b></a>')
4368 try:
4369 parse(f)
4370 except SyntaxError:
4371 pass
4372 f.close()
4373
4374 self.assertTrue([ message for message in messages
4375 if 'mismatch' in message ])
4376 self.assertTrue([ message for message in messages
4377 if ':PARSER:' in message])
4378 self.assertTrue([ message for message in messages
4379 if ':ERR_TAG_NAME_MISMATCH:' in message ])
4380 self.assertTrue([ message for message in messages
4381 if ':1:15:' in message ])
4382
4383
4385 etree = etree
4386
4390
4392 class Target(object):
4393 def start(self, tag, attrib):
4394 return 'start(%s)' % tag
4395 def end(self, tag):
4396 return 'end(%s)' % tag
4397 def close(self):
4398 return 'close()'
4399
4400 parser = self.etree.XMLPullParser(target=Target())
4401 events = parser.read_events()
4402
4403 parser.feed('<root><element>')
4404 self.assertFalse(list(events))
4405 self.assertFalse(list(events))
4406 parser.feed('</element><child>')
4407 self.assertEqual([('end', 'end(element)')], list(events))
4408 parser.feed('</child>')
4409 self.assertEqual([('end', 'end(child)')], list(events))
4410 parser.feed('</root>')
4411 self.assertEqual([('end', 'end(root)')], list(events))
4412 self.assertFalse(list(events))
4413 self.assertEqual('close()', parser.close())
4414
4416 class Target(object):
4417 def start(self, tag, attrib):
4418 return 'start(%s)' % tag
4419 def end(self, tag):
4420 return 'end(%s)' % tag
4421 def close(self):
4422 return 'close()'
4423
4424 parser = self.etree.XMLPullParser(
4425 ['start', 'end'], target=Target())
4426 events = parser.read_events()
4427
4428 parser.feed('<root><element>')
4429 self.assertEqual(
4430 [('start', 'start(root)'), ('start', 'start(element)')],
4431 list(events))
4432 self.assertFalse(list(events))
4433 parser.feed('</element><child>')
4434 self.assertEqual(
4435 [('end', 'end(element)'), ('start', 'start(child)')],
4436 list(events))
4437 parser.feed('</child>')
4438 self.assertEqual(
4439 [('end', 'end(child)')],
4440 list(events))
4441 parser.feed('</root>')
4442 self.assertEqual(
4443 [('end', 'end(root)')],
4444 list(events))
4445 self.assertFalse(list(events))
4446 self.assertEqual('close()', parser.close())
4447
4449 parser = self.etree.XMLPullParser(
4450 ['start', 'end'], target=etree.TreeBuilder())
4451 events = parser.read_events()
4452
4453 parser.feed('<root><element>')
4454 self.assert_event_tags(
4455 events, [('start', 'root'), ('start', 'element')])
4456 self.assertFalse(list(events))
4457 parser.feed('</element><child>')
4458 self.assert_event_tags(
4459 events, [('end', 'element'), ('start', 'child')])
4460 parser.feed('</child>')
4461 self.assert_event_tags(
4462 events, [('end', 'child')])
4463 parser.feed('</root>')
4464 self.assert_event_tags(
4465 events, [('end', 'root')])
4466 self.assertFalse(list(events))
4467 root = parser.close()
4468 self.assertEqual('root', root.tag)
4469
4471 class Target(etree.TreeBuilder):
4472 def end(self, tag):
4473 el = super(Target, self).end(tag)
4474 el.tag += '-huhu'
4475 return el
4476
4477 parser = self.etree.XMLPullParser(
4478 ['start', 'end'], target=Target())
4479 events = parser.read_events()
4480
4481 parser.feed('<root><element>')
4482 self.assert_event_tags(
4483 events, [('start', 'root'), ('start', 'element')])
4484 self.assertFalse(list(events))
4485 parser.feed('</element><child>')
4486 self.assert_event_tags(
4487 events, [('end', 'element-huhu'), ('start', 'child')])
4488 parser.feed('</child>')
4489 self.assert_event_tags(
4490 events, [('end', 'child-huhu')])
4491 parser.feed('</root>')
4492 self.assert_event_tags(
4493 events, [('end', 'root-huhu')])
4494 self.assertFalse(list(events))
4495 root = parser.close()
4496 self.assertEqual('root-huhu', root.tag)
4497
4498
4529
4530 if __name__ == '__main__':
4531 print('to test use test.py %s' % __file__)
4532