| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2
3 """
4 Tests specific to the extended etree API
5
6 Tests that apply to the general ElementTree API should go into
7 test_elementtree
8 """
9
10 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 # Python 3
46 _unicode = str
47
48
50 """Tests only for etree, not ElementTree"""
51 etree = etree
52
54 self.assertTrue(isinstance(etree.__version__, _unicode))
55 self.assertTrue(isinstance(etree.LXML_VERSION, tuple))
56 self.assertEqual(len(etree.LXML_VERSION), 4)
57 self.assertTrue(isinstance(etree.LXML_VERSION[0], int))
58 self.assertTrue(isinstance(etree.LXML_VERSION[1], int))
59 self.assertTrue(isinstance(etree.LXML_VERSION[2], int))
60 self.assertTrue(isinstance(etree.LXML_VERSION[3], int))
61 self.assertTrue(etree.__version__.startswith(
62 str(etree.LXML_VERSION[0])))
63
65 if hasattr(self.etree, '__pyx_capi__'):
66 # newer Pyrex compatible C-API
67 self.assertTrue(isinstance(self.etree.__pyx_capi__, dict))
68 self.assertTrue(len(self.etree.__pyx_capi__) > 0)
69 else:
70 # older C-API mechanism
71 self.assertTrue(hasattr(self.etree, '_import_c_api'))
72
74 import lxml
75 includes = lxml.get_include()
76 self.assertTrue(includes)
77 self.assertTrue(len(includes) >= 2)
78 self.assertTrue(os.path.join(os.path.dirname(lxml.__file__), 'includes') in includes,
79 includes)
80
82 Element = self.etree.Element
83 el = Element('name')
84 self.assertEqual(el.tag, 'name')
85 el = Element('{}name')
86 self.assertEqual(el.tag, 'name')
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
127 Element = self.etree.Element
128 SubElement = self.etree.SubElement
129
130 el = Element('name')
131 self.assertRaises(ValueError, SubElement, el, '{}')
132 self.assertRaises(ValueError, SubElement, el, '{test}')
133
135 Element = self.etree.Element
136 SubElement = self.etree.SubElement
137
138 el = Element('name')
139 self.assertRaises(ValueError, SubElement, el, 'p:name')
140 self.assertRaises(ValueError, SubElement, el, '{test}p:name')
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
154 Element = self.etree.Element
155 SubElement = self.etree.SubElement
156
157 el = Element('name')
158 self.assertRaises(ValueError, SubElement, el, ' name ')
159 self.assertRaises(ValueError, SubElement, el, 'na me')
160 self.assertRaises(ValueError, SubElement, el, '{test} name')
161
163 Element = self.etree.Element
164 SubElement = self.etree.SubElement
165
166 el = Element('name')
167 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'})
168 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'})
169 self.assertEqual(0, len(el))
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
179 QName = self.etree.QName
180 q = QName(None, 'TAG')
181 self.assertEqual('TAG', q)
182 self.assertEqual('TAG', q.localname)
183 self.assertEqual(None, q.namespace)
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
197 # ET doesn't have namespace/localname properties on QNames
198 QName = self.etree.QName
199 namespace, localname = 'http://myns', 'a'
200 qname = QName(namespace, localname)
201 self.assertEqual(namespace, qname.namespace)
202 self.assertEqual(localname, qname.localname)
203
205 # ET doesn't have namespace/localname properties on QNames
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 # ET doesn't resove QNames as text values
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
228 etree = self.etree
229 self.assertRaises(ValueError,
230 etree.Element, "root", nsmap={'"' : 'testns'})
231 self.assertRaises(ValueError,
232 etree.Element, "root", nsmap={'&' : 'testns'})
233 self.assertRaises(ValueError,
234 etree.Element, "root", nsmap={'a:b' : 'testns'})
235
237 XML = self.etree.XML
238 tostring = self.etree.tostring
239 a = XML('<a aa="A"><b ba="B">B1</b>B2<c ca="C">C1</c>C2</a>')
240 a[0].clear(keep_tail=True)
241 self.assertEqual(_bytes('<a aa="A"><b/>B2<c ca="C">C1</c>C2</a>'), tostring(a))
242
244 # ET in Py 3.x has no "attrib.has_key()" method
245 XML = self.etree.XML
246
247 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
248 self.assertEqual(
249 True, root.attrib.has_key('bar'))
250 self.assertEqual(
251 False, root.attrib.has_key('baz'))
252 self.assertEqual(
253 False, root.attrib.has_key('hah'))
254 self.assertEqual(
255 True,
256 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
257
259 Element = self.etree.Element
260 root = Element("root")
261 root.set("attr", "TEST")
262 self.assertEqual("TEST", root.get("attr"))
263
265 # ElementTree accepts arbitrary attribute values
266 # lxml.etree allows only strings
267 Element = self.etree.Element
268
269 root = Element("root")
270 root.set("attr", "TEST")
271 self.assertEqual("TEST", root.get("attr"))
272 self.assertRaises(TypeError, root.set, "newattr", 5)
273
275 Element = self.etree.Element
276
277 root = Element("root")
278 root.set("attr", "TEST")
279 self.assertEqual("TEST", root.attrib["attr"])
280
281 root2 = Element("root2", root.attrib, attr2='TOAST')
282 self.assertEqual("TEST", root2.attrib["attr"])
283 self.assertEqual("TOAST", root2.attrib["attr2"])
284 self.assertEqual(None, root.attrib.get("attr2"))
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 # Keyword arguments are not ordered in Py<3.6, and thus get sorted.
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 # ElementTree accepts arbitrary attribute values
331 # lxml.etree allows only strings, or None for (html5) boolean attributes
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
340 XML = self.etree.XML
341 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>')
342
343 root = XML(xml)
344 self.etree.strip_attributes(root, 'a')
345 self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'),
346 self._writeElement(root))
347
348 root = XML(xml)
349 self.etree.strip_attributes(root, 'b', 'c')
350 self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'),
351 self._writeElement(root))
352
354 XML = self.etree.XML
355 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>')
356
357 root = XML(xml)
358 self.etree.strip_attributes(root, 'a')
359 self.assertEqual(
360 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'),
361 self._writeElement(root))
362
363 root = XML(xml)
364 self.etree.strip_attributes(root, '{http://test/ns}a', 'c')
365 self.assertEqual(
366 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'),
367 self._writeElement(root))
368
369 root = XML(xml)
370 self.etree.strip_attributes(root, '{http://test/ns}*')
371 self.assertEqual(
372 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'),
373 self._writeElement(root))
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
550 # lxml.etree separates target and text
551 Element = self.etree.Element
552 SubElement = self.etree.SubElement
553 ProcessingInstruction = self.etree.ProcessingInstruction
554
555 a = Element('a')
556 a.append(ProcessingInstruction('foo', 'some more text'))
557 self.assertEqual(a[0].target, 'foo')
558 self.assertEqual(a[0].text, 'some more text')
559
561 XML = self.etree.XML
562 root = XML(_bytes("<test><?mypi my test ?></test>"))
563 self.assertEqual(root[0].target, "mypi")
564 self.assertEqual(root[0].text, "my test ")
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 # previously caused a crash
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
600 XML = self.etree.XML
601 tostring = self.etree.tostring
602 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->"))
603 tree1 = self.etree.ElementTree(root)
604 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"),
605 tostring(tree1))
606
607 tree2 = copy.deepcopy(tree1)
608 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"),
609 tostring(tree2))
610
611 root2 = copy.deepcopy(tree1.getroot())
612 self.assertEqual(_bytes("<test/>"),
613 tostring(root2))
614
616 XML = self.etree.XML
617 tostring = self.etree.tostring
618 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
619 root = XML(xml)
620 tree1 = self.etree.ElementTree(root)
621 self.assertEqual(xml, tostring(tree1))
622
623 tree2 = copy.deepcopy(tree1)
624 self.assertEqual(xml, tostring(tree2))
625
626 root2 = copy.deepcopy(tree1.getroot())
627 self.assertEqual(_bytes("<test/>"),
628 tostring(root2))
629
631 XML = self.etree.XML
632 tostring = self.etree.tostring
633 xml = _bytes('<!-- comment --><!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
634 root = XML(xml)
635 tree1 = self.etree.ElementTree(root)
636 self.assertEqual(xml, tostring(tree1))
637
638 tree2 = copy.deepcopy(tree1)
639 self.assertEqual(xml, tostring(tree2))
640
642 fromstring = self.etree.fromstring
643 tostring = self.etree.tostring
644 XMLParser = self.etree.XMLParser
645
646 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
647 parser = XMLParser(remove_comments=True)
648 root = fromstring(xml, parser)
649 self.assertEqual(
650 _bytes('<a><b><c/></b></a>'),
651 tostring(root))
652
654 parse = self.etree.parse
655 tostring = self.etree.tostring
656 XMLParser = self.etree.XMLParser
657
658 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
659
660 f = BytesIO(xml)
661 tree = parse(f)
662 self.assertEqual(
663 xml,
664 tostring(tree))
665
666 parser = XMLParser(remove_pis=True)
667 tree = parse(f, parser)
668 self.assertEqual(
669 _bytes('<a><b><c/></b></a>'),
670 tostring(tree))
671
673 # ET raises IOError only
674 parse = self.etree.parse
675 self.assertRaises(TypeError, parse, 'notthere.xml', object())
676
678 # ET removes comments
679 iterparse = self.etree.iterparse
680 tostring = self.etree.tostring
681
682 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
683 events = list(iterparse(f))
684 root = events[-1][1]
685 self.assertEqual(3, len(events))
686 self.assertEqual(
687 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
688 tostring(root))
689
691 # ET removes comments
692 iterparse = self.etree.iterparse
693 tostring = self.etree.tostring
694
695 def name(event, el):
696 if event == 'comment':
697 return el.text
698 else:
699 return el.tag
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
712 # ET removes pis
713 iterparse = self.etree.iterparse
714 tostring = self.etree.tostring
715 ElementTree = self.etree.ElementTree
716
717 def name(event, el):
718 if event == 'pi':
719 return el.target, el.text
720 else:
721 return el.tag
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
735 iterparse = self.etree.iterparse
736 tostring = self.etree.tostring
737
738 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
739 events = list(iterparse(f, remove_comments=True,
740 events=('end', 'comment')))
741 root = events[-1][1]
742 self.assertEqual(3, len(events))
743 self.assertEqual(['c', 'b', 'a'],
744 [ el.tag for (event, el) in events ])
745 self.assertEqual(
746 _bytes('<a><b><c/></b></a>'),
747 tostring(root))
748
750 iterparse = self.etree.iterparse
751 f = BytesIO('<a><b><c/></a>')
752 # ET raises ExpatError, lxml raises XMLSyntaxError
753 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
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
906 self.etree.XMLParser(encoding="ascii")
907 self.etree.XMLParser(encoding="utf-8")
908 self.etree.XMLParser(encoding="iso-8859-1")
909
911 parser = self.etree.XMLParser(recover=True)
912
913 parser.feed('<?xml version=')
914 parser.feed('"1.0"?><ro')
915 parser.feed('ot><')
916 parser.feed('a test="works"')
917 parser.feed('><othertag/></root') # <a> not closed!
918 parser.feed('>')
919
920 root = parser.close()
921
922 self.assertEqual(root.tag, "root")
923 self.assertEqual(len(root), 1)
924 self.assertEqual(root[0].tag, "a")
925 self.assertEqual(root[0].get("test"), "works")
926 self.assertEqual(len(root[0]), 1)
927 self.assertEqual(root[0][0].tag, "othertag")
928 # FIXME: would be nice to get some errors logged ...
929 #self.assertTrue(len(parser.error_log) > 0, "error log is empty")
930
932 # test that recover mode plays nicely with the no-id-dict setup
933 parser = self.etree.XMLParser(recover=True, collect_ids=False)
934
935 parser.feed('<?xml version=')
936 parser.feed('"1.0"?><ro')
937 parser.feed('ot xml:id="123"><')
938 parser.feed('a test="works" xml:id=')
939 parser.feed('"321"><othertag/></root') # <a> not closed!
940 parser.feed('>')
941
942 root = parser.close()
943
944 self.assertEqual(root.tag, "root")
945 self.assertEqual(len(root), 1)
946 self.assertEqual(root[0].tag, "a")
947 self.assertEqual(root[0].get("test"), "works")
948 self.assertEqual(root[0].attrib, {
949 'test': 'works',
950 '{http://www.w3.org/XML/1998/namespace}id': '321'})
951 self.assertEqual(len(root[0]), 1)
952 self.assertEqual(root[0][0].tag, "othertag")
953 # FIXME: would be nice to get some errors logged ...
954 #self.assertTrue(len(parser.error_log) > 0, "error log is empty")
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" # no Element!
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 # ET doesn't call .close() on errors
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 # ET doesn't call .close() on errors
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 # test that target parsing works nicely with the no-id-hash setup
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
1064 events = []
1065 class Target(object):
1066 def start(self, tag, attrib):
1067 events.append("start-" + tag)
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
1161 iterwalk = self.etree.iterwalk
1162 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1163
1164 iterator = iterwalk(root, tag="b", events=('start', 'end'))
1165 events = list(iterator)
1166 self.assertEqual(
1167 [('start', root[0]), ('end', root[0])],
1168 events)
1169
1171 iterwalk = self.etree.iterwalk
1172 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1173
1174 iterator = iterwalk(root, tag="*", events=('start', 'end'))
1175 events = list(iterator)
1176 self.assertEqual(
1177 8,
1178 len(events))
1179
1181 iterwalk = self.etree.iterwalk
1182 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1183
1184 events = list(iterwalk(root))
1185 self.assertEqual(
1186 [('end', root[0]), ('end', root[1]), ('end', root)],
1187 events)
1188
1190 iterwalk = self.etree.iterwalk
1191 root = self.etree.XML(
1192 b'<!--C0--><a><!--Ca--><b><!--Cb--></b><!--Cc--><c/></a><!--C99-->')
1193
1194 iterator = iterwalk(root, events=('start', 'end', 'comment'))
1195 events = list(iterator)
1196 self.assertEqual(
1197 [('start', root), ('comment', root[0]),
1198 ('start', root[1]), ('comment', root[1][0]), ('end', root[1]),
1199 ('comment', root[2]), ('start', root[3]), ('end', root[3]),
1200 ('end', root),
1201 ],
1202 events)
1203
1205 iterwalk = self.etree.iterwalk
1206 root = self.etree.XML(
1207 b'<!--C0--><a><!--Ca--><b><!--Cb--></b><!--Cc--><c/></a><!--C99-->')
1208
1209 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'comment'))
1210 events = list(iterator)
1211 self.assertEqual(
1212 [('comment', root.getprevious()),
1213 ('start', root), ('comment', root[0]), # <a>
1214 ('start', root[1]), ('comment', root[1][0]), ('end', root[1]), # <b>
1215 ('comment', root[2]), ('start', root[3]), ('end', root[3]), # <c>
1216 ('end', root), ('comment', root.getnext()),
1217 ],
1218 events)
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]), # <a>
1245 ('start', root[1]), ('pi', root[1][0]), ('end', root[1]), # <b>
1246 ('pi', root[2]), ('start', root[3]), ('end', root[3]), # <c>
1247 ('end', root), ('pi', root.getnext()),
1248 ],
1249 events)
1250
1252 iterwalk = self.etree.iterwalk
1253 root = self.etree.XML(
1254 b'<!--C0--><?C0?><!--C1--><a><?Ca?><b><!--Cb--></b><?Cc?><c/></a><!--C99--><?C99?>')
1255
1256 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end', 'pi', 'comment'))
1257 events = list(iterator)
1258 self.assertEqual(
1259 [('comment', root.getprevious().getprevious().getprevious()),
1260 ('pi', root.getprevious().getprevious()),
1261 ('comment', root.getprevious()),
1262 ('start', root), ('pi', root[0]), # <a>
1263 ('start', root[1]), ('comment', root[1][0]), ('end', root[1]), # <b>
1264 ('pi', root[2]), ('start', root[3]), ('end', root[3]), # <c>
1265 ('end', root), ('comment', root.getnext()), ('pi', root.getnext().getnext()),
1266 ],
1267 events)
1268
1270 iterwalk = self.etree.iterwalk
1271 root = self.etree.XML(
1272 b'<!--C0--><?C0?><!--C1--><a><?Ca?><b><!--Cb--></b><?Cc?><c/></a><!--C99--><?C99?>')
1273
1274 iterator = iterwalk(self.etree.ElementTree(root), events=('start', 'end'))
1275 events = list(iterator)
1276 self.assertEqual(
1277 [('start', root), # <a>
1278 ('start', root[1]), ('end', root[1]), # <b>
1279 ('start', root[3]), ('end', root[3]), # <c>
1280 ('end', root),
1281 ],
1282 events)
1283
1285 iterwalk = self.etree.iterwalk
1286 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1287
1288 iterator = iterwalk(root, events=('start',))
1289 events = list(iterator)
1290 self.assertEqual(
1291 [('start', root), ('start', root[0]), ('start', root[1])],
1292 events)
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
1340 iterwalk = self.etree.iterwalk
1341 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1342
1343 iterator = iterwalk(root)
1344 for event, elem in iterator:
1345 elem.clear()
1346
1347 self.assertEqual(0,
1348 len(root))
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
1376 iterwalk = self.etree.iterwalk
1377 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>'))
1378
1379 iterator = iterwalk(root)
1380 tags = []
1381 for event, elem in iterator:
1382 tags.append(elem.tag)
1383 # requesting a skip after an 'end' event should never have an effect
1384 iterator.skip_subtree()
1385
1386 self.assertEqual(['c', 'b', 'e', 'd', 'a'], tags)
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 # skipping should only have an effect on 'start', not on 'end'
1398 iterator.skip_subtree()
1399
1400 self.assertEqual(
1401 [('start', 'a'),
1402 ('start', 'b'), ('end', 'b'), # ignored child 'c'
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
1441 iterwalk = self.etree.iterwalk
1442 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1443
1444 counts = []
1445 for event, elem in iterwalk(root):
1446 counts.append(len(list(elem.getiterator())))
1447 self.assertEqual(
1448 [1,2,1,4],
1449 counts)
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
1536 parse = self.etree.parse
1537 parser = self.etree.XMLParser(attribute_defaults=True)
1538 assertEqual = self.assertEqual
1539 test_url = _str("__nosuch.dtd")
1540
1541 class MyResolver(self.etree.Resolver):
1542 def resolve(self, url, id, context):
1543 expected = fileUrlInTestDir(test_url)
1544 url = url.replace('file://', 'file:') # depends on libxml2 version
1545 expected = expected.replace('file://', 'file:')
1546 assertEqual(url, expected)
1547 return self.resolve_filename(
1548 fileUrlInTestDir('test.dtd'), context)
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
1605 parse = self.etree.parse
1606 parser = self.etree.XMLParser(dtd_validation=True)
1607
1608 class _LocalException(Exception):
1609 pass
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
1621 parse = self.etree.parse
1622 tostring = self.etree.tostring
1623 parser = self.etree.XMLParser(resolve_entities=False)
1624 Entity = self.etree.Entity
1625
1626 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>')
1627 tree = parse(BytesIO(xml), parser)
1628 root = tree.getroot()
1629 self.assertEqual(root[0].tag, Entity)
1630 self.assertEqual(root[0].text, "&myentity;")
1631 self.assertEqual(root[0].tail, None)
1632 self.assertEqual(root[0].name, "myentity")
1633
1634 self.assertEqual(_bytes('<doc>&myentity;</doc>'),
1635 tostring(root))
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
1657 Entity = self.etree.Entity
1658 Element = self.etree.Element
1659 tostring = self.etree.tostring
1660
1661 root = Element("root")
1662 root.append( Entity("test") )
1663
1664 self.assertEqual(root[0].tag, Entity)
1665 self.assertEqual(root[0].text, "&test;")
1666 self.assertEqual(root[0].tail, None)
1667 self.assertEqual(root[0].name, "test")
1668
1669 self.assertEqual(_bytes('<root>&test;</root>'),
1670 tostring(root))
1671
1673 Entity = self.etree.Entity
1674 Element = self.etree.Element
1675 parser = self.etree.XMLParser(resolve_entities=False)
1676 entity = self.etree.XML('''<!DOCTYPE data [
1677 <!ENTITY a "a">
1678 <!ENTITY b "&a;">
1679 ]>
1680 <data>&b;</data>
1681 ''', parser)
1682
1683 el = Element('test')
1684 el.append(entity)
1685 self.assertEqual(el.tag, 'test')
1686 self.assertEqual(el[0].tag, 'data')
1687 self.assertEqual(el[0][0].tag, Entity)
1688 self.assertEqual(el[0][0].name, 'b')
1689
1691 Entity = self.etree.Entity
1692 self.assertEqual(Entity("test").text, '&test;')
1693 self.assertEqual(Entity("#17683").text, '䔓')
1694 self.assertEqual(Entity("#x1768").text, 'ᝨ')
1695 self.assertEqual(Entity("#x98AF").text, '颯')
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
1706 CDATA = self.etree.CDATA
1707 Element = self.etree.Element
1708 tostring = self.etree.tostring
1709
1710 root = Element("root")
1711 root.text = CDATA('test')
1712
1713 self.assertEqual('test',
1714 root.text)
1715 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
1716 tostring(root))
1717
1719 CDATA = self.etree.CDATA
1720 Element = self.etree.Element
1721 SubElement = self.etree.SubElement
1722 tostring = self.etree.tostring
1723
1724 root = Element("root")
1725 child = SubElement(root, 'child')
1726 child.tail = CDATA('test')
1727
1728 self.assertEqual('test', child.tail)
1729 self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'),
1730 tostring(root))
1731
1732 root = Element("root")
1733 root.tail = CDATA('test')
1734
1735 self.assertEqual('test', root.tail)
1736 self.assertEqual(_bytes('<root/><![CDATA[test]]>'),
1737 tostring(root))
1738
1740 CDATA = self.etree.CDATA
1741 Element = self.etree.Element
1742 root = Element("root")
1743
1744 root.text = CDATA("test")
1745 self.assertEqual('test', root.text)
1746
1747 root.text = CDATA(_str("test"))
1748 self.assertEqual('test', root.text)
1749
1750 self.assertRaises(TypeError, CDATA, 1)
1751
1753 CDATA = self.etree.CDATA
1754 Element = self.etree.Element
1755
1756 root = Element("root")
1757 cdata = CDATA('test')
1758
1759 self.assertRaises(TypeError,
1760 root.set, 'attr', cdata)
1761 self.assertRaises(TypeError,
1762 operator.setitem, root.attrib, 'attr', cdata)
1763
1765 tostring = self.etree.tostring
1766 parser = self.etree.XMLParser(strip_cdata=False)
1767 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1768
1769 self.assertEqual('test', root.text)
1770 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
1771 tostring(root))
1772
1774 tostring = self.etree.tostring
1775 parser = self.etree.XMLParser(strip_cdata=False)
1776 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1777 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
1778 tostring(root))
1779
1780 self.assertEqual(['test'], root.xpath('//text()'))
1781
1782 # TypeError in etree, AssertionError in ElementTree;
1784 Element = self.etree.Element
1785 SubElement = self.etree.SubElement
1786
1787 a = Element('a')
1788 b = SubElement(a, 'b')
1789
1790 self.assertRaises(TypeError,
1791 a.__setitem__, 0, 'foo')
1792
1794 Element = self.etree.Element
1795 root = Element('root')
1796 # raises AssertionError in ElementTree
1797 self.assertRaises(TypeError, root.append, None)
1798 self.assertRaises(TypeError, root.extend, [None])
1799 self.assertRaises(TypeError, root.extend, [Element('one'), None])
1800 self.assertEqual('one', root[0].tag)
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
1815 Element = self.etree.Element
1816 SubElement = self.etree.SubElement
1817 root = Element('root')
1818 SubElement(root, 'a')
1819 SubElement(root, 'b')
1820
1821 self.assertEqual(['a', 'b'],
1822 [c.tag for c in root])
1823 root[1].addnext(root[0])
1824 self.assertEqual(['b', 'a'],
1825 [c.tag for c in root])
1826
1828 Element = self.etree.Element
1829 SubElement = self.etree.SubElement
1830 root = Element('root')
1831 SubElement(root, 'a')
1832 SubElement(root, 'b')
1833
1834 self.assertEqual(['a', 'b'],
1835 [c.tag for c in root])
1836 root[0].addprevious(root[1])
1837 self.assertEqual(['b', 'a'],
1838 [c.tag for c in root])
1839
1841 Element = self.etree.Element
1842 SubElement = self.etree.SubElement
1843 root = Element('root')
1844 a = SubElement(root, 'a')
1845 b = SubElement(a, 'b')
1846 # appending parent as sibling is forbidden
1847 self.assertRaises(ValueError, b.addnext, a)
1848 self.assertEqual(['a'], [c.tag for c in root])
1849 self.assertEqual(['b'], [c.tag for c in a])
1850
1852 Element = self.etree.Element
1853 SubElement = self.etree.SubElement
1854 root = Element('root')
1855 a = SubElement(root, 'a')
1856 b = SubElement(a, 'b')
1857 # appending parent as sibling is forbidden
1858 self.assertRaises(ValueError, b.addprevious, a)
1859 self.assertEqual(['a'], [c.tag for c in root])
1860 self.assertEqual(['b'], [c.tag for c in a])
1861
1863 Element = self.etree.Element
1864 SubElement = self.etree.SubElement
1865 root = Element('root')
1866 a = SubElement(root, 'a')
1867 b = SubElement(a, 'b')
1868 c = SubElement(b, 'c')
1869 # appending parent as sibling is forbidden
1870 self.assertRaises(ValueError, c.addnext, a)
1871
1873 Element = self.etree.Element
1874 SubElement = self.etree.SubElement
1875 root = Element('root')
1876 a = SubElement(root, 'a')
1877 b = SubElement(a, 'b')
1878 c = SubElement(b, 'c')
1879 # appending parent as sibling is forbidden
1880 self.assertRaises(ValueError, c.addprevious, a)
1881
1883 Element = self.etree.Element
1884 SubElement = self.etree.SubElement
1885 root = Element('root')
1886 a = SubElement(root, 'a')
1887 b = SubElement(root, 'b')
1888 a.addprevious(a)
1889 self.assertEqual('a', root[0].tag)
1890 self.assertEqual('b', root[1].tag)
1891 b.addprevious(b)
1892 self.assertEqual('a', root[0].tag)
1893 self.assertEqual('b', root[1].tag)
1894 b.addprevious(a)
1895 self.assertEqual('a', root[0].tag)
1896 self.assertEqual('b', root[1].tag)
1897
1899 Element = self.etree.Element
1900 SubElement = self.etree.SubElement
1901 root = Element('root')
1902 a = SubElement(root, 'a')
1903 b = SubElement(root, 'b')
1904 a.addnext(a)
1905 self.assertEqual('a', root[0].tag)
1906 self.assertEqual('b', root[1].tag)
1907 b.addnext(b)
1908 self.assertEqual('a', root[0].tag)
1909 self.assertEqual('b', root[1].tag)
1910 a.addnext(b)
1911 self.assertEqual('a', root[0].tag)
1912 self.assertEqual('b', root[1].tag)
1913
1915 Element = self.etree.Element
1916 a = Element('a')
1917 b = Element('b')
1918 self.assertRaises(TypeError, a.addnext, b)
1919
1921 Element = self.etree.Element
1922 SubElement = self.etree.SubElement
1923 PI = self.etree.PI
1924 root = Element('root')
1925 SubElement(root, 'a')
1926 pi = PI('TARGET', 'TEXT')
1927 pi.tail = "TAIL"
1928
1929 self.assertEqual(_bytes('<root><a></a></root>'),
1930 self._writeElement(root))
1931 root[0].addprevious(pi)
1932 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
1933 self._writeElement(root))
1934
1936 Element = self.etree.Element
1937 PI = self.etree.PI
1938 root = Element('root')
1939 pi = PI('TARGET', 'TEXT')
1940 pi.tail = "TAIL"
1941
1942 self.assertEqual(_bytes('<root></root>'),
1943 self._writeElement(root))
1944 root.addprevious(pi)
1945 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'),
1946 self._writeElement(root))
1947
1949 Element = self.etree.Element
1950 SubElement = self.etree.SubElement
1951 PI = self.etree.PI
1952 root = Element('root')
1953 SubElement(root, 'a')
1954 pi = PI('TARGET', 'TEXT')
1955 pi.tail = "TAIL"
1956
1957 self.assertEqual(_bytes('<root><a></a></root>'),
1958 self._writeElement(root))
1959 root[0].addnext(pi)
1960 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
1961 self._writeElement(root))
1962
1964 Element = self.etree.Element
1965 PI = self.etree.PI
1966 root = Element('root')
1967 pi = PI('TARGET', 'TEXT')
1968 pi.tail = "TAIL"
1969
1970 self.assertEqual(_bytes('<root></root>'),
1971 self._writeElement(root))
1972 root.addnext(pi)
1973 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'),
1974 self._writeElement(root))
1975
1977 Element = self.etree.Element
1978 SubElement = self.etree.SubElement
1979 Comment = self.etree.Comment
1980 root = Element('root')
1981 SubElement(root, 'a')
1982 comment = Comment('TEXT ')
1983 comment.tail = "TAIL"
1984
1985 self.assertEqual(_bytes('<root><a></a></root>'),
1986 self._writeElement(root))
1987 root[0].addnext(comment)
1988 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
1989 self._writeElement(root))
1990
1992 Element = self.etree.Element
1993 Comment = self.etree.Comment
1994 root = Element('root')
1995 comment = Comment('TEXT ')
1996 comment.tail = "TAIL"
1997
1998 self.assertEqual(_bytes('<root></root>'),
1999 self._writeElement(root))
2000 root.addnext(comment)
2001 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'),
2002 self._writeElement(root))
2003
2005 Element = self.etree.Element
2006 SubElement = self.etree.SubElement
2007 Comment = self.etree.Comment
2008 root = Element('root')
2009 SubElement(root, 'a')
2010 comment = Comment('TEXT ')
2011 comment.tail = "TAIL"
2012
2013 self.assertEqual(_bytes('<root><a></a></root>'),
2014 self._writeElement(root))
2015 root[0].addprevious(comment)
2016 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
2017 self._writeElement(root))
2018
2020 Element = self.etree.Element
2021 Comment = self.etree.Comment
2022 root = Element('root')
2023 comment = Comment('TEXT ')
2024 comment.tail = "TAIL"
2025
2026 self.assertEqual(_bytes('<root></root>'),
2027 self._writeElement(root))
2028 root.addprevious(comment)
2029 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'),
2030 self._writeElement(root))
2031
2032 # ET's Elements have items() and key(), but not values()
2034 XML = self.etree.XML
2035
2036 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
2037 values = root.values()
2038 values.sort()
2039 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
2040
2041 # gives error in ElementTree
2043 Element = self.etree.Element
2044 Comment = self.etree.Comment
2045
2046 a = Element('a')
2047 a.append(Comment())
2048 self.assertEqual(
2049 _bytes('<a><!----></a>'),
2050 self._writeElement(a))
2051
2052 # ElementTree ignores comments
2054 ElementTree = self.etree.ElementTree
2055 tostring = self.etree.tostring
2056
2057 xml = _bytes('<a><b/><!----><c/></a>')
2058 f = BytesIO(xml)
2059 doc = ElementTree(file=f)
2060 a = doc.getroot()
2061 self.assertEqual(
2062 '',
2063 a[1].text)
2064 self.assertEqual(
2065 xml,
2066 tostring(a))
2067
2068 # ElementTree ignores comments
2070 ElementTree = self.etree.ElementTree
2071
2072 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
2073 doc = ElementTree(file=f)
2074 a = doc.getroot()
2075 self.assertEqual(
2076 ' hoi ',
2077 a[1].text)
2078
2079 # does not raise an exception in ElementTree
2081 Element = self.etree.Element
2082 Comment = self.etree.Comment
2083
2084 c = Comment()
2085 el = Element('myel')
2086
2087 self.assertRaises(TypeError, c.append, el)
2088 self.assertRaises(TypeError, c.insert, 0, el)
2089 self.assertRaises(TypeError, c.set, "myattr", "test")
2090
2092 c = self.etree.Comment()
2093 self.assertEqual(0, len(c.attrib))
2094
2095 self.assertFalse(c.attrib.__contains__('nope'))
2096 self.assertFalse('nope' in c.attrib)
2097 self.assertFalse('nope' in c.attrib.keys())
2098 self.assertFalse('nope' in c.attrib.values())
2099 self.assertFalse(('nope', 'huhu') in c.attrib.items())
2100
2101 self.assertEqual([], list(c.attrib))
2102 self.assertEqual([], list(c.attrib.keys()))
2103 self.assertEqual([], list(c.attrib.items()))
2104 self.assertEqual([], list(c.attrib.values()))
2105 self.assertEqual([], list(c.attrib.iterkeys()))
2106 self.assertEqual([], list(c.attrib.iteritems()))
2107 self.assertEqual([], list(c.attrib.itervalues()))
2108
2109 self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU'))
2110 self.assertRaises(KeyError, c.attrib.pop, 'nope')
2111
2112 self.assertRaises(KeyError, c.attrib.__getitem__, 'only')
2113 self.assertRaises(KeyError, c.attrib.__getitem__, 'names')
2114 self.assertRaises(KeyError, c.attrib.__getitem__, 'nope')
2115 self.assertRaises(KeyError, c.attrib.__setitem__, 'nope', 'yep')
2116 self.assertRaises(KeyError, c.attrib.__delitem__, 'nope')
2117
2118 # test passing 'None' to dump()
2121
2123 ElementTree = self.etree.ElementTree
2124
2125 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
2126 doc = ElementTree(file=f)
2127 a = doc.getroot()
2128 self.assertEqual(
2129 None,
2130 a.prefix)
2131 self.assertEqual(
2132 'foo',
2133 a[0].prefix)
2134
2136 ElementTree = self.etree.ElementTree
2137
2138 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
2139 doc = ElementTree(file=f)
2140 a = doc.getroot()
2141 self.assertEqual(
2142 None,
2143 a.prefix)
2144 self.assertEqual(
2145 None,
2146 a[0].prefix)
2147
2149 Element = self.etree.Element
2150 SubElement = self.etree.SubElement
2151
2152 a = Element('a')
2153 b = SubElement(a, 'b')
2154 c = SubElement(a, 'c')
2155 d = SubElement(b, 'd')
2156 self.assertEqual(
2157 None,
2158 a.getparent())
2159 self.assertEqual(
2160 a,
2161 b.getparent())
2162 self.assertEqual(
2163 b.getparent(),
2164 c.getparent())
2165 self.assertEqual(
2166 b,
2167 d.getparent())
2168
2170 XML = self.etree.XML
2171
2172 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
2173 result = []
2174 for el in root.iterchildren():
2175 result.append(el.tag)
2176 self.assertEqual(['one', 'two', 'three'], result)
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
2188 XML = self.etree.XML
2189
2190 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
2191 result = []
2192 for el in root.iterchildren(tag='two'):
2193 result.append(el.text)
2194 self.assertEqual(['Two', 'Bla'], result)
2195
2197 XML = self.etree.XML
2198
2199 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
2200 result = []
2201 for el in root.iterchildren('two'):
2202 result.append(el.text)
2203 self.assertEqual(['Two', 'Bla'], result)
2204
2206 XML = self.etree.XML
2207
2208 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
2209 result = []
2210 for el in root.iterchildren(reversed=True, tag='two'):
2211 result.append(el.text)
2212 self.assertEqual(['Bla', 'Two'], result)
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
2242 Element = self.etree.Element
2243 SubElement = self.etree.SubElement
2244
2245 a = Element('a')
2246 b = SubElement(a, 'b')
2247 c = SubElement(a, 'c')
2248 d = SubElement(b, 'd')
2249 self.assertEqual(
2250 [],
2251 list(a.iterancestors()))
2252 self.assertEqual(
2253 [a],
2254 list(b.iterancestors()))
2255 self.assertEqual(
2256 [a],
2257 list(c.iterancestors()))
2258 self.assertEqual(
2259 [b, a],
2260 list(d.iterancestors()))
2261
2263 Element = self.etree.Element
2264 SubElement = self.etree.SubElement
2265
2266 a = Element('a')
2267 b = SubElement(a, 'b')
2268 c = SubElement(a, 'c')
2269 d = SubElement(b, 'd')
2270 self.assertEqual(
2271 [a],
2272 list(d.iterancestors('a')))
2273 self.assertEqual(
2274 [a],
2275 list(d.iterancestors(tag='a')))
2276
2277 self.assertEqual(
2278 [b, a],
2279 list(d.iterancestors('*')))
2280 self.assertEqual(
2281 [b, a],
2282 list(d.iterancestors(tag='*')))
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
2328 Element = self.etree.Element
2329 SubElement = self.etree.SubElement
2330
2331 a = Element('a')
2332 b = SubElement(a, 'b')
2333 c = SubElement(a, 'c')
2334 d = SubElement(b, 'd')
2335 e = SubElement(c, 'e')
2336
2337 self.assertEqual(
2338 [b, d, c, e],
2339 list(a.iterdescendants()))
2340 self.assertEqual(
2341 [],
2342 list(d.iterdescendants()))
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
2413 Element = self.etree.Element
2414 SubElement = self.etree.SubElement
2415
2416 a = Element('a')
2417 b = SubElement(a, 'b')
2418 c = SubElement(a, 'c')
2419 d = SubElement(b, 'd')
2420 self.assertEqual(
2421 a,
2422 a.getroottree().getroot())
2423 self.assertEqual(
2424 a,
2425 b.getroottree().getroot())
2426 self.assertEqual(
2427 a,
2428 d.getroottree().getroot())
2429
2431 Element = self.etree.Element
2432 SubElement = self.etree.SubElement
2433
2434 a = Element('a')
2435 b = SubElement(a, 'b')
2436 c = SubElement(a, 'c')
2437 self.assertEqual(
2438 None,
2439 a.getnext())
2440 self.assertEqual(
2441 c,
2442 b.getnext())
2443 self.assertEqual(
2444 None,
2445 c.getnext())
2446
2448 Element = self.etree.Element
2449 SubElement = self.etree.SubElement
2450
2451 a = Element('a')
2452 b = SubElement(a, 'b')
2453 c = SubElement(a, 'c')
2454 d = SubElement(b, 'd')
2455 self.assertEqual(
2456 None,
2457 a.getprevious())
2458 self.assertEqual(
2459 b,
2460 c.getprevious())
2461 self.assertEqual(
2462 None,
2463 b.getprevious())
2464
2466 Element = self.etree.Element
2467 SubElement = self.etree.SubElement
2468
2469 a = Element('a')
2470 b = SubElement(a, 'b')
2471 c = SubElement(a, 'c')
2472 d = SubElement(b, 'd')
2473 self.assertEqual(
2474 [],
2475 list(a.itersiblings()))
2476 self.assertEqual(
2477 [c],
2478 list(b.itersiblings()))
2479 self.assertEqual(
2480 [],
2481 list(c.itersiblings()))
2482 self.assertEqual(
2483 [b],
2484 list(c.itersiblings(preceding=True)))
2485 self.assertEqual(
2486 [],
2487 list(b.itersiblings(preceding=True)))
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
2671 self.assertRaises(ValueError, self.etree.register_namespace,
2672 "XML", "http://www.w3.org/XML/1998/namespace")
2673 self.assertRaises(ValueError, self.etree.register_namespace,
2674 "xml", "http://www.w3.org/XML/2345")
2675 self.etree.register_namespace("xml", "http://www.w3.org/XML/1998/namespace") # ok
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 # make sure the source document is deallocated
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
2884 xml = _bytes(
2885 '<foo xmlns="F" xmlns:x="x">'
2886 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">'
2887 '<ns:baz/>'
2888 '</bar></foo>'
2889 )
2890 root = self.etree.fromstring(xml)
2891 self.assertEqual(xml, self.etree.tostring(root))
2892 self.etree.cleanup_namespaces(root)
2893 self.assertEqual(
2894 _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
2895 self.etree.tostring(root))
2896
2898 xml = _bytes(
2899 '<foo xmlns="F" xmlns:x="X" xmlns:a="A">'
2900 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">'
2901 '<ns:baz a:test="attr"/>'
2902 '</bar></foo>'
2903 )
2904 root = self.etree.fromstring(xml)
2905 self.assertEqual(xml, self.etree.tostring(root))
2906 self.etree.cleanup_namespaces(root)
2907 self.assertEqual(
2908 _bytes('<foo xmlns="F" xmlns:a="A">'
2909 '<bar xmlns:ns="NS" xmlns="B">'
2910 '<ns:baz a:test="attr"/>'
2911 '</bar></foo>'),
2912 self.etree.tostring(root))
2913
2915 xml = ('<n12:foo ' +
2916 ' '.join('xmlns:n{n}="NS{n}"'.format(n=i) for i in range(100)) +
2917 '><n68:a/></n12:foo>').encode('utf8')
2918 root = self.etree.fromstring(xml)
2919 self.assertEqual(xml, self.etree.tostring(root))
2920 self.etree.cleanup_namespaces(root)
2921 self.assertEqual(
2922 b'<n12:foo xmlns:n12="NS12" xmlns:n68="NS68"><n68:a/></n12:foo>',
2923 self.etree.tostring(root))
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
3138 Element = self.etree.Element
3139 Entity = self.etree.Entity
3140 SubElement = self.etree.SubElement
3141
3142 a = Element('a')
3143 b = SubElement(a, 'b')
3144 entity_b = Entity("TEST-b")
3145 b.append(entity_b)
3146
3147 self.assertEqual(
3148 [entity_b],
3149 list(a.getiterator(Entity)))
3150
3151 entity_a = Entity("TEST-a")
3152 a.append(entity_a)
3153
3154 self.assertEqual(
3155 [entity_b, entity_a],
3156 list(a.getiterator(Entity)))
3157
3158 self.assertEqual(
3159 [entity_b],
3160 list(b.getiterator(Entity)))
3161
3163 Element = self.etree.Element
3164 Comment = self.etree.Comment
3165 PI = self.etree.PI
3166 SubElement = self.etree.SubElement
3167
3168 a = Element('a')
3169 b = SubElement(a, 'b')
3170 a.append(Comment("test"))
3171 a.append(PI("pi", "content"))
3172 c = SubElement(a, 'c')
3173
3174 self.assertEqual(
3175 [a, b, c],
3176 list(a.getiterator(Element)))
3177
3179 # ElementTree iterates over everything here
3180 Element = self.etree.Element
3181 Comment = self.etree.Comment
3182 PI = self.etree.PI
3183 SubElement = self.etree.SubElement
3184
3185 a = Element('a')
3186 b = SubElement(a, 'b')
3187 a.append(Comment("test"))
3188 a.append(PI("pi", "content"))
3189 c = SubElement(a, 'c')
3190
3191 self.assertEqual(
3192 [a, b, c],
3193 list(a.getiterator('*')))
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) # not a parent of a/c/d1/d2
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) # not a parent of d1/d2
3255 self.assertRaises(ValueError, tree.getelementpath, d1)
3256 self.assertRaises(ValueError, tree.getelementpath, d2)
3257
3259 XML = self.etree.XML
3260 ElementTree = self.etree.ElementTree
3261 QName = self.etree.QName
3262 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
3263 self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
3264
3266 XML = self.etree.XML
3267 ElementTree = self.etree.ElementTree
3268 QName = self.etree.QName
3269 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
3270 self.assertEqual(len(list(tree.findall(QName("c")))), 1)
3271
3273 XML = self.etree.XML
3274 ElementTree = self.etree.ElementTree
3275 QName = self.etree.QName
3276 tree = ElementTree(XML(
3277 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
3278 self.assertEqual(len(list(tree.findall(QName("b")))), 2)
3279 self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
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
3301 XML = self.etree.XML
3302 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3303 nsmap = {'xx': 'X'}
3304 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3305 nsmap = {'xx': 'X', None: 'Y'}
3306 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1)
3307 nsmap = {'xx': 'X', '': 'Y'}
3308 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1)
3309
3311 XML = self.etree.XML
3312 root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>'))
3313 self.assertRaises(SyntaxError, root.findall, '')
3314 self.assertRaises(SyntaxError, root.findall, '//') # absolute path on Element
3315 self.assertRaises(SyntaxError, root.findall, './//')
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
3422 Element = self.etree.Element
3423 SubElement = self.etree.SubElement
3424
3425 a = Element('a')
3426 b = SubElement(a, 'b')
3427 c = SubElement(a, 'c')
3428 d = SubElement(a, 'd')
3429 e = SubElement(a, 'e')
3430
3431 x = Element('x')
3432 y = Element('y')
3433
3434 a[1::2] = [x, y]
3435 self.assertEqual(
3436 [b, x, d, y],
3437 list(a))
3438
3440 Element = self.etree.Element
3441 SubElement = self.etree.SubElement
3442
3443 a = Element('a')
3444 b = SubElement(a, 'b')
3445 c = SubElement(a, 'c')
3446 d = SubElement(a, 'd')
3447 e = SubElement(a, 'e')
3448
3449 x = Element('x')
3450 y = Element('y')
3451
3452 a[1::-1] = [x, y]
3453 self.assertEqual(
3454 [y, x, d, e],
3455 list(a))
3456
3458 Element = self.etree.Element
3459 SubElement = self.etree.SubElement
3460
3461 a = Element('a')
3462 b = SubElement(a, 'b')
3463 c = SubElement(a, 'c')
3464 d = SubElement(a, 'd')
3465 e = SubElement(a, 'e')
3466
3467 x = Element('x')
3468 y = Element('y')
3469
3470 a[::-2] = [x, y]
3471 self.assertEqual(
3472 [b, y, d, x],
3473 list(a))
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
3503 XML = self.etree.XML
3504 root = XML(_bytes('''<?xml version="1.0"?>
3505 <root><test>
3506
3507 <bla/></test>
3508 </root>
3509 '''))
3510
3511 self.assertEqual(
3512 [2, 2, 4],
3513 [ el.sourceline for el in root.getiterator() ])
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
3532 parse = self.etree.parse
3533 tree = parse(fileInTestDir('include/test_xinclude.xml'))
3534
3535 self.assertEqual(
3536 [1, 2, 3],
3537 [ el.sourceline for el in tree.getiterator() ])
3538
3540 iterparse = self.etree.iterparse
3541 lines = [ el.sourceline for (event, el) in
3542 iterparse(fileInTestDir('include/test_xinclude.xml')) ]
3543
3544 self.assertEqual(
3545 [2, 3, 1],
3546 lines)
3547
3549 iterparse = self.etree.iterparse
3550 lines = [ el.sourceline for (event, el) in
3551 iterparse(fileInTestDir('include/test_xinclude.xml'),
3552 events=("start",)) ]
3553
3554 self.assertEqual(
3555 [1, 2, 3],
3556 lines)
3557
3559 Element = self.etree.Element
3560 SubElement = self.etree.SubElement
3561 el = Element("test")
3562 self.assertEqual(None, el.sourceline)
3563
3564 child = SubElement(el, "test")
3565 self.assertEqual(None, el.sourceline)
3566 self.assertEqual(None, child.sourceline)
3567
3569 etree = self.etree
3570 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3571 docinfo = root.getroottree().docinfo
3572 self.assertEqual(docinfo.URL, "http://no/such/url")
3573
3575 etree = self.etree
3576 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3577 docinfo = root.getroottree().docinfo
3578 self.assertEqual(docinfo.URL, "http://no/such/url")
3579 docinfo.URL = "https://secret/url"
3580 self.assertEqual(docinfo.URL, "https://secret/url")
3581
3583 etree = self.etree
3584 tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
3585 docinfo = tree.docinfo
3586 self.assertEqual(docinfo.URL, "http://no/such/url")
3587
3589 etree = self.etree
3590 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
3591 base_url="http://no/such/url")
3592 docinfo = tree.docinfo
3593 self.assertEqual(docinfo.URL, "http://no/such/url")
3594
3596 etree = self.etree
3597 root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
3598 docinfo = root.getroottree().docinfo
3599 self.assertEqual(docinfo.URL, "http://no/such/url")
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
3620 etree = self.etree
3621 xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
3622 sys_id = "some.dtd"
3623 doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
3624 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
3625
3626 tree = etree.parse(BytesIO(xml))
3627 docinfo = tree.docinfo
3628 self.assertEqual(docinfo.encoding, "UTF-8")
3629 self.assertEqual(docinfo.xml_version, "1.0")
3630 self.assertEqual(docinfo.public_id, None)
3631 self.assertEqual(docinfo.system_url, sys_id)
3632 self.assertEqual(docinfo.root_name, 'html')
3633 self.assertEqual(docinfo.doctype, doctype_string)
3634
3636 etree = self.etree
3637 xml = _bytes('<html><body></body></html>')
3638 tree = etree.parse(BytesIO(xml))
3639 docinfo = tree.docinfo
3640 self.assertEqual(docinfo.encoding, "UTF-8")
3641 self.assertEqual(docinfo.xml_version, "1.0")
3642 self.assertEqual(docinfo.public_id, None)
3643 self.assertEqual(docinfo.system_url, None)
3644 self.assertEqual(docinfo.root_name, 'html')
3645 self.assertEqual(docinfo.doctype, '')
3646
3648 etree = self.etree
3649 xml = _bytes('<!DOCTYPE root><root></root>')
3650 tree = etree.parse(BytesIO(xml))
3651 docinfo = tree.docinfo
3652 self.assertEqual(docinfo.encoding, "UTF-8")
3653 self.assertEqual(docinfo.xml_version, "1.0")
3654 self.assertEqual(docinfo.public_id, None)
3655 self.assertEqual(docinfo.system_url, None)
3656 self.assertEqual(docinfo.root_name, 'root')
3657 self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
3658
3660 etree = self.etree
3661 xml = _bytes('<!DOCTYPE root>\n<root/>')
3662 tree = etree.parse(BytesIO(xml))
3663 self.assertEqual(xml, etree.tostring(tree))
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
3702 etree = self.etree
3703 root = etree.HTML(_bytes("<html><body></body></html>"),
3704 base_url="http://no/such/url")
3705 self.assertEqual(root.base, "http://no/such/url")
3706
3708 etree = self.etree
3709 root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
3710 self.assertEqual(root.base, "http://no/such/url")
3711
3713 # parse from a file object that returns unicode strings
3714 f = LargeFileLikeUnicode()
3715 tree = self.etree.parse(f)
3716 root = tree.getroot()
3717 self.assertTrue(root.tag.endswith('root'))
3718
3720 # check that DTDs that go in also go back out
3721 xml = _bytes('''\
3722 <!DOCTYPE test SYSTEM "test.dtd" [
3723 <!ENTITY entity "tasty">
3724 <!ELEMENT test (a)>
3725 <!ELEMENT a (#PCDATA)>
3726 ]>
3727 <test><a>test-test</a></test>\
3728 ''')
3729 tree = self.etree.parse(BytesIO(xml))
3730 self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
3731 xml.replace(_bytes(" "), _bytes("")))
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
3806 # ElementTree fails to serialize this
3807 tostring = self.etree.tostring
3808 Element = self.etree.Element
3809 SubElement = self.etree.SubElement
3810
3811 a = Element('a')
3812 b = SubElement(a, 'b')
3813 c = SubElement(a, 'c')
3814
3815 result = tostring(a, encoding='UTF-16')
3816 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
3817 canonicalize(result))
3818
3820 # ElementTree raises an AssertionError here
3821 tostring = self.etree.tostring
3822 self.assertRaises(TypeError, self.etree.tostring, None)
3823
3825 tostring = self.etree.tostring
3826 Element = self.etree.Element
3827 SubElement = self.etree.SubElement
3828
3829 a = Element('a')
3830 b = SubElement(a, 'b')
3831 c = SubElement(a, 'c')
3832
3833 result = tostring(a)
3834 self.assertEqual(result, _bytes("<a><b/><c/></a>"))
3835
3836 result = tostring(a, pretty_print=False)
3837 self.assertEqual(result, _bytes("<a><b/><c/></a>"))
3838
3839 result = tostring(a, pretty_print=True)
3840 self.assertEqual(result, _bytes("<a>\n <b/>\n <c/>\n</a>\n"))
3841
3843 tostring = self.etree.tostring
3844 Element = self.etree.Element
3845 SubElement = self.etree.SubElement
3846
3847 a = Element('a')
3848 a.tail = "aTAIL"
3849 b = SubElement(a, 'b')
3850 b.tail = "bTAIL"
3851 c = SubElement(a, 'c')
3852
3853 result = tostring(a)
3854 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
3855
3856 result = tostring(a, with_tail=False)
3857 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>"))
3858
3859 result = tostring(a, with_tail=True)
3860 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
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
3886 tostring = self.etree.tostring
3887 XML = self.etree.XML
3888 ElementTree = self.etree.ElementTree
3889 Element = self.etree.Element
3890
3891 tree = Element("root").getroottree()
3892 self.assertEqual(None, tree.docinfo.standalone)
3893
3894 tree = XML(_bytes("<root/>")).getroottree()
3895 self.assertEqual(None, tree.docinfo.standalone)
3896
3897 tree = XML(_bytes(
3898 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
3899 )).getroottree()
3900 self.assertEqual(True, tree.docinfo.standalone)
3901
3902 tree = XML(_bytes(
3903 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
3904 )).getroottree()
3905 self.assertEqual(False, tree.docinfo.standalone)
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
3938 tostring = self.etree.tostring
3939 XML = self.etree.XML
3940 ElementTree = self.etree.ElementTree
3941
3942 root = XML(_bytes(
3943 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
3944
3945 tree = ElementTree(root)
3946 self.assertEqual(True, tree.docinfo.standalone)
3947
3948 result = tostring(root, xml_declaration=True, encoding="ASCII")
3949 self.assertEqual(result, _bytes(
3950 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3951
3952 result = tostring(root, xml_declaration=True, encoding="ASCII",
3953 standalone=True)
3954 self.assertEqual(result, _bytes(
3955 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
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
3998 tounicode = self.etree.tounicode
3999 Element = self.etree.Element
4000 SubElement = self.etree.SubElement
4001
4002 a = Element('a')
4003 b = SubElement(a, 'b')
4004 c = SubElement(a, 'c')
4005
4006 self.assertTrue(isinstance(tounicode(a), _unicode))
4007 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
4008 canonicalize(tounicode(a)))
4009
4011 tounicode = self.etree.tounicode
4012 Element = self.etree.Element
4013 SubElement = self.etree.SubElement
4014
4015 a = Element('a')
4016 b = SubElement(a, 'b')
4017 c = SubElement(a, 'c')
4018 d = SubElement(c, 'd')
4019 self.assertTrue(isinstance(tounicode(b), _unicode))
4020 self.assertTrue(isinstance(tounicode(c), _unicode))
4021 self.assertEqual(_bytes('<b></b>'),
4022 canonicalize(tounicode(b)))
4023 self.assertEqual(_bytes('<c><d></d></c>'),
4024 canonicalize(tounicode(c)))
4025
4029
4031 tounicode = self.etree.tounicode
4032 Element = self.etree.Element
4033 SubElement = self.etree.SubElement
4034
4035 a = Element('a')
4036 b = SubElement(a, 'b')
4037 c = SubElement(a, 'c')
4038 d = SubElement(c, 'd')
4039 b.tail = 'Foo'
4040
4041 self.assertTrue(isinstance(tounicode(b), _unicode))
4042 self.assertTrue(tounicode(b) == '<b/>Foo' or
4043 tounicode(b) == '<b />Foo')
4044
4046 tounicode = self.etree.tounicode
4047 Element = self.etree.Element
4048 SubElement = self.etree.SubElement
4049
4050 a = Element('a')
4051 b = SubElement(a, 'b')
4052 c = SubElement(a, 'c')
4053
4054 result = tounicode(a)
4055 self.assertEqual(result, "<a><b/><c/></a>")
4056
4057 result = tounicode(a, pretty_print=False)
4058 self.assertEqual(result, "<a><b/><c/></a>")
4059
4060 result = tounicode(a, pretty_print=True)
4061 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
4062
4064 tostring = self.etree.tostring
4065 Element = self.etree.Element
4066 SubElement = self.etree.SubElement
4067
4068 a = Element('a')
4069 b = SubElement(a, 'b')
4070 c = SubElement(a, 'c')
4071
4072 self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode))
4073 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
4074 canonicalize(tostring(a, encoding=_unicode)))
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
4093 tostring = self.etree.tostring
4094 self.assertRaises(TypeError, self.etree.tostring,
4095 None, encoding=_unicode)
4096
4098 tostring = self.etree.tostring
4099 Element = self.etree.Element
4100 SubElement = self.etree.SubElement
4101
4102 a = Element('a')
4103 b = SubElement(a, 'b')
4104 c = SubElement(a, 'c')
4105 d = SubElement(c, 'd')
4106 b.tail = 'Foo'
4107
4108 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
4109 self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or
4110 tostring(b, encoding=_unicode) == '<b />Foo')
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
4131 root = etree.Element('parent')
4132 etree.SubElement(root, 'child')
4133
4134 self.assertEqual(len(root), 1)
4135 self.assertEqual(root[0].tag, 'child')
4136
4137 # in PyPy, GC used to kill the Python proxy instance without cleanup
4138 gc.collect()
4139 self.assertEqual(len(root), 1)
4140 self.assertEqual(root[0].tag, 'child')
4141
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 # not really testing anything here, but it shouldn't crash
4156
4158 root = etree.Element('parent')
4159 c1 = etree.SubElement(root, 'child1')
4160 c2 = etree.SubElement(root, 'child2')
4161
4162 root.remove(c1)
4163 root.remove(c2)
4164 c1.addnext(c2)
4165 del c1
4166 # trigger deallocation attempt of c1
4167 c2.getprevious()
4168 # make sure it wasn't deallocated
4169 self.assertEqual('child1', c2.getprevious().tag)
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 # trigger deallocation attempt of c1
4183 c2.getprevious()
4184 # make sure it wasn't deallocated
4185 self.assertEqual('child1', c2.getprevious().tag)
4186 self.assertEqual('abc', c2.getprevious().tail)
4187
4188 # helper methods
4189
4191 """Write out element for comparison.
4192 """
4193 ElementTree = self.etree.ElementTree
4194 f = BytesIO()
4195 tree = ElementTree(element=element)
4196 tree.write(f, encoding=encoding, compression=compression)
4197 data = f.getvalue()
4198 if compression:
4199 data = zlib.decompress(data)
4200 return canonicalize(data)
4201
4202
4205 filename = fileInTestDir('test_broken.xml')
4206 root = etree.XML(_bytes('''\
4207 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
4208 <xi:include href="%s" parse="text"/>
4209 </doc>
4210 ''' % path2url(filename)))
4211 old_text = root.text
4212 content = read_file(filename)
4213 old_tail = root[0].tail
4214
4215 self.include( etree.ElementTree(root) )
4216 self.assertEqual(old_text + content + old_tail,
4217 root.text)
4218
4220 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
4221 self.assertNotEqual(
4222 'a',
4223 tree.getroot()[1].tag)
4224 # process xincludes
4225 self.include( tree )
4226 # check whether we find it replaced with included data
4227 self.assertEqual(
4228 'a',
4229 tree.getroot()[1].tag)
4230
4232 class res(etree.Resolver):
4233 include_text = read_file(fileInTestDir('test.xml'))
4234 called = {}
4235 def resolve(self, url, id, context):
4236 if url.endswith(".dtd"):
4237 self.called["dtd"] = True
4238 return self.resolve_filename(
4239 fileInTestDir('test.dtd'), context)
4240 elif url.endswith("test_xinclude.xml"):
4241 self.called["input"] = True
4242 return None # delegate to default resolver
4243 else:
4244 self.called["include"] = True
4245 return self.resolve_string(self.include_text, context)
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 # delegate to default resolver
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
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
4345 try:
4346 data = textwrap.dedent(self.XINCLUDE[href])
4347 except KeyError:
4348 raise OSError("resource not found")
4349 if parse == "xml":
4350 data = etree.fromstring(data)
4351 return data
4352
4354 # Test infinitely recursive includes.
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 # Test 'max_depth' limitation.
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
4412 tree = self.parse(_bytes('<a><b/></a>'))
4413 with tmpfile() as filename:
4414 tree.write_c14n(filename)
4415 data = read_file(filename, 'rb')
4416 self.assertEqual(_bytes('<a><b></b></a>'),
4417 data)
4418
4420 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4421 with tmpfile() as filename:
4422 tree.write_c14n(filename, compression=9)
4423 with gzip.open(filename, 'rb') as f:
4424 data = f.read()
4425 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4426 data)
4427
4429 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4430 with tmpfile() as filename:
4431 tree.write(filename, method='c14n2', compression=9)
4432 with gzip.open(filename, 'rb') as f:
4433 data = f.read()
4434 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4435 data)
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
4453 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4454 f = BytesIO()
4455 tree.write_c14n(f)
4456 s = f.getvalue()
4457 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4458 s)
4459 f = BytesIO()
4460 tree.write_c14n(f, with_comments=True)
4461 s = f.getvalue()
4462 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4463 s)
4464 f = BytesIO()
4465 tree.write_c14n(f, with_comments=False)
4466 s = f.getvalue()
4467 self.assertEqual(_bytes('<a><b></b></a>'),
4468 s)
4469
4471 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4472 f = BytesIO()
4473 tree.write(f, method='c14n2')
4474 s = f.getvalue()
4475 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4476 s)
4477 f = BytesIO()
4478 tree.write(f, method='c14n2', with_comments=True)
4479 s = f.getvalue()
4480 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4481 s)
4482 f = BytesIO()
4483 tree.write(f, method='c14n2', with_comments=False)
4484 s = f.getvalue()
4485 self.assertEqual(_bytes('<a><b></b></a>'),
4486 s)
4487
4489 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4490 s = etree.tostring(tree, method='c14n')
4491 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4492 s)
4493 s = etree.tostring(tree, method='c14n', with_comments=True)
4494 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4495 s)
4496 s = etree.tostring(tree, method='c14n', with_comments=False)
4497 self.assertEqual(_bytes('<a><b></b></a>'),
4498 s)
4499
4501 tree = self.parse(b'<!--hi--><a><!--ho--><b/></a><!--hu-->')
4502 s = etree.tostring(tree, method='c14n2')
4503 self.assertEqual(b'<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->',
4504 s)
4505 s = etree.tostring(tree, method='c14n2', with_comments=True)
4506 self.assertEqual(b'<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->',
4507 s)
4508 s = etree.tostring(tree, method='c14n2', with_comments=False)
4509 self.assertEqual(b'<a><b></b></a>',
4510 s)
4511
4513 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4514 s = etree.tostring(tree.getroot(), method='c14n')
4515 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
4516 s)
4517 s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
4518 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
4519 s)
4520 s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
4521 self.assertEqual(_bytes('<a><b></b></a>'),
4522 s)
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
4667 tree = self.parse(_bytes('<a><b/></a>'))
4668 with tmpfile() as filename:
4669 tree.write(filename)
4670 data = read_file(filename, 'rb')
4671 self.assertEqual(_bytes('<a><b/></a>'),
4672 data)
4673
4675 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4676 with tmpfile() as filename:
4677 tree.write(filename, compression=9)
4678 with gzip.open(filename, 'rb') as f:
4679 data = f.read()
4680 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4681 data)
4682
4684 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4685 with tmpfile() as filename:
4686 tree.write(filename, compression=9)
4687 data = etree.tostring(etree.parse(filename))
4688 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4689 data)
4690
4692 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4693 with tmpfile() as filename:
4694 tree.write(filename, compression=9)
4695 with gzip.GzipFile(filename) as f:
4696 data = etree.tostring(etree.parse(f))
4697 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4698 data)
4699
4701 xml = _bytes('<a>'+'<b/>'*200+'</a>')
4702 tree = self.parse(xml)
4703 with tmpfile(prefix="p+%20", suffix=".xml") as filename:
4704 url = 'file://' + (filename if sys.platform != 'win32'
4705 else '/' + filename.replace('\\', '/'))
4706 tree.write(url)
4707 data = read_file(filename, 'rb').replace(_bytes('\n'), _bytes(''))
4708 self.assertEqual(data, xml)
4709
4710
4712 etree = etree
4713
4715 parse = self.etree.parse
4716 f = BytesIO('<a><b></c></b></a>')
4717 self.etree.clear_error_log()
4718 try:
4719 parse(f)
4720 logs = None
4721 except SyntaxError:
4722 e = sys.exc_info()[1]
4723 logs = e.error_log
4724 f.close()
4725 self.assertTrue([ log for log in logs
4726 if 'mismatch' in log.message ])
4727 self.assertTrue([ log for log in logs
4728 if 'PARSER' in log.domain_name])
4729 self.assertTrue([ log for log in logs
4730 if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
4731 self.assertTrue([ log for log in logs
4732 if 1 == log.line ])
4733 self.assertTrue([ log for log in logs
4734 if 15 == log.column ])
4735
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
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
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
4881 suite = unittest.TestSuite()
4882 suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
4883 suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
4884 suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
4885 suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
4886 suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
4887 suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
4888 suite.addTests([unittest.makeSuite(XMLPullParserTest)])
4889
4890 # add original doctests from ElementTree selftest modules
4891 from . import selftest, selftest2
4892 suite.addTests(doctest.DocTestSuite(selftest))
4893 suite.addTests(doctest.DocTestSuite(selftest2))
4894
4895 # add doctests
4896 suite.addTests(doctest.DocTestSuite(etree))
4897 suite.addTests(
4898 [make_doctest('../../../doc/tutorial.txt')])
4899 suite.addTests(
4900 [make_doctest('../../../doc/api.txt')])
4901 suite.addTests(
4902 [make_doctest('../../../doc/FAQ.txt')])
4903 suite.addTests(
4904 [make_doctest('../../../doc/parsing.txt')])
4905 suite.addTests(
4906 [make_doctest('../../../doc/resolvers.txt')])
4907 return suite
4908
4909
4910 if __name__ == '__main__':
4911 print('to test use test.py %s' % __file__)
4912
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Aug 12 02:25:38 2019 | http://epydoc.sourceforge.net |