| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2
3 """
4 Tests for the ElementTree API
5
6 Only test cases that apply equally well to etree and ElementTree
7 belong here. Note that there is a second test module called test_io.py
8 for IO related test cases.
9 """
10
11 from __future__ import absolute_import
12
13 import copy
14 import io
15 import operator
16 import os
17 import re
18 import sys
19 import textwrap
20 import unittest
21 from contextlib import contextmanager
22 from functools import wraps, partial
23 from itertools import islice
24
25 from .common_imports import (
26 BytesIO, etree, HelperTestCase,
27 ElementTree, cElementTree, ET_VERSION, CET_VERSION,
28 filter_by_version, fileInTestDir, canonicalize, tmpfile,
29 _str, _bytes, unicode, next, IS_PYTHON2
30 )
31
32 if cElementTree is not None and (CET_VERSION <= (1,0,7) or sys.version_info[0] >= 3):
33 cElementTree = None
34
35 if ElementTree is not None:
36 print("Comparing with ElementTree %s" % getattr(ElementTree, "VERSION", "?"))
37
38 if cElementTree is not None:
39 print("Comparing with cElementTree %s" % getattr(cElementTree, "VERSION", "?"))
43 def wrap(method):
44 @wraps(method)
45 def testfunc(self, *args):
46 if self.etree is not etree and sys.version_info < version:
47 raise unittest.SkipTest("requires ET in Python %s" % '.'.join(map(str, version)))
48 return method(self, *args)
49 return testfunc
50 return wrap
51
54 etree = None
55 required_versions_ET = {}
56 required_versions_cET = {}
57
59 try:
60 XMLParser = self.etree.XMLParser
61 except AttributeError:
62 assert 'ElementTree' in self.etree.__name__
63 XMLParser = self.etree.TreeBuilder
64 return XMLParser(**kwargs)
65
66 try:
67 HelperTestCase.assertRegex
68 except AttributeError:
71
72 @et_needs_pyversion(3, 6)
74 # Test element tree interface.
75
76 def check_string(string):
77 len(string)
78 for char in string:
79 self.assertEqual(len(char), 1,
80 msg="expected one-character string, got %r" % char)
81 new_string = string + ""
82 new_string = string + " "
83 string[:0]
84
85 def check_mapping(mapping):
86 len(mapping)
87 keys = mapping.keys()
88 items = mapping.items()
89 for key in keys:
90 item = mapping[key]
91 mapping["key"] = "value"
92 self.assertEqual(mapping["key"], "value",
93 msg="expected value string, got %r" % mapping["key"])
94
95 def check_element(element):
96 self.assertTrue(self.etree.iselement(element), msg="not an element")
97 direlem = dir(element)
98 for attr in 'tag', 'attrib', 'text', 'tail':
99 self.assertTrue(hasattr(element, attr),
100 msg='no %s member' % attr)
101 self.assertIn(attr, direlem,
102 msg='no %s visible by dir' % attr)
103
104 check_string(element.tag)
105 check_mapping(element.attrib)
106 if element.text is not None:
107 check_string(element.text)
108 if element.tail is not None:
109 check_string(element.tail)
110 for elem in element:
111 check_element(elem)
112
113 element = self.etree.Element("tag")
114 check_element(element)
115 tree = self.etree.ElementTree(element)
116 check_element(tree.getroot())
117 element = self.etree.Element(u"t\xe4g", key="value")
118 tree = self.etree.ElementTree(element)
119 # lxml and ET Py2: slightly different repr()
120 #self.assertRegex(repr(element), r"^<Element 't\xe4g' at 0x.*>$")
121 element = self.etree.Element("tag", key="value")
122
123 # Make sure all standard element methods exist.
124
125 def check_method(method):
126 self.assertTrue(hasattr(method, '__call__'),
127 msg="%s not callable" % method)
128
129 check_method(element.append)
130 check_method(element.extend)
131 check_method(element.insert)
132 check_method(element.remove)
133 # Removed in Py3.9
134 #check_method(element.getchildren)
135 check_method(element.find)
136 check_method(element.iterfind)
137 check_method(element.findall)
138 check_method(element.findtext)
139 check_method(element.clear)
140 check_method(element.get)
141 check_method(element.set)
142 check_method(element.keys)
143 check_method(element.items)
144 check_method(element.iter)
145 check_method(element.itertext)
146 # Removed in Py3.9
147 #check_method(element.getiterator)
148
149 # These methods return an iterable. See bug 6472.
150
151 def check_iter(it):
152 check_method(it.next if IS_PYTHON2 else it.__next__)
153
154 check_iter(element.iterfind("tag"))
155 check_iter(element.iterfind("*"))
156 check_iter(tree.iterfind("tag"))
157 check_iter(tree.iterfind("*"))
158
159 # These aliases are provided:
160
161 # not an alias in lxml
162 #self.assertEqual(self.etree.XML, self.etree.fromstring)
163 self.assertEqual(self.etree.PI, self.etree.ProcessingInstruction)
164
166 for i in range(10):
167 e = self.etree.Element('foo')
168 self.assertEqual(e.tag, 'foo')
169 self.assertEqual(e.text, None)
170 self.assertEqual(e.tail, None)
171
173 Element = self.etree.Element
174
175 root = Element('root')
176 root.append(Element('one'))
177 root.append(Element('two'))
178 root.append(Element('three'))
179 self.assertEqual(3, len(root))
180 self.assertEqual('one', root[0].tag)
181 self.assertEqual('two', root[1].tag)
182 self.assertEqual('three', root[2].tag)
183 self.assertRaises(IndexError, operator.getitem, root, 3)
184
185 # test weird dictionary interaction leading to segfault previously
187 root = self.etree.Element('root')
188 self.assertEqual(root.tag, "root")
189 add = self.etree.ElementTree(file=BytesIO('<foo>Foo</foo>'))
190 self.assertEqual(add.getroot().tag, "foo")
191 self.assertEqual(add.getroot().text, "Foo")
192 root.append(self.etree.Element('baz'))
193 self.assertEqual(root.tag, "root")
194 self.assertEqual(root[0].tag, "baz")
195
197 Element = self.etree.Element
198 SubElement = self.etree.SubElement
199
200 root = Element('root')
201 SubElement(root, 'one')
202 SubElement(root, 'two')
203 SubElement(root, 'three')
204 self.assertEqual(3, len(root))
205 self.assertEqual('one', root[0].tag)
206 self.assertEqual('two', root[1].tag)
207 self.assertEqual('three', root[2].tag)
208
210 Element = self.etree.Element
211 SubElement = self.etree.SubElement
212
213 root1 = Element('root')
214 SubElement(root1, 'one')
215 self.assertTrue(root1[0] in root1)
216
217 root2 = Element('root')
218 SubElement(root2, 'two')
219 SubElement(root2, 'three')
220 self.assertTrue(root2[0] in root2)
221 self.assertTrue(root2[1] in root2)
222
223 self.assertFalse(root1[0] in root2)
224 self.assertFalse(root2[0] in root1)
225 self.assertFalse(None in root2)
226
228 ElementTree = self.etree.ElementTree
229
230 f = BytesIO('<doc>Test<one>One</one></doc>')
231 doc = ElementTree(file=f)
232 root = doc.getroot()
233 self.assertEqual(1, len(root))
234 self.assertEqual('one', root[0].tag)
235 self.assertRaises(IndexError, operator.getitem, root, 1)
236
238 ElementTree = self.etree.ElementTree
239
240 f = BytesIO('<doc><one>One</one><two>Two</two>hm<three>Three</three></doc>')
241 doc = ElementTree(file=f)
242 root = doc.getroot()
243 self.assertEqual(3, len(root))
244 self.assertEqual('one', root[0].tag)
245 self.assertEqual('two', root[1].tag)
246 self.assertEqual('three', root[2].tag)
247
249 ElementTree = self.etree.ElementTree
250
251 f = BytesIO('<doc>Test</doc>')
252 doc = ElementTree(file=f)
253 root = doc.getroot()
254 self.assertEqual(0, len(root))
255
257 Element = self.etree.Element
258 SubElement = self.etree.SubElement
259 a = Element('a')
260 b = SubElement(a, 'b')
261 c = SubElement(a, 'c')
262 d = SubElement(a, 'd')
263 self.assertEqual(d, a[-1])
264 self.assertEqual(c, a[-2])
265 self.assertEqual(b, a[-3])
266 self.assertRaises(IndexError, operator.getitem, a, -4)
267 a[-1] = e = Element('e')
268 self.assertEqual(e, a[-1])
269 del a[-1]
270 self.assertEqual(2, len(a))
271
273 ElementTree = self.etree.ElementTree
274
275 f = BytesIO('<doc><one>One</one><two>Two</two></doc>')
276 doc = ElementTree(file=f)
277 root = doc.getroot()
278 self.assertEqual(2, len(root))
279 self.assertEqual('one', root[0].tag)
280 self.assertEqual('two', root[1].tag)
281
283 ElementTree = self.etree.ElementTree
284
285 f = BytesIO('<doc>This is a text</doc>')
286 doc = ElementTree(file=f)
287 root = doc.getroot()
288 self.assertEqual('This is a text', root.text)
289
291 ElementTree = self.etree.ElementTree
292
293 f = BytesIO('<doc></doc>')
294 doc = ElementTree(file=f)
295 root = doc.getroot()
296 self.assertEqual(None, root.text)
297
299 ElementTree = self.etree.ElementTree
300
301 f = BytesIO('<doc><one>One</one></doc>')
302 doc = ElementTree(file=f)
303 root = doc.getroot()
304 self.assertEqual(None, root.text)
305 self.assertEqual('One', root[0].text)
306
308 ElementTree = self.etree.ElementTree
309
310 f = BytesIO('<doc>This is > than a text</doc>')
311 doc = ElementTree(file=f)
312 root = doc.getroot()
313 self.assertEqual('This is > than a text', root.text)
314
316 Element = self.etree.Element
317
318 a = Element("a")
319 a.text = "<>&"
320 self.assertXML(_bytes('<a><>&</a>'),
321 a)
322
324 tostring = self.etree.tostring
325 Element = self.etree.Element
326
327 a = Element("a")
328 a.text = "<>&"
329 self.assertEqual(_bytes('<a><>&</a>'),
330 tostring(a))
331
337
338 a = Element("a")
339 a.text = strTest("text")
340 self.assertXML(_bytes('<a>text</a>'),
341 a)
342
344 ElementTree = self.etree.ElementTree
345
346 f = BytesIO('<doc>This is <i>mixed</i> content.</doc>')
347 doc = ElementTree(file=f)
348 root = doc.getroot()
349 self.assertEqual(1, len(root))
350 self.assertEqual('This is ', root.text)
351 self.assertEqual(None, root.tail)
352 self.assertEqual('mixed', root[0].text)
353 self.assertEqual(' content.', root[0].tail)
354
356 Element = self.etree.Element
357 SubElement = self.etree.SubElement
358
359 class strTest(str):
360 pass
361
362 a = Element("a")
363 SubElement(a, "t").tail = strTest("tail")
364 self.assertXML(_bytes('<a><t></t>tail</a>'),
365 a)
366
368 # this is discouraged for ET compat, should not be tested...
369 XML = self.etree.XML
370
371 root = XML(_bytes('<doc>This is <i>mixed</i> content.</doc>'))
372 self.assertEqual(1, len(root))
373 self.assertEqual('This is ', root.text)
374 self.assertEqual(None, root.tail)
375 self.assertEqual('mixed', root[0].text)
376 self.assertEqual(' content.', root[0].tail)
377
378 del root[0].tail
379
380 self.assertEqual(1, len(root))
381 self.assertEqual('This is ', root.text)
382 self.assertEqual(None, root.tail)
383 self.assertEqual('mixed', root[0].text)
384 self.assertEqual(None, root[0].tail)
385
386 root[0].tail = "TAIL"
387
388 self.assertEqual(1, len(root))
389 self.assertEqual('This is ', root.text)
390 self.assertEqual(None, root.tail)
391 self.assertEqual('mixed', root[0].text)
392 self.assertEqual('TAIL', root[0].tail)
393
395 Element = self.etree.Element
396 ElementTree = self.etree.ElementTree
397
398 el = Element('hoi')
399 doc = ElementTree(el)
400 root = doc.getroot()
401 self.assertEqual(None, root.text)
402 self.assertEqual('hoi', root.tag)
403
405 ElementTree = self.etree.ElementTree
406
407 f = BytesIO('<doc one="One" two="Two"/>')
408 doc = ElementTree(file=f)
409 root = doc.getroot()
410 self.assertEqual('One', root.attrib['one'])
411 self.assertEqual('Two', root.attrib['two'])
412 self.assertRaises(KeyError, operator.getitem, root.attrib, 'three')
413
415 ElementTree = self.etree.ElementTree
416
417 f = BytesIO('<doc one="One" two="Two"/>')
418 doc = ElementTree(file=f)
419 root = doc.getroot()
420 self.assertEqual('One', root.attrib.get('one'))
421 self.assertEqual('Two', root.attrib.get('two'))
422 self.assertEqual(None, root.attrib.get('three'))
423 self.assertEqual('foo', root.attrib.get('three', 'foo'))
424
426 ElementTree = self.etree.ElementTree
427
428 f = BytesIO('<doc one="One" two="Two"/>')
429 doc = ElementTree(file=f)
430 root = doc.getroot()
431 attrib = dict(root.attrib)
432 self.assertEqual('One', attrib['one'])
433 self.assertEqual('Two', attrib['two'])
434 self.assertRaises(KeyError, operator.getitem, attrib, 'three')
435
437 ElementTree = self.etree.ElementTree
438
439 f = BytesIO('<doc one="One" two="Two"/>')
440 doc = ElementTree(file=f)
441 root = doc.getroot()
442 attrib = copy.copy(root.attrib)
443 self.assertEqual('One', attrib['one'])
444 self.assertEqual('Two', attrib['two'])
445 self.assertRaises(KeyError, operator.getitem, attrib, 'three')
446
448 ElementTree = self.etree.ElementTree
449
450 f = BytesIO('<doc one="One" two="Two"/>')
451 doc = ElementTree(file=f)
452 root = doc.getroot()
453 attrib = copy.deepcopy(root.attrib)
454 self.assertEqual('One', attrib['one'])
455 self.assertEqual('Two', attrib['two'])
456 self.assertRaises(KeyError, operator.getitem, attrib, 'three')
457
459 ElementTree = self.etree.ElementTree
460
461 f = BytesIO('<doc one="One" two="Two"/>')
462 doc = ElementTree(file=f)
463 root = doc.getroot()
464 self.assertEqual('One', root.get('one'))
465 self.assertEqual('Two', root.get('two'))
466 self.assertEqual(None, root.get('three'))
467 self.assertEqual('foo', root.get('three', 'foo'))
468
470 XML = self.etree.XML
471
472 root = XML(_bytes('<doc one="One" two="Two"/>'))
473 self.assertEqual('One', root.get('one'))
474 self.assertEqual('Two', root.get('two'))
475 root.attrib.clear()
476 self.assertEqual(None, root.get('one'))
477 self.assertEqual(None, root.get('two'))
478
480 Element = self.etree.Element
481
482 root = Element("root", one="One")
483 root.set("two", "Two")
484 self.assertEqual('One', root.get('one'))
485 self.assertEqual('Two', root.get('two'))
486 root.attrib.clear()
487 self.assertEqual(None, root.get('one'))
488 self.assertEqual(None, root.get('two'))
489
491 Element = self.etree.Element
492 SubElement = self.etree.SubElement
493
494 attribNS = '{http://foo/bar}x'
495
496 parent = Element('parent')
497 parent.set(attribNS, 'a')
498 child = SubElement(parent, 'child')
499 child.set(attribNS, 'b')
500
501 self.assertEqual('a', parent.get(attribNS))
502 self.assertEqual('b', child.get(attribNS))
503
504 parent.clear()
505 self.assertEqual(None, parent.get(attribNS))
506 self.assertEqual('b', child.get(attribNS))
507
509 ElementTree = self.etree.ElementTree
510
511 f = BytesIO('<doc one="One" two="Two"/>')
512 doc = ElementTree(file=f)
513 root = doc.getroot()
514 self.assertEqual('One', root.attrib['one'])
515 self.assertEqual('Two', root.attrib['two'])
516
517 self.assertEqual('One', root.attrib.pop('one'))
518
519 self.assertEqual(None, root.attrib.get('one'))
520 self.assertEqual('Two', root.attrib['two'])
521
523 root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
524 self.assertRaises(KeyError, root.attrib.pop, 'NONE')
525
526 self.assertEqual('One', root.attrib['one'])
527 self.assertEqual('Two', root.attrib['two'])
528
530 root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
531 self.assertEqual('Three', root.attrib.pop('three', 'Three'))
532
534 root = self.etree.XML(_bytes('<doc/>'))
535 self.assertEqual('Three', root.attrib.pop('three', 'Three'))
536
538 root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
539 self.assertRaises(TypeError, root.attrib.pop, 'One', None, None)
540
542 XML = self.etree.XML
543
544 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
545 items = list(root.attrib.items())
546 items.sort()
547 self.assertEqual(
548 [('alpha', 'Alpha'), ('beta', 'Beta')],
549 items)
550
551 root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'})
552
553 items = list(root.attrib.items())
554 items.sort()
555 self.assertEqual(
556 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
557 items)
558
560 XML = self.etree.XML
561
562 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
563 items = list(root.attrib.items())
564 items.sort()
565 self.assertEqual(
566 [('alpha', 'Alpha'), ('beta', 'Beta')],
567 items)
568
569 root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'}.items())
570
571 items = list(root.attrib.items())
572 items.sort()
573 self.assertEqual(
574 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
575 items)
576
578 XML = self.etree.XML
579
580 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
581 items = list(root.attrib.items())
582 items.sort()
583 self.assertEqual(
584 [('alpha', 'Alpha'), ('beta', 'Beta')],
585 items)
586
587 root.attrib.update(iter({'alpha' : 'test', 'gamma' : 'Gamma'}.items()))
588
589 items = list(root.attrib.items())
590 items.sort()
591 self.assertEqual(
592 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
593 items)
594
596 XML = self.etree.XML
597
598 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
599 items = list(root.attrib.items())
600 items.sort()
601 self.assertEqual(
602 [('alpha', 'Alpha'), ('beta', 'Beta')],
603 items)
604
605 other = XML(_bytes('<doc alpha="test" gamma="Gamma"/>'))
606 root.attrib.update(other.attrib)
607
608 items = list(root.attrib.items())
609 items.sort()
610 self.assertEqual(
611 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
612 items)
613
615 XML = self.etree.XML
616
617 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
618 keys = list(root.attrib.keys())
619 keys.sort()
620 self.assertEqual(['alpha', 'beta', 'gamma'], keys)
621
623 XML = self.etree.XML
624
625 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
626 keys = list(root.keys())
627 keys.sort()
628 self.assertEqual(['alpha', 'beta', 'gamma'], keys)
629
631 XML = self.etree.XML
632
633 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
634 items = list(root.items())
635 items.sort()
636 self.assertEqual(
637 [('alpha','Alpha'), ('beta','Beta'), ('gamma','Gamma')],
638 items)
639
641 XML = self.etree.XML
642
643 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
644 keys = list(root.keys())
645 keys.sort()
646 self.assertEqual(['bar', '{http://ns.codespeak.net/test}baz'],
647 keys)
648
650 XML = self.etree.XML
651
652 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
653 values = list(root.attrib.values())
654 values.sort()
655 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
656
658 XML = self.etree.XML
659
660 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
661 values = list(root.attrib.values())
662 values.sort()
663 self.assertEqual(
664 ['Bar', 'Baz'], values)
665
667 XML = self.etree.XML
668
669 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
670 items = list(root.attrib.items())
671 items.sort()
672 self.assertEqual([
673 ('alpha', 'Alpha'),
674 ('beta', 'Beta'),
675 ('gamma', 'Gamma'),
676 ],
677 items)
678
680 XML = self.etree.XML
681
682 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
683 items = list(root.attrib.items())
684 items.sort()
685 self.assertEqual(
686 [('bar', 'Bar'), ('{http://ns.codespeak.net/test}baz', 'Baz')],
687 items)
688
690 XML = self.etree.XML
691
692 expected = "{'{http://ns.codespeak.net/test}baz': 'Baz', 'bar': 'Bar'}"
693 alternative = "{'bar': 'Bar', '{http://ns.codespeak.net/test}baz': 'Baz'}"
694
695 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
696 try:
697 self.assertEqual(expected, str(root.attrib))
698 except AssertionError:
699 self.assertEqual(alternative, str(root.attrib))
700
702 XML = self.etree.XML
703
704 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
705 self.assertEqual(
706 True, 'bar' in root.attrib)
707 self.assertEqual(
708 False, 'baz' in root.attrib)
709 self.assertEqual(
710 False, 'hah' in root.attrib)
711 self.assertEqual(
712 True,
713 '{http://ns.codespeak.net/test}baz' in root.attrib)
714
716 Element = self.etree.Element
717
718 root = Element("root")
719 root.set("attr", "TEST")
720 self.assertEqual("TEST", root.get("attr"))
721
723 Element = self.etree.Element
724
725 root = Element("root")
726 root.set("attr", "TEST")
727 self.assertEqual("TEST", root.attrib["attr"])
728
729 root2 = Element("root2", root.attrib)
730 self.assertEqual("TEST", root2.attrib["attr"])
731
733 XML = self.etree.XML
734
735 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma" />'))
736 result = []
737 for key in root.attrib:
738 result.append(key)
739 result.sort()
740 self.assertEqual(['alpha', 'beta', 'gamma'], result)
741
743 Element = self.etree.Element
744
745 a = Element('a')
746 a.attrib['foo'] = 'Foo'
747 a.attrib['bar'] = 'Bar'
748 self.assertEqual('Foo', a.attrib['foo'])
749 del a.attrib['foo']
750 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
751
753 Element = self.etree.Element
754
755 a = Element('a')
756 a.attrib['{http://a/}foo'] = 'Foo'
757 a.attrib['{http://a/}bar'] = 'Bar'
758 self.assertEqual(None, a.get('foo'))
759 self.assertEqual('Foo', a.get('{http://a/}foo'))
760 self.assertEqual('Foo', a.attrib['{http://a/}foo'])
761
762 self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
763 self.assertEqual('Foo', a.attrib['{http://a/}foo'])
764
765 del a.attrib['{http://a/}foo']
766 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
767
769 XML = self.etree.XML
770
771 a = XML(_bytes('<a xmlns:nsa="http://a/" nsa:foo="FooNS" foo="Foo" />'))
772
773 self.assertEqual('Foo', a.attrib['foo'])
774 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
775
776 del a.attrib['foo']
777 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
778 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
779 self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
780
781 del a.attrib['{http://a/}foo']
782 self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
783 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
784
785 a = XML(_bytes('<a xmlns:nsa="http://a/" foo="Foo" nsa:foo="FooNS" />'))
786
787 self.assertEqual('Foo', a.attrib['foo'])
788 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
789
790 del a.attrib['foo']
791 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
792 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
793
794 del a.attrib['{http://a/}foo']
795 self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
796 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
797
799 XML = self.etree.XML
800
801 root = XML(_bytes('<doc>This is a text.</doc>'))
802 self.assertEqual(0, len(root))
803 self.assertEqual('This is a text.', root.text)
804
806 XMLID = self.etree.XMLID
807 XML = self.etree.XML
808 xml_text = _bytes('''
809 <document>
810 <h1 id="chapter1">...</h1>
811 <p id="note1" class="note">...</p>
812 <p>Regular paragraph.</p>
813 <p xml:id="xmlid">XML:ID paragraph.</p>
814 <p id="warn1" class="warning">...</p>
815 </document>
816 ''')
817
818 root, dic = XMLID(xml_text)
819 root2 = XML(xml_text)
820 self.assertEqual(self._writeElement(root),
821 self._writeElement(root2))
822 expected = {
823 "chapter1" : root[0],
824 "note1" : root[1],
825 "warn1" : root[4]
826 }
827 self.assertEqual(dic, expected)
828
830 fromstring = self.etree.fromstring
831
832 root = fromstring('<doc>This is a text.</doc>')
833 self.assertEqual(0, len(root))
834 self.assertEqual('This is a text.', root.text)
835
836 required_versions_ET['test_fromstringlist'] = (1,3)
838 fromstringlist = self.etree.fromstringlist
839
840 root = fromstringlist(["<do", "c>T", "hi", "s is",
841 " a text.<", "/doc", ">"])
842 self.assertEqual(0, len(root))
843 self.assertEqual('This is a text.', root.text)
844
845 required_versions_ET['test_fromstringlist_characters'] = (1,3)
847 fromstringlist = self.etree.fromstringlist
848
849 root = fromstringlist(list('<doc>This is a text.</doc>'))
850 self.assertEqual(0, len(root))
851 self.assertEqual('This is a text.', root.text)
852
853 required_versions_ET['test_fromstringlist_single'] = (1,3)
855 fromstringlist = self.etree.fromstringlist
856
857 root = fromstringlist(['<doc>This is a text.</doc>'])
858 self.assertEqual(0, len(root))
859 self.assertEqual('This is a text.', root.text)
860
862 iselement = self.etree.iselement
863 Element = self.etree.Element
864 ElementTree = self.etree.ElementTree
865 XML = self.etree.XML
866 Comment = self.etree.Comment
867 ProcessingInstruction = self.etree.ProcessingInstruction
868
869 el = Element('hoi')
870 self.assertTrue(iselement(el))
871
872 el2 = XML(_bytes('<foo/>'))
873 self.assertTrue(iselement(el2))
874
875 tree = ElementTree(element=Element('dag'))
876 self.assertTrue(not iselement(tree))
877 self.assertTrue(iselement(tree.getroot()))
878
879 c = Comment('test')
880 self.assertTrue(iselement(c))
881
882 p = ProcessingInstruction("test", "some text")
883 self.assertTrue(iselement(p))
884
886 XML = self.etree.XML
887
888 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
889 result = []
890 for el in root:
891 result.append(el.tag)
892 self.assertEqual(['one', 'two', 'three'], result)
893
895 XML = self.etree.XML
896
897 root = XML(_bytes('<doc></doc>'))
898 result = []
899 for el in root:
900 result.append(el.tag)
901 self.assertEqual([], result)
902
904 XML = self.etree.XML
905
906 root = XML(_bytes('<doc>Text</doc>'))
907 result = []
908 for el in root:
909 result.append(el.tag)
910 self.assertEqual([], result)
911
913 # this would cause a crash in the past
914 fromstring = self.etree.fromstring
915 root = fromstring('<html><p></p>x</html>')
916 for elem in root:
917 elem.tail = ''
918
920 # this would cause a crash in the past
921 fromstring = self.etree.fromstring
922 root = fromstring('<html><p></p>x</html>')
923 for elem in root:
924 elem.tail = None
925
927 XML = self.etree.XML
928 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
929 result = []
930 for el in reversed(root):
931 result.append(el.tag)
932 self.assertEqual(['three', 'two', 'one'], result)
933
935 XML = self.etree.XML
936
937 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
938 result = []
939 add = True
940 for el in root:
941 result.append(el.tag)
942 if add:
943 self.etree.SubElement(root, 'four')
944 add = False
945 self.assertEqual(['one', 'two', 'three', 'four'], result)
946
948 XML = self.etree.XML
949
950 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
951 result = []
952 for el in root:
953 result.append(el.tag)
954 del root[-1]
955 self.assertEqual(['one', 'two'], result)
956
958 XML = self.etree.XML
959
960 root = XML(_bytes('<doc><one/><two/></doc>'))
961 result = []
962 for el0 in root:
963 result.append(el0.tag)
964 for el1 in root:
965 result.append(el1.tag)
966 self.assertEqual(['one','one', 'two', 'two', 'one', 'two'], result)
967
968 required_versions_ET['test_itertext'] = (1,3)
970 # ET 1.3+
971 XML = self.etree.XML
972 root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
973
974 text = list(root.itertext())
975 self.assertEqual(["RTEXT", "ATAIL", "CTEXT", "CTAIL"],
976 text)
977
978 required_versions_ET['test_itertext_child'] = (1,3)
980 # ET 1.3+
981 XML = self.etree.XML
982 root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
983
984 text = list(root[2].itertext())
985 self.assertEqual(["CTEXT"],
986 text)
987
989 XML = self.etree.XML
990 root = XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))
991 self.assertEqual(len(list(root.findall("c"))), 1)
992 self.assertEqual(len(list(root.findall(".//c"))), 2)
993 self.assertEqual(len(list(root.findall(".//b"))), 3)
994 self.assertEqual(len(list(root.findall(".//b"))[0]), 1)
995 self.assertEqual(len(list(root.findall(".//b"))[1]), 0)
996 self.assertEqual(len(list(root.findall(".//b"))[2]), 0)
997
999 XML = self.etree.XML
1000 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
1001 self.assertEqual(len(list(root.findall(".//{X}b"))), 2)
1002 self.assertEqual(len(list(root.findall(".//b"))), 3)
1003 self.assertEqual(len(list(root.findall("b"))), 2)
1004
1005 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
1009
1010 root = self.etree.XML('''
1011 <a xmlns:x="X" xmlns:y="Y">
1012 <x:b><c/></x:b>
1013 <b/>
1014 <c><x:b/><b/></c><y:b/>
1015 </a>''')
1016 root.append(self.etree.Comment('test'))
1017
1018 self.assertEqual(summarize_list(root.findall("{*}b")),
1019 ['{X}b', 'b', '{Y}b'])
1020 self.assertEqual(summarize_list(root.findall("{*}c")),
1021 ['c'])
1022 self.assertEqual(summarize_list(root.findall("{X}*")),
1023 ['{X}b'])
1024 self.assertEqual(summarize_list(root.findall("{Y}*")),
1025 ['{Y}b'])
1026 self.assertEqual(summarize_list(root.findall("{}*")),
1027 ['b', 'c'])
1028 self.assertEqual(summarize_list(root.findall("{}b")), # only for consistency
1029 ['b'])
1030 self.assertEqual(summarize_list(root.findall("{}b")),
1031 summarize_list(root.findall("b")))
1032 self.assertEqual(summarize_list(root.findall("{*}*")),
1033 ['{X}b', 'b', 'c', '{Y}b'])
1034 self.assertEqual(summarize_list(root.findall("{*}*")
1035 + ([] if self.etree is etree else [root[-1]])),
1036 summarize_list(root.findall("*")))
1037
1038 self.assertEqual(summarize_list(root.findall(".//{*}b")),
1039 ['{X}b', 'b', '{X}b', 'b', '{Y}b'])
1040 self.assertEqual(summarize_list(root.findall(".//{*}c")),
1041 ['c', 'c'])
1042 self.assertEqual(summarize_list(root.findall(".//{X}*")),
1043 ['{X}b', '{X}b'])
1044 self.assertEqual(summarize_list(root.findall(".//{Y}*")),
1045 ['{Y}b'])
1046 self.assertEqual(summarize_list(root.findall(".//{}*")),
1047 ['c', 'b', 'c', 'b'])
1048 self.assertEqual(summarize_list(root.findall(".//{}b")),
1049 ['b', 'b'])
1050
1052 Element = self.etree.Element
1053
1054 el = Element('tag', foo='Foo', bar='Bar')
1055 self.assertEqual('Foo', el.attrib['foo'])
1056 self.assertEqual('Bar', el.attrib['bar'])
1057
1059 Element = self.etree.Element
1060
1061 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'})
1062 self.assertEqual('Foo', el.attrib['foo'])
1063 self.assertEqual('Bar', el.attrib['bar'])
1064
1066 Element = self.etree.Element
1067
1068 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, baz='Baz')
1069 self.assertEqual('Foo', el.attrib['foo'])
1070 self.assertEqual('Bar', el.attrib['bar'])
1071 self.assertEqual('Baz', el.attrib['baz'])
1072
1074 Element = self.etree.Element
1075
1076 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, bar='Baz')
1077 self.assertEqual('Foo', el.attrib['foo'])
1078 self.assertEqual('Baz', el.attrib['bar'])
1079
1081 Element = self.etree.Element
1082
1083 el = Element('tag', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
1084 self.assertEqual('Foo', el.attrib['{ns1}foo'])
1085 self.assertEqual('Bar', el.attrib['{ns2}bar'])
1086
1088 Element = self.etree.Element
1089 SubElement = self.etree.SubElement
1090
1091 el = Element('tag')
1092 SubElement(el, 'foo', {'foo':'Foo'}, baz="Baz")
1093 self.assertEqual("Baz", el[0].attrib['baz'])
1094 self.assertEqual('Foo', el[0].attrib['foo'])
1095
1097 Element = self.etree.Element
1098 SubElement = self.etree.SubElement
1099
1100 el = Element('tag')
1101 SubElement(el, 'foo', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
1102 self.assertEqual('Foo', el[0].attrib['{ns1}foo'])
1103 self.assertEqual('Bar', el[0].attrib['{ns2}bar'])
1104
1106 ElementTree = self.etree.ElementTree
1107 XML = self.etree.XML
1108
1109 for i in range(10):
1110 f = BytesIO()
1111 root = XML(_bytes('<doc%s>This is a test.</doc%s>' % (i, i)))
1112 tree = ElementTree(element=root)
1113 tree.write(f)
1114 data = f.getvalue()
1115 self.assertEqual(
1116 _bytes('<doc%s>This is a test.</doc%s>' % (i, i)),
1117 canonicalize(data))
1118
1119 required_versions_ET['test_write_method_html'] = (1,3)
1121 ElementTree = self.etree.ElementTree
1122 Element = self.etree.Element
1123 SubElement = self.etree.SubElement
1124
1125 html = Element('html')
1126 body = SubElement(html, 'body')
1127 p = SubElement(body, 'p')
1128 p.text = "html"
1129 SubElement(p, 'br').tail = "test"
1130
1131 tree = ElementTree(element=html)
1132 f = BytesIO()
1133 tree.write(f, method="html")
1134 data = f.getvalue().replace(_bytes('\n'),_bytes(''))
1135
1136 self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
1137 data)
1138
1139 required_versions_ET['test_write_method_text'] = (1,3)
1141 ElementTree = self.etree.ElementTree
1142 Element = self.etree.Element
1143 SubElement = self.etree.SubElement
1144
1145 a = Element('a')
1146 a.text = "A"
1147 a.tail = "tail"
1148 b = SubElement(a, 'b')
1149 b.text = "B"
1150 b.tail = "TAIL"
1151 c = SubElement(a, 'c')
1152 c.text = "C"
1153
1154 tree = ElementTree(element=a)
1155 f = BytesIO()
1156 tree.write(f, method="text")
1157 data = f.getvalue()
1158
1159 self.assertEqual(_bytes('ABTAILCtail'),
1160 data)
1161
1163 ElementTree = self.etree.ElementTree
1164 XML = self.etree.XML
1165
1166 tree = ElementTree( XML(_bytes('<doc>This is a test.</doc>')) )
1167 self.assertRaises(IOError, tree.write,
1168 "definitely////\\-\\nonexisting\\-\\////FILE")
1169
1170 # this could trigger a crash, apparently because the document
1171 # reference was prematurely garbage collected
1173 Element = self.etree.Element
1174
1175 element = Element('tag')
1176 for i in range(10):
1177 element.attrib['key'] = 'value'
1178 value = element.attrib['key']
1179 self.assertEqual(value, 'value')
1180
1181 # from doctest; for some reason this caused crashes too
1183 Element = self.etree.Element
1184 ElementTree = self.etree.ElementTree
1185
1186 f = BytesIO()
1187 for i in range(10):
1188 element = Element('tag%s' % i)
1189 self._check_element(element)
1190 tree = ElementTree(element)
1191 tree.write(f)
1192 self._check_element_tree(tree)
1193
1195 Element = self.etree.Element
1196 SubElement = self.etree.SubElement
1197
1198 el = Element('foo')
1199 el2 = SubElement(el, 'bar')
1200 el3 = SubElement(el2, 'baz')
1201
1202 al = Element('foo2')
1203 al2 = SubElement(al, 'bar2')
1204 al3 = SubElement(al2, 'baz2')
1205
1206 # now move al2 into el
1207 el.append(al2)
1208
1209 # now change al3 directly
1210 al3.text = 'baz2-modified'
1211
1212 # it should have changed through this route too
1213 self.assertEqual(
1214 'baz2-modified',
1215 el[1][0].text)
1216
1218 Element = self.etree.Element
1219 SubElement = self.etree.SubElement
1220
1221 a = Element('a')
1222 b = SubElement(a, 'b')
1223 a.text = 'hoi'
1224 self.assertEqual(
1225 'hoi',
1226 a.text)
1227 self.assertEqual(
1228 'b',
1229 a[0].tag)
1230
1232 Element = self.etree.Element
1233 SubElement = self.etree.SubElement
1234
1235 a = Element('a')
1236 a.text = 'hoi'
1237 b = SubElement(a ,'b')
1238 self.assertEqual(
1239 'hoi',
1240 a.text)
1241 self.assertEqual(
1242 'b',
1243 a[0].tag)
1244
1246 Element = self.etree.Element
1247
1248 a = Element('a')
1249
1250 a.text = 'foo'
1251 a.text = None
1252
1253 self.assertEqual(
1254 None,
1255 a.text)
1256 self.assertXML(_bytes('<a></a>'), a)
1257
1259 Element = self.etree.Element
1260
1261 a = Element('a')
1262 self.assertEqual(None, a.text)
1263
1264 a.text = ''
1265 self.assertEqual('', a.text)
1266 self.assertXML(_bytes('<a></a>'), a)
1267
1269 Element = self.etree.Element
1270 SubElement = self.etree.SubElement
1271
1272 a = Element('a')
1273 a.tail = 'dag'
1274 self.assertEqual('dag',
1275 a.tail)
1276 b = SubElement(a, 'b')
1277 b.tail = 'hoi'
1278 self.assertEqual('hoi',
1279 b.tail)
1280 self.assertEqual('dag',
1281 a.tail)
1282
1284 Element = self.etree.Element
1285
1286 a = Element('a')
1287 b = Element('b')
1288 b.tail = 'b_tail'
1289 a.append(b)
1290 self.assertEqual('b_tail',
1291 b.tail)
1292
1294 Element = self.etree.Element
1295 SubElement = self.etree.SubElement
1296
1297 a = Element('a')
1298 b = SubElement(a, 'b')
1299 b.tail = 'foo'
1300 b.tail = 'bar'
1301 self.assertEqual('bar',
1302 b.tail)
1303 self.assertXML(_bytes('<a><b></b>bar</a>'), a)
1304
1306 Element = self.etree.Element
1307 a = Element('a')
1308 a.tail = 'foo'
1309 a.tail = None
1310 self.assertEqual(
1311 None,
1312 a.tail)
1313 self.assertXML(_bytes('<a></a>'), a)
1314
1315 required_versions_ET['test_extend'] = (1,3)
1317 root = self.etree.Element('foo')
1318 for i in range(3):
1319 element = self.etree.SubElement(root, 'a%s' % i)
1320 element.text = "text%d" % i
1321 element.tail = "tail%d" % i
1322
1323 elements = []
1324 for i in range(3):
1325 new_element = self.etree.Element("test%s" % i)
1326 new_element.text = "TEXT%s" % i
1327 new_element.tail = "TAIL%s" % i
1328 elements.append(new_element)
1329
1330 root.extend(elements)
1331
1332 self.assertEqual(
1333 ["a0", "a1", "a2", "test0", "test1", "test2"],
1334 [ el.tag for el in root ])
1335 self.assertEqual(
1336 ["text0", "text1", "text2", "TEXT0", "TEXT1", "TEXT2"],
1337 [ el.text for el in root ])
1338 self.assertEqual(
1339 ["tail0", "tail1", "tail2", "TAIL0", "TAIL1", "TAIL2"],
1340 [ el.tail for el in root ])
1341
1343 Element = self.etree.Element
1344 SubElement = self.etree.SubElement
1345 Comment = self.etree.Comment
1346
1347 a = Element('a')
1348 a.append(Comment('foo'))
1349 self.assertEqual(a[0].tag, Comment)
1350 self.assertEqual(a[0].text, 'foo')
1351
1352 # ElementTree < 1.3 adds whitespace around comments
1353 required_versions_ET['test_comment_text'] = (1,3)
1355 Element = self.etree.Element
1356 SubElement = self.etree.SubElement
1357 Comment = self.etree.Comment
1358 tostring = self.etree.tostring
1359
1360 a = Element('a')
1361 a.append(Comment('foo'))
1362 self.assertEqual(a[0].text, 'foo')
1363
1364 self.assertEqual(
1365 _bytes('<a><!--foo--></a>'),
1366 tostring(a))
1367
1368 a[0].text = "TEST"
1369 self.assertEqual(a[0].text, 'TEST')
1370
1371 self.assertEqual(
1372 _bytes('<a><!--TEST--></a>'),
1373 tostring(a))
1374
1375 # ElementTree < 1.3 adds whitespace around comments
1376 required_versions_ET['test_comment_whitespace'] = (1,3)
1378 Element = self.etree.Element
1379 SubElement = self.etree.SubElement
1380 Comment = self.etree.Comment
1381 tostring = self.etree.tostring
1382
1383 a = Element('a')
1384 a.append(Comment(' foo '))
1385 self.assertEqual(a[0].text, ' foo ')
1386 self.assertEqual(
1387 _bytes('<a><!-- foo --></a>'),
1388 tostring(a))
1389
1391 Comment = self.etree.Comment
1392 c = Comment('foo')
1393 self.assertEqual({}, c.attrib)
1394 self.assertEqual([], list(c.keys()))
1395 self.assertEqual([], list(c.items()))
1396 self.assertEqual(None, c.get('hoi'))
1397 self.assertEqual(0, len(c))
1398 # should not iterate
1399 for i in c:
1400 pass
1401
1403 # lxml.etree separates target and text
1404 Element = self.etree.Element
1405 SubElement = self.etree.SubElement
1406 ProcessingInstruction = self.etree.ProcessingInstruction
1407
1408 a = Element('a')
1409 a.append(ProcessingInstruction('foo', 'some more text'))
1410 self.assertEqual(a[0].tag, ProcessingInstruction)
1411 self.assertXML(_bytes("<a><?foo some more text?></a>"),
1412 a)
1413
1415 # lxml.etree separates target and text
1416 Element = self.etree.Element
1417 SubElement = self.etree.SubElement
1418 ProcessingInstruction = self.etree.PI
1419
1420 a = Element('a')
1421 a.append(ProcessingInstruction('foo', 'some more text'))
1422 self.assertEqual(a[0].tag, ProcessingInstruction)
1423 self.assertXML(_bytes("<a><?foo some more text?></a>"),
1424 a)
1425
1427 ProcessingInstruction = self.etree.ProcessingInstruction
1428 pi = ProcessingInstruction('foo')
1429 self.assertEqual({}, pi.attrib)
1430 self.assertEqual([], list(pi.keys()))
1431 self.assertEqual([], list(pi.items()))
1432 self.assertEqual(None, pi.get('hoi'))
1433 self.assertEqual(0, len(pi))
1434 # should not iterate
1435 for i in pi:
1436 pass
1437
1439 Element = self.etree.Element
1440 SubElement = self.etree.SubElement
1441
1442 a = Element('a')
1443 b = SubElement(a, 'b')
1444 c = Element('c')
1445 a[0] = c
1446 self.assertEqual(
1447 c,
1448 a[0])
1449 self.assertXML(_bytes('<a><c></c></a>'),
1450 a)
1451 self.assertXML(_bytes('<b></b>'),
1452 b)
1453
1455 Element = self.etree.Element
1456 SubElement = self.etree.SubElement
1457
1458 a = Element('a')
1459 for i in range(5):
1460 b = SubElement(a, 'b%s' % i)
1461 c = SubElement(b, 'c')
1462 for i in range(5):
1463 d = Element('d')
1464 e = SubElement(d, 'e')
1465 a[i] = d
1466 self.assertXML(
1467 _bytes('<a><d><e></e></d><d><e></e></d><d><e></e></d><d><e></e></d><d><e></e></d></a>'),
1468 a)
1469 self.assertXML(_bytes('<c></c>'),
1470 c)
1471
1473 Element = self.etree.Element
1474 SubElement = self.etree.SubElement
1475
1476 a = Element('a')
1477 SubElement(a, 'b')
1478 d = Element('d')
1479 a[0] = d
1480 self.assertXML(_bytes('<a><d></d></a>'), a)
1481
1483 Element = self.etree.Element
1484 SubElement = self.etree.SubElement
1485
1486 a = Element('a')
1487 b = SubElement(a, 'b')
1488
1489 self.assertRaises(IndexError, operator.setitem, a, 1, Element('c'))
1490
1492 Element = self.etree.Element
1493 SubElement = self.etree.SubElement
1494
1495 a = Element('a')
1496 b = SubElement(a, 'b')
1497 b.tail = 'B2'
1498 c = Element('c')
1499 c.tail = 'C2'
1500
1501 a[0] = c
1502 self.assertXML(
1503 _bytes('<a><c></c>C2</a>'),
1504 a)
1505
1507 Element = self.etree.Element
1508 SubElement = self.etree.SubElement
1509
1510 a = Element('a')
1511 b = SubElement(a, 'b')
1512
1513 a.tag = 'c'
1514
1515 self.assertEqual(
1516 'c',
1517 a.tag)
1518
1519 self.assertXML(
1520 _bytes('<c><b></b></c>'),
1521 a)
1522
1524 Element = self.etree.Element
1525 SubElement = self.etree.SubElement
1526 tostring = self.etree.tostring
1527
1528 a = Element('{a}a')
1529 b1 = SubElement(a, '{a}b')
1530 b2 = SubElement(a, '{b}b')
1531
1532 self.assertEqual('{a}b', b1.tag)
1533
1534 b1.tag = 'c'
1535
1536 # can't use C14N here!
1537 self.assertEqual('c', b1.tag)
1538 self.assertEqual(_bytes('<c'), tostring(b1)[:2])
1539 self.assertTrue(_bytes('<c') in tostring(a))
1540
1542 Element = self.etree.Element
1543 SubElement = self.etree.SubElement
1544 tostring = self.etree.tostring
1545
1546 a = Element('{a}a')
1547 b1 = SubElement(a, '{a}b')
1548 b2 = SubElement(a, '{b}b')
1549
1550 a.tag = 'c'
1551
1552 self.assertEqual(
1553 'c',
1554 a.tag)
1555
1556 # can't use C14N here!
1557 self.assertEqual('c', a.tag)
1558 self.assertEqual(_bytes('<c'), tostring(a)[:2])
1559
1565
1566 a = Element("a")
1567 a.tag = strTest("TAG")
1568 self.assertXML(_bytes('<TAG></TAG>'),
1569 a)
1570
1572 Element = self.etree.Element
1573 SubElement = self.etree.SubElement
1574
1575 a = Element('a')
1576 b = SubElement(a, 'b')
1577 c = SubElement(a, 'c')
1578 d = SubElement(a, 'd')
1579
1580 del a[1]
1581 self.assertXML(
1582 _bytes('<a><b></b><d></d></a>'),
1583 a)
1584
1585 del a[0]
1586 self.assertXML(
1587 _bytes('<a><d></d></a>'),
1588 a)
1589
1590 del a[0]
1591 self.assertXML(
1592 _bytes('<a></a>'),
1593 a)
1594 # move deleted element into other tree afterwards
1595 other = Element('other')
1596 other.append(c)
1597 self.assertXML(
1598 _bytes('<other><c></c></other>'),
1599 other)
1600
1602 Element = self.etree.Element
1603 SubElement = self.etree.SubElement
1604
1605 a = Element('a')
1606 b = SubElement(a, 'b')
1607 bs = SubElement(b, 'bs')
1608 c = SubElement(a, 'c')
1609 cs = SubElement(c, 'cs')
1610
1611 el = a[0]
1612 self.assertXML(
1613 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1614 a)
1615 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1616 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1617
1618 del a[0]
1619 self.assertXML(
1620 _bytes('<a><c><cs></cs></c></a>'),
1621 a)
1622 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1623 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1624
1625 a.insert(0, el)
1626 self.assertXML(
1627 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1628 a)
1629 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1630 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1631
1633 Element = self.etree.Element
1634 SubElement = self.etree.SubElement
1635
1636 a = Element('a')
1637 b = SubElement(a, 'b')
1638 bs = SubElement(b, 'bs')
1639 c = SubElement(a, 'c')
1640 cs = SubElement(c, 'cs')
1641
1642 el = a[0]
1643 del a[0]
1644 a[0] = el
1645 self.assertXML(
1646 _bytes('<a><b><bs></bs></b></a>'),
1647 a)
1648 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1649 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1650
1652 Element = self.etree.Element
1653 SubElement = self.etree.SubElement
1654
1655 a = Element('a')
1656 b = SubElement(a, 'b')
1657 bs = SubElement(b, 'bs')
1658 c = SubElement(a, 'c')
1659 cs = SubElement(c, 'cs')
1660
1661 el = a[0]
1662 del a[0]
1663 a[0:0] = [el]
1664 self.assertXML(
1665 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1666 a)
1667 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1668 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1669
1671 XML = self.etree.XML
1672 a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
1673 b, c = a
1674
1675 a[:] = []
1676
1677 self.assertEqual("B2", b.tail)
1678 self.assertEqual("C2", c.tail)
1679
1681 XML = self.etree.XML
1682 root = XML(_bytes(
1683 '<foo><bar xmlns:baz="http://huhu"><puh><baz:bump1 /><baz:bump2 /></puh></bar></foo>'))
1684 root[:] = root.findall('.//puh') # delete bar from hierarchy
1685
1686 # previously, this lost a namespace declaration on bump2
1687 result = self.etree.tostring(root)
1688 foo = self.etree.fromstring(result)
1689
1690 self.assertEqual('puh', foo[0].tag)
1691 self.assertEqual('{http://huhu}bump1', foo[0][0].tag)
1692 self.assertEqual('{http://huhu}bump2', foo[0][1].tag)
1693
1695 ElementTree = self.etree.ElementTree
1696 f = BytesIO('<a><b></b>B2<c></c>C2</a>')
1697 doc = ElementTree(file=f)
1698 a = doc.getroot()
1699 del a[0]
1700 self.assertXML(
1701 _bytes('<a><c></c>C2</a>'),
1702 a)
1703
1705 ElementTree = self.etree.ElementTree
1706 f = BytesIO('<a><b></b>B2<c></c>C2</a>')
1707 doc = ElementTree(file=f)
1708 a = doc.getroot()
1709 b, c = a
1710 del a[0]
1711 self.assertXML(
1712 _bytes('<a><c></c>C2</a>'),
1713 a)
1714 self.assertEqual("B2", b.tail)
1715 self.assertEqual("C2", c.tail)
1716
1718 Element = self.etree.Element
1719
1720 a = Element('a')
1721 a.text = 'foo'
1722 a.tail = 'bar'
1723 a.set('hoi', 'dag')
1724 a.clear()
1725 self.assertEqual(None, a.text)
1726 self.assertEqual(None, a.tail)
1727 self.assertEqual(None, a.get('hoi'))
1728 self.assertEqual('a', a.tag)
1729
1731 Element = self.etree.Element
1732 SubElement = self.etree.SubElement
1733
1734 a = Element('a')
1735 a.text = 'foo'
1736 a.tail = 'bar'
1737 a.set('hoi', 'dag')
1738 b = SubElement(a, 'b')
1739 c = SubElement(b, 'c')
1740 a.clear()
1741 self.assertEqual(None, a.text)
1742 self.assertEqual(None, a.tail)
1743 self.assertEqual(None, a.get('hoi'))
1744 self.assertEqual('a', a.tag)
1745 self.assertEqual(0, len(a))
1746 self.assertXML(_bytes('<a></a>'),
1747 a)
1748 self.assertXML(_bytes('<b><c></c></b>'),
1749 b)
1750
1752 ElementTree = self.etree.ElementTree
1753 f = BytesIO('<a><b></b>B2<c></c>C2</a>')
1754 doc = ElementTree(file=f)
1755 a = doc.getroot()
1756 a.clear()
1757 self.assertXML(
1758 _bytes('<a></a>'),
1759 a)
1760
1762 Element = self.etree.Element
1763 SubElement = self.etree.SubElement
1764
1765 a = Element('a')
1766 b = SubElement(a, 'b')
1767 c = SubElement(a, 'c')
1768 d = Element('d')
1769 a.insert(0, d)
1770
1771 self.assertEqual(
1772 d,
1773 a[0])
1774
1775 self.assertXML(
1776 _bytes('<a><d></d><b></b><c></c></a>'),
1777 a)
1778
1779 e = Element('e')
1780 a.insert(2, e)
1781 self.assertEqual(
1782 e,
1783 a[2])
1784 self.assertXML(
1785 _bytes('<a><d></d><b></b><e></e><c></c></a>'),
1786 a)
1787
1789 # See GH#268 / LP#1773749.
1790 Element = self.etree.Element
1791 SubElement = self.etree.SubElement
1792
1793 # Use unique names to make sure they are new in the tag name dict.
1794 import uuid
1795 names = dict((k, 'tag-' + str(uuid.uuid4())) for k in 'abcde')
1796
1797 a = Element(names['a'])
1798 b = SubElement(a, names['b'])
1799 c = SubElement(a, names['c'])
1800 d = Element(names['d'])
1801 a.insert(0, d)
1802
1803 self.assertEqual(
1804 d,
1805 a[0])
1806
1807 self.assertXML(
1808 _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(c)s></%(c)s></%(a)s>' % names),
1809 a)
1810
1811 e = Element(names['e'])
1812 a.insert(2, e)
1813 self.assertEqual(
1814 e,
1815 a[2])
1816 self.assertXML(
1817 _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(e)s></%(e)s><%(c)s></%(c)s></%(a)s>' % names),
1818 a)
1819
1821 Element = self.etree.Element
1822 SubElement = self.etree.SubElement
1823
1824 a = Element('a')
1825 b = SubElement(a, 'b')
1826 c = Element('c')
1827
1828 a.insert(2, c)
1829 self.assertEqual(
1830 c,
1831 a[1])
1832 self.assertXML(
1833 _bytes('<a><b></b><c></c></a>'),
1834 a)
1835
1837 Element = self.etree.Element
1838 SubElement = self.etree.SubElement
1839
1840 a = Element('a')
1841 b = SubElement(a, 'b')
1842 c = SubElement(a, 'c')
1843
1844 d = Element('d')
1845 a.insert(-1, d)
1846 self.assertEqual(
1847 d,
1848 a[-2])
1849 self.assertXML(
1850 _bytes('<a><b></b><d></d><c></c></a>'),
1851 a)
1852
1854 Element = self.etree.Element
1855 SubElement = self.etree.SubElement
1856
1857 a = Element('a')
1858 b = SubElement(a, 'b')
1859
1860 c = Element('c')
1861 c.tail = 'C2'
1862
1863 a.insert(0, c)
1864 self.assertXML(
1865 _bytes('<a><c></c>C2<b></b></a>'),
1866 a)
1867
1869 Element = self.etree.Element
1870 SubElement = self.etree.SubElement
1871
1872 a = Element('a')
1873 b = SubElement(a, 'b')
1874 c = SubElement(a, 'c')
1875
1876 a.remove(b)
1877 self.assertEqual(
1878 c,
1879 a[0])
1880 self.assertXML(
1881 _bytes('<a><c></c></a>'),
1882 a)
1883
1885 Element = self.etree.Element
1886 SubElement = self.etree.SubElement
1887
1888 a = Element('{http://test}a')
1889 b = SubElement(a, '{http://test}b')
1890 c = SubElement(a, '{http://test}c')
1891
1892 a.remove(b)
1893 self.assertXML(
1894 _bytes('<ns0:a xmlns:ns0="http://test"><ns0:c></ns0:c></ns0:a>'),
1895 a)
1896 self.assertXML(
1897 _bytes('<ns0:b xmlns:ns0="http://test"></ns0:b>'),
1898 b)
1899
1901 Element = self.etree.Element
1902 SubElement = self.etree.SubElement
1903
1904 a = Element('a')
1905 b = SubElement(a, 'b')
1906 c = SubElement(a, 'c')
1907 d = Element('d')
1908 self.assertRaises(
1909 ValueError, a.remove, d)
1910
1912 Element = self.etree.Element
1913 SubElement = self.etree.SubElement
1914
1915 a = Element('a')
1916 b = SubElement(a, 'b')
1917 b.tail = 'b2'
1918 a.remove(b)
1919 self.assertXML(
1920 _bytes('<a></a>'),
1921 a)
1922 self.assertEqual('b2', b.tail)
1923
1925 # There is no guarantee that this "works", but it should
1926 # remove at least one child and not crash.
1927 Element = self.etree.Element
1928 SubElement = self.etree.SubElement
1929
1930 a = Element('a')
1931 SubElement(a, 'b')
1932 SubElement(a, 'c')
1933 SubElement(a, 'd')
1934 for el in a:
1935 a.remove(el)
1936 self.assertLess(len(a), 3)
1937
1939 Element = self.etree.Element
1940
1941 a = Element('a')
1942 b = a.makeelement('c', {'hoi':'dag'})
1943 self.assertXML(
1944 _bytes('<c hoi="dag"></c>'),
1945 b)
1946
1947 required_versions_ET['test_iter'] = (1,3)
1949 Element = self.etree.Element
1950 SubElement = self.etree.SubElement
1951
1952 a = Element('a')
1953 b = SubElement(a, 'b')
1954 c = SubElement(a, 'c')
1955 d = SubElement(b, 'd')
1956 e = SubElement(c, 'e')
1957
1958 self.assertEqual(
1959 [a, b, d, c, e],
1960 list(a.iter()))
1961 self.assertEqual(
1962 [d],
1963 list(d.iter()))
1964
1966 Element = self.etree.Element
1967 SubElement = self.etree.SubElement
1968
1969 a = Element('a')
1970 a.text = 'a'
1971 a.tail = 'a1' * 100
1972 b = SubElement(a, 'b')
1973 b.text = 'b'
1974 b.tail = 'b1' * 100
1975 c = SubElement(a, 'c')
1976 c.text = 'c'
1977 c.tail = 'c1' * 100
1978 d = SubElement(b, 'd')
1979 d.text = 'd'
1980 d.tail = 'd1' * 100
1981 e = SubElement(c, 'e')
1982 e.text = 'e'
1983 e.tail = 'e1' * 100
1984
1985 for el in a.iter():
1986 el.tail = None
1987 el = None
1988
1989 self.assertEqual(
1990 [None] * 5,
1991 [el.tail for el in a.iter()])
1992
1994 Element = self.etree.Element
1995 SubElement = self.etree.SubElement
1996
1997 a = Element('a')
1998 b = SubElement(a, 'b')
1999 c = SubElement(a, 'c')
2000 d = SubElement(a, 'd')
2001
2002 self.assertEqual(
2003 [b, c],
2004 a[0:2])
2005 self.assertEqual(
2006 [b, c, d],
2007 a[:])
2008 self.assertEqual(
2009 [b, c, d],
2010 a[:10])
2011 self.assertEqual(
2012 [b],
2013 a[0:1])
2014 self.assertEqual(
2015 [],
2016 a[10:12])
2017
2019 Element = self.etree.Element
2020 SubElement = self.etree.SubElement
2021
2022 a = Element('a')
2023 b = SubElement(a, 'b')
2024 c = SubElement(a, 'c')
2025 d = SubElement(a, 'd')
2026
2027 self.assertEqual(
2028 [d],
2029 a[-1:])
2030 self.assertEqual(
2031 [c, d],
2032 a[-2:])
2033 self.assertEqual(
2034 [c],
2035 a[-2:-1])
2036 self.assertEqual(
2037 [b, c],
2038 a[-3:-1])
2039 self.assertEqual(
2040 [b, c],
2041 a[-3:2])
2042
2044 Element = self.etree.Element
2045 SubElement = self.etree.SubElement
2046
2047 a = Element('a')
2048 b = SubElement(a, 'b')
2049 c = SubElement(a, 'c')
2050 d = SubElement(a, 'd')
2051 e = SubElement(a, 'e')
2052
2053 self.assertEqual(
2054 [e,d,c,b],
2055 a[::-1])
2056 self.assertEqual(
2057 [b,d],
2058 a[::2])
2059 self.assertEqual(
2060 [e,c],
2061 a[::-2])
2062 self.assertEqual(
2063 [d,c],
2064 a[-2:0:-1])
2065 self.assertEqual(
2066 [e],
2067 a[:1:-2])
2068
2070 ElementTree = self.etree.ElementTree
2071
2072 f = BytesIO('<a><b>B</b>B1<c>C</c>C1</a>')
2073 doc = ElementTree(file=f)
2074 a = doc.getroot()
2075 b = a[0]
2076 c = a[1]
2077 self.assertEqual(
2078 [b, c],
2079 a[:])
2080 self.assertEqual(
2081 [b],
2082 a[0:1])
2083 self.assertEqual(
2084 [c],
2085 a[1:])
2086
2088 Element = self.etree.Element
2089 Comment = self.etree.Comment
2090 SubElement = self.etree.SubElement
2091
2092 a = Element('a')
2093 b = SubElement(a, 'b')
2094 foo = Comment('foo')
2095 a.append(foo)
2096 c = SubElement(a, 'c')
2097 self.assertEqual(
2098 [b, foo, c],
2099 a[:])
2100 self.assertEqual(
2101 foo,
2102 a[1])
2103 a[1] = new = Element('new')
2104 self.assertEqual(
2105 new,
2106 a[1])
2107 self.assertXML(
2108 _bytes('<a><b></b><new></new><c></c></a>'),
2109 a)
2110
2112 Element = self.etree.Element
2113 SubElement = self.etree.SubElement
2114
2115 a = Element('a')
2116 b = SubElement(a, 'b')
2117 c = SubElement(a, 'c')
2118 d = SubElement(a, 'd')
2119 e = SubElement(a, 'e')
2120
2121 del a[1:3]
2122 self.assertEqual(
2123 [b, e],
2124 list(a))
2125
2127 Element = self.etree.Element
2128 SubElement = self.etree.SubElement
2129
2130 a = Element('a')
2131 b = SubElement(a, 'b')
2132 c = SubElement(a, 'c')
2133 d = SubElement(a, 'd')
2134 e = SubElement(a, 'e')
2135
2136 del a[1:-1]
2137 self.assertEqual(
2138 [b, e],
2139 list(a))
2140
2142 Element = self.etree.Element
2143 SubElement = self.etree.SubElement
2144
2145 a = Element('a')
2146 b = SubElement(a, 'b')
2147 c = SubElement(a, 'c')
2148 d = SubElement(a, 'd')
2149 e = SubElement(a, 'e')
2150
2151 del a[-3:-1]
2152 self.assertEqual(
2153 [b, e],
2154 list(a))
2155
2157 Element = self.etree.Element
2158 SubElement = self.etree.SubElement
2159
2160 a = Element('a')
2161 b = SubElement(a, 'b')
2162 c = SubElement(a, 'c')
2163 d = SubElement(a, 'd')
2164 e = SubElement(a, 'e')
2165
2166 del a[1::2]
2167 self.assertEqual(
2168 [b, d],
2169 list(a))
2170
2172 Element = self.etree.Element
2173 SubElement = self.etree.SubElement
2174
2175 a = Element('a')
2176 b = SubElement(a, 'b')
2177 c = SubElement(a, 'c')
2178 d = SubElement(a, 'd')
2179 e = SubElement(a, 'e')
2180
2181 del a[::-1]
2182 self.assertEqual(
2183 [],
2184 list(a))
2185
2187 Element = self.etree.Element
2188 SubElement = self.etree.SubElement
2189
2190 a = Element('a')
2191 b = SubElement(a, 'b')
2192 c = SubElement(a, 'c')
2193 d = SubElement(a, 'd')
2194 e = SubElement(a, 'e')
2195
2196 del a[::-2]
2197 self.assertEqual(
2198 [b, d],
2199 list(a))
2200
2202 ElementTree = self.etree.ElementTree
2203 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2204 doc = ElementTree(file=f)
2205 a = doc.getroot()
2206 del a[1:3]
2207 self.assertXML(
2208 _bytes('<a><b></b>B2<e></e>E2</a>'),
2209 a)
2210
2212 ElementTree = self.etree.ElementTree
2213 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2214 doc = ElementTree(file=f)
2215 a = doc.getroot()
2216 b, c, d, e = a
2217 del a[1:3]
2218 self.assertXML(
2219 _bytes('<a><b></b>B2<e></e>E2</a>'),
2220 a)
2221 self.assertEqual("B2", b.tail)
2222 self.assertEqual("C2", c.tail)
2223 self.assertEqual("D2", d.tail)
2224 self.assertEqual("E2", e.tail)
2225
2227 XML = self.etree.XML
2228 a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
2229 b, c = a
2230
2231 del a[:]
2232
2233 self.assertEqual("B2", b.tail)
2234 self.assertEqual("C2", c.tail)
2235
2237 # this could trigger a crash
2238 Element = self.etree.Element
2239 SubElement = self.etree.SubElement
2240 a = Element('a')
2241 b = SubElement(a, 'b')
2242 c = SubElement(b, 'c')
2243 del b # no more reference to b
2244 del a[:]
2245 self.assertEqual('c', c.tag)
2246
2248 Element = self.etree.Element
2249 SubElement = self.etree.SubElement
2250
2251 a = Element('a')
2252 b = SubElement(a, 'b')
2253 c = SubElement(a, 'c')
2254 d = SubElement(a, 'd')
2255
2256 e = Element('e')
2257 f = Element('f')
2258 g = Element('g')
2259
2260 s = [e, f, g]
2261 a[1:2] = s
2262 self.assertEqual(
2263 [b, e, f, g, d],
2264 list(a))
2265
2267 Element = self.etree.Element
2268 SubElement = self.etree.SubElement
2269
2270 a = Element('a')
2271 b = SubElement(a, 'b')
2272 c = SubElement(a, 'c')
2273
2274 e = Element('e')
2275 f = Element('f')
2276 g = Element('g')
2277
2278 s = [e, f, g]
2279 a[:] = s
2280 self.assertEqual(
2281 [e, f, g],
2282 list(a))
2283
2285 Element = self.etree.Element
2286 SubElement = self.etree.SubElement
2287
2288 a = Element('a')
2289
2290 e = Element('e')
2291 f = Element('f')
2292 g = Element('g')
2293
2294 s = [e, f, g]
2295 a[:] = s
2296 self.assertEqual(
2297 [e, f, g],
2298 list(a))
2299
2301 Element = self.etree.Element
2302 SubElement = self.etree.SubElement
2303
2304 a = Element('a')
2305 b = SubElement(a, 'b')
2306 c = SubElement(a, 'c')
2307 d = SubElement(a, 'd')
2308
2309 s = [b, c, d]
2310 a[:] = s
2311 self.assertEqual(
2312 [b, c, d],
2313 list(a))
2314
2316 Element = self.etree.Element
2317 SubElement = self.etree.SubElement
2318
2319 a = Element('a')
2320 b = SubElement(a, 'b')
2321 c = SubElement(a, 'c')
2322 d = SubElement(a, 'd')
2323
2324 s = [d, c, b]
2325 a[:] = s
2326 self.assertEqual(
2327 [d, c, b],
2328 list(a))
2329
2331 Element = self.etree.Element
2332 SubElement = self.etree.SubElement
2333
2334 a = Element('{ns}a')
2335 b = SubElement(a, '{ns}b', {'{ns1}a1': 'test'})
2336 c = SubElement(a, '{ns}c', {'{ns2}a2': 'test'})
2337 d = SubElement(a, '{ns}d', {'{ns3}a3': 'test'})
2338
2339 s = [d, c, b]
2340 a[:] = s
2341 self.assertEqual(
2342 [d, c, b],
2343 list(a))
2344 self.assertEqual(
2345 ['{ns}d', '{ns}c', '{ns}b'],
2346 [ child.tag for child in a ])
2347
2348 self.assertEqual(
2349 [['{ns3}a3'], ['{ns2}a2'], ['{ns1}a1']],
2350 [ list(child.attrib.keys()) for child in a ])
2351
2353 Element = self.etree.Element
2354 SubElement = self.etree.SubElement
2355
2356 a = Element('{ns}a')
2357 b = SubElement(a, '{ns1}b', {'{ns}a1': 'test'})
2358 c = SubElement(a, '{ns2}c', {'{ns}a2': 'test'})
2359 d = SubElement(a, '{ns3}d', {'{ns}a3': 'test'})
2360
2361 s = [d, c, b]
2362 a[:] = s
2363 self.assertEqual(
2364 [d, c, b],
2365 list(a))
2366 self.assertEqual(
2367 ['{ns3}d', '{ns2}c', '{ns1}b'],
2368 [ child.tag for child in a ])
2369
2370 self.assertEqual(
2371 [['{ns}a3'], ['{ns}a2'], ['{ns}a1']],
2372 [ list(child.attrib.keys()) for child in a ])
2373
2375 Element = self.etree.Element
2376 SubElement = self.etree.SubElement
2377
2378 a = Element('a')
2379 b = SubElement(a, 'b')
2380 c = SubElement(a, 'c')
2381
2382 e = Element('e')
2383 f = Element('f')
2384 g = Element('g')
2385 h = Element('h')
2386
2387 s = [e, f]
2388 a[99:] = s
2389 self.assertEqual(
2390 [b, c, e, f],
2391 list(a))
2392
2393 s = [g, h]
2394 a[:0] = s
2395 self.assertEqual(
2396 [g, h, b, c, e, f],
2397 list(a))
2398
2400 Element = self.etree.Element
2401 SubElement = self.etree.SubElement
2402
2403 a = Element('a')
2404 b = SubElement(a, 'b')
2405 c = SubElement(a, 'c')
2406 d = SubElement(a, 'd')
2407
2408 e = Element('e')
2409 f = Element('f')
2410 g = Element('g')
2411
2412 s = [e, f, g]
2413 a[3:] = s
2414 self.assertEqual(
2415 [b, c, d, e, f, g],
2416 list(a))
2417
2419 Element = self.etree.Element
2420 SubElement = self.etree.SubElement
2421
2422 a = Element('a')
2423 b = SubElement(a, 'b')
2424 c = SubElement(a, 'c')
2425
2426 e = Element('e')
2427 f = Element('f')
2428
2429 s = [e]
2430 a[0:1] = s
2431 self.assertEqual(
2432 [e, c],
2433 list(a))
2434
2435 s = [f]
2436 a[1:2] = s
2437 self.assertEqual(
2438 [e, f],
2439 list(a))
2440
2442 ElementTree = self.etree.ElementTree
2443 Element = self.etree.Element
2444 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2445 doc = ElementTree(file=f)
2446 a = doc.getroot()
2447 x = Element('x')
2448 y = Element('y')
2449 z = Element('z')
2450 x.tail = 'X2'
2451 y.tail = 'Y2'
2452 z.tail = 'Z2'
2453 a[1:3] = [x, y, z]
2454 self.assertXML(
2455 _bytes('<a><b></b>B2<x></x>X2<y></y>Y2<z></z>Z2<e></e>E2</a>'),
2456 a)
2457
2459 Element = self.etree.Element
2460 SubElement = self.etree.SubElement
2461
2462 a = Element('a')
2463 b = SubElement(a, 'b')
2464 c = SubElement(a, 'c')
2465 d = SubElement(a, 'd')
2466
2467 x = Element('x')
2468 y = Element('y')
2469
2470 a[1:-1] = [x, y]
2471 self.assertEqual(
2472 [b, x, y, d],
2473 list(a))
2474
2476 Element = self.etree.Element
2477 SubElement = self.etree.SubElement
2478
2479 a = Element('a')
2480 b = SubElement(a, 'b')
2481 c = SubElement(a, 'c')
2482 d = SubElement(a, 'd')
2483
2484 x = Element('x')
2485 y = Element('y')
2486
2487 a[1:-2] = [x, y]
2488 self.assertEqual(
2489 [b, x, y, c, d],
2490 list(a))
2491
2493 Element = self.etree.Element
2494
2495 a = Element('a')
2496
2497 b = Element('b')
2498 c = Element('c')
2499
2500 a[:] = [b, c]
2501 self.assertEqual(
2502 [b, c],
2503 list(a))
2504
2506 Element = self.etree.Element
2507 ElementTree = self.etree.ElementTree
2508
2509 a = Element('a')
2510 a.tail = 'A2'
2511 t = ElementTree(element=a)
2512 self.assertEqual('A2',
2513 a.tail)
2514
2516 ElementTree = self.etree.ElementTree
2517 ns = 'http://xml.infrae.com/1'
2518 f = BytesIO('<x:a xmlns:x="%s"><x:b></x:b></x:a>' % ns)
2519 t = ElementTree(file=f)
2520 a = t.getroot()
2521 self.assertEqual('{%s}a' % ns,
2522 a.tag)
2523 self.assertEqual('{%s}b' % ns,
2524 a[0].tag)
2525
2527 ElementTree = self.etree.ElementTree
2528 ns = 'http://xml.infrae.com/1'
2529 ns2 = 'http://xml.infrae.com/2'
2530 f = BytesIO('<x:a xmlns:x="%s" xmlns:y="%s"><x:b></x:b><y:b></y:b></x:a>' % (ns, ns2))
2531 t = ElementTree(file=f)
2532 a = t.getroot()
2533 self.assertEqual('{%s}a' % ns,
2534 a.tag)
2535 self.assertEqual('{%s}b' % ns,
2536 a[0].tag)
2537 self.assertEqual('{%s}b' % ns2,
2538 a[1].tag)
2539
2541 Element = self.etree.Element
2542 SubElement = self.etree.SubElement
2543 ns = 'http://xml.infrae.com/1'
2544 ns2 = 'http://xml.infrae.com/2'
2545 a = Element('{%s}a' % ns)
2546 b = SubElement(a, '{%s}b' % ns2)
2547 c = SubElement(a, '{%s}c' % ns)
2548 self.assertEqual('{%s}a' % ns,
2549 a.tag)
2550 self.assertEqual('{%s}b' % ns2,
2551 b.tag)
2552 self.assertEqual('{%s}c' % ns,
2553 c.tag)
2554 self.assertEqual('{%s}a' % ns,
2555 a.tag)
2556 self.assertEqual('{%s}b' % ns2,
2557 b.tag)
2558 self.assertEqual('{%s}c' % ns,
2559 c.tag)
2560
2562 Element = self.etree.Element
2563 SubElement = self.etree.SubElement
2564 ElementTree = self.etree.ElementTree
2565
2566 ns = 'http://xml.infrae.com/1'
2567 ns2 = 'http://xml.infrae.com/2'
2568 f = BytesIO('<a xmlns="%s" xmlns:x="%s"><x:b></x:b><b></b></a>' % (ns, ns2))
2569 t = ElementTree(file=f)
2570
2571 a = t.getroot()
2572 self.assertEqual('{%s}a' % ns,
2573 a.tag)
2574 self.assertEqual('{%s}b' % ns2,
2575 a[0].tag)
2576 self.assertEqual('{%s}b' % ns,
2577 a[1].tag)
2578
2580 Element = self.etree.Element
2581 ns = 'http://xml.infrae.com/1'
2582 ns2 = 'http://xml.infrae.com/2'
2583 a = Element('a')
2584 a.set('{%s}foo' % ns, 'Foo')
2585 a.set('{%s}bar' % ns2, 'Bar')
2586 self.assertEqual(
2587 'Foo',
2588 a.get('{%s}foo' % ns))
2589 self.assertEqual(
2590 'Bar',
2591 a.get('{%s}bar' % ns2))
2592 try:
2593 self.assertXML(
2594 _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns0:foo="Foo" ns1:bar="Bar"></a>' % (ns, ns2)),
2595 a)
2596 except AssertionError:
2597 self.assertXML(
2598 _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns1:foo="Foo" ns0:bar="Bar"></a>' % (ns2, ns)),
2599 a)
2600
2602 Element = self.etree.Element
2603 one = self.etree.fromstring(
2604 _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
2605 baz = one[0][0]
2606
2607 two = Element('root')
2608 two.append(baz)
2609 # removing the originating document could cause a crash/error before
2610 # as namespace is not moved along with it
2611 del one, baz
2612 self.assertEqual('{http://a.b.c}baz', two[0].tag)
2613
2615 tostring = self.etree.tostring
2616 root = self.etree.XML(
2617 _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
2618 baz = root[0][0]
2619
2620 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2621 tostring(baz))
2622 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2623
2625 tostring = self.etree.tostring
2626 root = self.etree.XML(
2627 _bytes('<foo><bar xmlns="http://a.b.c"><baz/></bar></foo>'))
2628 baz = root[0][0]
2629
2630 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2631 tostring(baz))
2632 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2633
2635 tostring = self.etree.tostring
2636 root = self.etree.XML(
2637 _bytes('<foo xmlns:ns="http://a.b.c"><bar><ns:baz/></bar></foo>'))
2638 baz = root[0][0]
2639
2640 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2641 tostring(baz))
2642
2643 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2644
2646 Element = self.etree.Element
2647 SubElement = self.etree.SubElement
2648
2649 root = Element("foo")
2650 bar = SubElement(root, "{http://a.b.c}bar")
2651 baz = SubElement(bar, "{http://a.b.c}baz")
2652
2653 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2654 self.etree.tostring(baz))
2655
2656 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2657
2659 Element = self.etree.Element
2660
2661 root = Element('element')
2662
2663 subelement = Element('subelement',
2664 {"{http://www.w3.org/XML/1998/namespace}id": "foo"})
2665 self.assertEqual(1, len(subelement.attrib))
2666 self.assertEqual(
2667 "foo",
2668 subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
2669
2670 root.append(subelement)
2671 self.assertEqual(1, len(subelement.attrib))
2672 self.assertEqual(
2673 list({"{http://www.w3.org/XML/1998/namespace}id" : "foo"}.items()),
2674 list(subelement.attrib.items()))
2675 self.assertEqual(
2676 "foo",
2677 subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
2678
2680 parse = self.etree.parse
2681 tostring = self.etree.tostring
2682
2683 ns_href = "http://a.b.c"
2684 one = parse(
2685 BytesIO('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2686 baz = one.getroot()[0][0]
2687
2688 parsed = parse(BytesIO( tostring(baz) )).getroot()
2689 self.assertEqual('{%s}baz' % ns_href, parsed.tag)
2690
2692 fromstring = self.etree.fromstring
2693 tostring = self.etree.tostring
2694
2695 ns_href = "http://a.b.c"
2696 xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
2697 ns_href,ns_href))
2698 root = fromstring(xml)
2699 self.assertEqual('test', root[0].get('{%s}a' % ns_href))
2700
2701 xml2 = tostring(root)
2702 self.assertTrue(_bytes(':a=') in xml2, xml2)
2703
2704 root2 = fromstring(xml2)
2705 self.assertEqual('test', root2[0].get('{%s}a' % ns_href))
2706
2708 fromstring = self.etree.fromstring
2709 tostring = self.etree.tostring
2710
2711 ns_href = "http://a.b.c"
2712 xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
2713 ns_href,ns_href))
2714 root = fromstring(xml)
2715 self.assertEqual('test', root[0].get('{%s}a' % ns_href))
2716
2717 root[0].set('{%s}a' % ns_href, 'TEST')
2718
2719 xml2 = tostring(root)
2720 self.assertTrue(_bytes(':a=') in xml2, xml2)
2721
2722 root2 = fromstring(xml2)
2723 self.assertEqual('TEST', root2[0].get('{%s}a' % ns_href))
2724
2725 required_versions_ET['test_register_namespace'] = (1,3)
2727 # ET 1.3+
2728 Element = self.etree.Element
2729 prefix = 'TESTPREFIX'
2730 namespace = 'http://seriously.unknown/namespace/URI'
2731
2732 el = Element('{%s}test' % namespace)
2733 self.assertEqual(_bytes('<ns0:test xmlns:ns0="%s"></ns0:test>' % namespace),
2734 self._writeElement(el))
2735
2736 self.etree.register_namespace(prefix, namespace)
2737 el = Element('{%s}test' % namespace)
2738 self.assertEqual(_bytes('<%s:test xmlns:%s="%s"></%s:test>' % (
2739 prefix, prefix, namespace, prefix)),
2740 self._writeElement(el))
2741
2742 self.assertRaises(ValueError, self.etree.register_namespace, 'ns25', namespace)
2743
2745 tostring = self.etree.tostring
2746 Element = self.etree.Element
2747 SubElement = self.etree.SubElement
2748
2749 a = Element('a')
2750 b = SubElement(a, 'b')
2751 c = SubElement(a, 'c')
2752
2753 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
2754 canonicalize(tostring(a)))
2755
2757 tostring = self.etree.tostring
2758 Element = self.etree.Element
2759 SubElement = self.etree.SubElement
2760
2761 a = Element('a')
2762 b = SubElement(a, 'b')
2763 c = SubElement(a, 'c')
2764 d = SubElement(c, 'd')
2765 self.assertEqual(_bytes('<b></b>'),
2766 canonicalize(tostring(b)))
2767 self.assertEqual(_bytes('<c><d></d></c>'),
2768 canonicalize(tostring(c)))
2769
2771 tostring = self.etree.tostring
2772 Element = self.etree.Element
2773 SubElement = self.etree.SubElement
2774
2775 a = Element('a')
2776 b = SubElement(a, 'b')
2777 c = SubElement(a, 'c')
2778 d = SubElement(c, 'd')
2779 b.tail = 'Foo'
2780
2781 self.assertTrue(tostring(b) == _bytes('<b/>Foo') or
2782 tostring(b) == _bytes('<b />Foo'))
2783
2784 required_versions_ET['test_tostring_method_html'] = (1,3)
2786 tostring = self.etree.tostring
2787 Element = self.etree.Element
2788 SubElement = self.etree.SubElement
2789
2790 html = Element('html')
2791 body = SubElement(html, 'body')
2792 p = SubElement(body, 'p')
2793 p.text = "html"
2794 SubElement(p, 'br').tail = "test"
2795
2796 self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
2797 tostring(html, method="html"))
2798
2799 required_versions_ET['test_tostring_method_text'] = (1,3)
2801 tostring = self.etree.tostring
2802 Element = self.etree.Element
2803 SubElement = self.etree.SubElement
2804
2805 a = Element('a')
2806 a.text = "A"
2807 a.tail = "tail"
2808 b = SubElement(a, 'b')
2809 b.text = "B"
2810 b.tail = "TAIL"
2811 c = SubElement(a, 'c')
2812 c.text = "C"
2813
2814 self.assertEqual(_bytes('ABTAILCtail'),
2815 tostring(a, method="text"))
2816
2818 iterparse = self.etree.iterparse
2819 f = BytesIO('<a><b></b><c/></a>')
2820
2821 iterator = iterparse(f)
2822 self.assertEqual(None,
2823 iterator.root)
2824 events = list(iterator)
2825 root = iterator.root
2826 self.assertEqual(
2827 [('end', root[0]), ('end', root[1]), ('end', root)],
2828 events)
2829
2831 iterparse = self.etree.iterparse
2832 f = BytesIO('<a><b></b><c/></a>')
2833
2834 iterator = iterparse(f)
2835 self.assertEqual(None,
2836 iterator.root)
2837 event, element = next(iter(iterator))
2838 self.assertEqual('end', event)
2839 self.assertEqual('b', element.tag)
2840
2842 iterparse = self.etree.iterparse
2843 iterator = iterparse(fileInTestDir("test.xml"))
2844 self.assertEqual(None,
2845 iterator.root)
2846 events = list(iterator)
2847 root = iterator.root
2848 self.assertEqual(
2849 [('end', root[0]), ('end', root)],
2850 events)
2851
2853 iterparse = self.etree.iterparse
2854 f = BytesIO('<a><b></b><c/></a>')
2855
2856 iterator = iterparse(f, events=('start',))
2857 events = list(iterator)
2858 root = iterator.root
2859 self.assertEqual(
2860 [('start', root), ('start', root[0]), ('start', root[1])],
2861 events)
2862
2864 iterparse = self.etree.iterparse
2865 f = BytesIO('<a><b></b><c/></a>')
2866
2867 iterator = iterparse(f, events=('start','end'))
2868 events = list(iterator)
2869 root = iterator.root
2870 self.assertEqual(
2871 [('start', root), ('start', root[0]), ('end', root[0]),
2872 ('start', root[1]), ('end', root[1]), ('end', root)],
2873 events)
2874
2876 iterparse = self.etree.iterparse
2877 f = BytesIO('<a><b></b><c/></a>')
2878
2879 iterator = iterparse(f)
2880 for event, elem in iterator:
2881 elem.clear()
2882
2883 root = iterator.root
2884 self.assertEqual(0,
2885 len(root))
2886
2888 iterparse = self.etree.iterparse
2889 CHILD_COUNT = 12345
2890 f = BytesIO('<a>%s</a>' % ('<b>test</b>'*CHILD_COUNT))
2891
2892 i = 0
2893 for key in iterparse(f):
2894 event, element = key
2895 i += 1
2896 self.assertEqual(i, CHILD_COUNT + 1)
2897
2899 iterparse = self.etree.iterparse
2900 f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
2901
2902 attr_name = '{http://testns/}bla'
2903 events = []
2904 iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
2905 for event, elem in iterator:
2906 events.append(event)
2907 if event == 'start':
2908 if elem.tag != '{http://ns1/}a':
2909 elem.set(attr_name, 'value')
2910
2911 self.assertEqual(
2912 ['start-ns', 'start', 'start', 'start-ns', 'start',
2913 'end', 'end-ns', 'end', 'end', 'end-ns'],
2914 events)
2915
2916 root = iterator.root
2917 self.assertEqual(
2918 None,
2919 root.get(attr_name))
2920 self.assertEqual(
2921 'value',
2922 root[0].get(attr_name))
2923
2925 iterparse = self.etree.iterparse
2926 f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
2927
2928 attr_name = '{http://testns/}bla'
2929 events = []
2930 iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
2931 for event, elem in iterator:
2932 events.append(event)
2933 if event == 'start':
2934 if elem.tag != '{http://ns1/}a':
2935 elem.set(attr_name, 'value')
2936
2937 self.assertEqual(
2938 ['start-ns', 'start', 'start', 'start-ns', 'start',
2939 'end', 'end-ns', 'end', 'end', 'end-ns'],
2940 events)
2941
2942 root = iterator.root
2943 self.assertEqual(
2944 None,
2945 root.get(attr_name))
2946 self.assertEqual(
2947 'value',
2948 root[0].get(attr_name))
2949
2951 iterparse = self.etree.iterparse
2952 f = BytesIO('<a><b><d/></b><c/></a>')
2953
2954 for event, node in etree.iterparse(f): pass
2955
2956 root = etree.Element('new_root', {})
2957 root[:] = node[:]
2958
2959 self.assertEqual(
2960 ['b', 'c'],
2961 [ el.tag for el in root ])
2962
2964 tostring = self.etree.tostring
2965 f = BytesIO('<root><![CDATA[test]]></root>')
2966 context = self.etree.iterparse(f)
2967 content = [ el.text for event,el in context ]
2968
2969 self.assertEqual(['test'], content)
2970 self.assertEqual(_bytes('<root>test</root>'),
2971 tostring(context.root))
2972
2974 parse = self.etree.parse
2975 # from file
2976 tree = parse(fileInTestDir('test.xml'))
2977 self.assertXML(
2978 _bytes('<a><b></b></a>'),
2979 tree.getroot())
2980
2984
2988
2989 required_versions_ET['test_parse_error'] = (1,3)
2991 # ET < 1.3 raises ExpatError
2992 parse = self.etree.parse
2993 f = BytesIO('<a><b></c></b></a>')
2994 self.assertRaises(SyntaxError, parse, f)
2995 f.close()
2996
2997 required_versions_ET['test_parse_error_from_file'] = (1,3)
2999 parse = self.etree.parse
3000 # from file
3001 f = open(fileInTestDir('test_broken.xml'), 'rb')
3002 self.assertRaises(SyntaxError, parse, f)
3003 f.close()
3004
3006 parse = self.etree.parse
3007 # from file object
3008 f = open(fileInTestDir('test.xml'), 'rb')
3009 tree = parse(f)
3010 f.close()
3011 self.assertXML(
3012 _bytes('<a><b></b></a>'),
3013 tree.getroot())
3014
3016 parse = self.etree.parse
3017 f = BytesIO('<a><b></b></a>')
3018 tree = parse(f)
3019 f.close()
3020 self.assertXML(
3021 _bytes('<a><b></b></a>'),
3022 tree.getroot()
3023 )
3024
3026 tostring = self.etree.tostring
3027 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'))
3028
3029 self.assertEqual('test', root.text)
3030 self.assertEqual(_bytes('<root>test</root>'),
3031 tostring(root))
3032
3034 # this can fail in libxml2 <= 2.6.22
3035 parse = self.etree.parse
3036 tree = parse(BytesIO('<?xml version="1.0" encoding="ascii"?><html/>'))
3037 self.assertXML(_bytes('<html></html>'),
3038 tree.getroot())
3039
3041 Element = self.etree.Element
3042
3043 a = Element('a')
3044 a.text = _str('Søk på nettet')
3045 self.assertXML(
3046 _str('<a>Søk på nettet</a>').encode('UTF-8'),
3047 a, 'utf-8')
3048
3050 ElementTree = self.etree.ElementTree
3051 Element = self.etree.Element
3052
3053 a = Element('a')
3054 a.text = _str('Søk på nettet')
3055
3056 f = BytesIO()
3057 tree = ElementTree(element=a)
3058 tree.write(f, encoding='utf-8')
3059 self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
3060 f.getvalue().replace(_bytes('\n'),_bytes('')))
3061
3063 parse = self.etree.parse
3064 # from file
3065 tree = parse(fileInTestDir('test-string.xml'))
3066 self.assertXML(
3067 _str('<a>Søk på nettet</a>').encode('UTF-8'),
3068 tree.getroot(), 'UTF-8')
3069
3071 parse = self.etree.parse
3072 # from file object
3073 f = open(fileInTestDir('test-string.xml'), 'rb')
3074 tree = parse(f)
3075 f.close()
3076 self.assertXML(
3077 _str('<a>Søk på nettet</a>').encode('UTF-8'),
3078 tree.getroot(), 'UTF-8')
3079
3081 ElementTree = self.etree.ElementTree
3082 Element = self.etree.Element
3083
3084 a = Element('a')
3085 a.text = _str('Søk på nettet')
3086
3087 f = BytesIO()
3088 tree = ElementTree(element=a)
3089 tree.write(f, encoding='iso-8859-1')
3090 result = f.getvalue()
3091 declaration = _bytes("<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>")
3092 self.assertEncodingDeclaration(result, _bytes('iso-8859-1'))
3093 result = result.split(_bytes('?>'), 1)[-1].replace(_bytes('\n'),_bytes(''))
3094 self.assertEqual(_str('<a>Søk på nettet</a>').encode('iso-8859-1'),
3095 result)
3096
3097 required_versions_ET['test_parse_encoding_8bit_explicit'] = (1,3)
3099 XMLParser = self.XMLParser
3100
3101 text = _str('Søk på nettet')
3102 xml_latin1 = (_str('<a>%s</a>') % text).encode('iso-8859-1')
3103
3104 self.assertRaises(self.etree.ParseError,
3105 self.etree.parse,
3106 BytesIO(xml_latin1))
3107
3108 tree = self.etree.parse(BytesIO(xml_latin1),
3109 XMLParser(encoding="iso-8859-1"))
3110 a = tree.getroot()
3111 self.assertEqual(a.text, text)
3112
3113 required_versions_ET['test_parse_encoding_8bit_override'] = (1,3)
3115 XMLParser = self.XMLParser
3116
3117 text = _str('Søk på nettet')
3118 wrong_declaration = _str("<?xml version='1.0' encoding='UTF-8'?>")
3119 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
3120 ).encode('iso-8859-1')
3121
3122 self.assertRaises(self.etree.ParseError,
3123 self.etree.parse,
3124 BytesIO(xml_latin1))
3125
3126 tree = self.etree.parse(BytesIO(xml_latin1),
3127 XMLParser(encoding="iso-8859-1"))
3128 a = tree.getroot()
3129 self.assertEqual(a.text, text)
3130
3132 # raise error on wrong encoding declaration in unicode strings
3133 XML = self.etree.XML
3134 test_utf = (_str('<?xml version="1.0" encoding="iso-8859-1"?>') +
3135 _str('<a>Søk på nettet</a>'))
3136 self.assertRaises(SyntaxError, XML, test_utf)
3137
3139 ElementTree = self.etree.ElementTree
3140 Element = self.etree.Element
3141
3142 a = Element('a')
3143 a.text = _str('Søk på nettet')
3144
3145 f = BytesIO()
3146 tree = ElementTree(element=a)
3147 tree.write(f)
3148 data = f.getvalue().replace(_bytes('\n'),_bytes(''))
3149 self.assertEqual(
3150 _str('<a>Søk på nettet</a>').encode('ASCII', 'xmlcharrefreplace'),
3151 data)
3152
3154 Element = self.etree.Element
3155 tostring = self.etree.tostring
3156
3157 a = Element('a')
3158 a.text = _str('Søk på nettet')
3159 self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
3160 tostring(a, encoding='utf-8'))
3161
3163 Element = self.etree.Element
3164 tostring = self.etree.tostring
3165
3166 a = Element('a')
3167 a.text = _str('Søk på nettet')
3168 self.assertRaises(LookupError, tostring, a,
3169 encoding='Invalid Encoding')
3170
3172 Element = self.etree.Element
3173 SubElement = self.etree.SubElement
3174 tostring = self.etree.tostring
3175
3176 a = Element('a')
3177 b = SubElement(a, 'b')
3178 b.text = _str('Søk på nettet')
3179 self.assertEqual(_str('<b>Søk på nettet</b>').encode('UTF-8'),
3180 tostring(b, encoding='utf-8'))
3181
3183 Element = self.etree.Element
3184 SubElement = self.etree.SubElement
3185 tostring = self.etree.tostring
3186
3187 a = Element('a')
3188 b = SubElement(a, 'b')
3189 b.text = _str('Søk på nettet')
3190 b.tail = _str('Søk')
3191 self.assertEqual(_str('<b>Søk på nettet</b>Søk').encode('UTF-8'),
3192 tostring(b, encoding='utf-8'))
3193
3195 Element = self.etree.Element
3196 SubElement = self.etree.SubElement
3197 tostring = self.etree.tostring
3198
3199 a = Element('a')
3200 a.text = _str('Søk på nettet')
3201
3202 expected = _bytes('<a>Søk på nettet</a>')
3203 self.assertEqual(
3204 expected,
3205 tostring(a))
3206
3208 Element = self.etree.Element
3209 SubElement = self.etree.SubElement
3210 tostring = self.etree.tostring
3211
3212 a = Element('a')
3213 b = SubElement(a, 'b')
3214 b.text = _str('Søk på nettet')
3215
3216 expected = _bytes('<b>Søk på nettet</b>')
3217 self.assertEqual(
3218 expected,
3219 tostring(b))
3220
3222 utext = _str('Søk på nettet')
3223 uxml = _str('<p>%s</p>') % utext
3224 prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
3225 isoxml = prologue + uxml.encode('iso-8859-1')
3226 tree = self.etree.XML(isoxml)
3227 self.assertEqual(utext, tree.text)
3228
3230 utext = _str('Søk på nettet')
3231 uxml = (_str('<?xml version="1.0" encoding="UTF-8"?>') +
3232 _str('<p>%s</p>') % utext)
3233 bom = _bytes('\\xEF\\xBB\\xBF').decode("unicode_escape").encode("latin1")
3234 xml = bom + uxml.encode("utf-8")
3235 tree = etree.XML(xml)
3236 self.assertEqual(utext, tree.text)
3237
3239 utext = _str('Søk på nettet')
3240 uxml = _str('<p>%s</p>') % utext
3241 prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
3242 isoxml = prologue + uxml.encode('iso-8859-1')
3243 el = self.etree.parse(BytesIO(isoxml)).getroot()
3244 self.assertEqual(utext, el.text)
3245
3247 Element = self.etree.Element
3248 ElementTree = self.etree.ElementTree
3249
3250 a = Element('a')
3251 a.text = "Foo"
3252 atree = ElementTree(a)
3253
3254 btree = copy.deepcopy(atree)
3255 self.assertEqual("Foo", atree.getroot().text)
3256 self.assertEqual("Foo", btree.getroot().text)
3257 self.assertFalse(btree is atree)
3258 self.assertFalse(btree.getroot() is atree.getroot())
3259
3261 Element = self.etree.Element
3262
3263 a = Element('a')
3264 a.text = 'Foo'
3265
3266 b = copy.deepcopy(a)
3267 self.assertEqual('Foo', b.text)
3268
3269 b.text = 'Bar'
3270 self.assertEqual('Bar', b.text)
3271 self.assertEqual('Foo', a.text)
3272
3273 del a
3274 self.assertEqual('Bar', b.text)
3275
3277 Element = self.etree.Element
3278
3279 a = Element('a')
3280 a.tail = 'Foo'
3281
3282 b = copy.deepcopy(a)
3283 self.assertEqual('Foo', b.tail)
3284
3285 b.tail = 'Bar'
3286 self.assertEqual('Bar', b.tail)
3287 self.assertEqual('Foo', a.tail)
3288
3289 del a
3290 self.assertEqual('Bar', b.tail)
3291
3293 Element = self.etree.Element
3294 SubElement = self.etree.SubElement
3295
3296 root = Element('root')
3297 a = SubElement(root, 'a')
3298 a.text = 'FooText'
3299 a.tail = 'FooTail'
3300
3301 b = copy.deepcopy(a)
3302 self.assertEqual('FooText', b.text)
3303 self.assertEqual('FooTail', b.tail)
3304
3305 b.text = 'BarText'
3306 b.tail = 'BarTail'
3307 self.assertEqual('BarTail', b.tail)
3308 self.assertEqual('FooTail', a.tail)
3309 self.assertEqual('BarText', b.text)
3310 self.assertEqual('FooText', a.text)
3311
3312 del a
3313 self.assertEqual('BarTail', b.tail)
3314 self.assertEqual('BarText', b.text)
3315
3317 root = self.etree.XML(_bytes('''<doc xmlns="dns" xmlns:t="tns">
3318 <parent><node t:foo="bar" /></parent>
3319 </doc>'''))
3320 self.assertEqual(
3321 root[0][0].get('{tns}foo'),
3322 copy.deepcopy(root[0])[0].get('{tns}foo') )
3323 self.assertEqual(
3324 root[0][0].get('{tns}foo'),
3325 copy.deepcopy(root[0][0]).get('{tns}foo') )
3326
3328 # previously caused a crash
3329 Element = self.etree.Element
3330 tostring = self.etree.tostring
3331
3332 a = Element('a')
3333 b = copy.deepcopy(a)
3334 a.append( Element('C') )
3335 b.append( Element('X') )
3336
3337 self.assertEqual(_bytes('<a><C/></a>'),
3338 tostring(a).replace(_bytes(' '), _bytes('')))
3339 self.assertEqual(_bytes('<a><X/></a>'),
3340 tostring(b).replace(_bytes(' '), _bytes('')))
3341
3343 # previously caused a crash
3344 # not supported by ET < 1.3!
3345 Comment = self.etree.Comment
3346
3347 a = Comment("ONE")
3348 b = copy.deepcopy(a)
3349 b.text = "ANOTHER"
3350
3351 self.assertEqual('ONE', a.text)
3352 self.assertEqual('ANOTHER', b.text)
3353
3355 Element = self.etree.Element
3356
3357 a = Element('a')
3358 a.text = 'Foo'
3359
3360 b = copy.copy(a)
3361 self.assertEqual('Foo', b.text)
3362
3363 b.text = 'Bar'
3364 self.assertEqual('Bar', b.text)
3365 self.assertEqual('Foo', a.text)
3366 # XXX ElementTree will share nodes, but lxml.etree won't..
3367
3369 Element = self.etree.Element
3370 ElementTree = self.etree.ElementTree
3371
3372 a = Element('a')
3373 a.text = 'Foo'
3374 atree = ElementTree(a)
3375
3376 btree = copy.copy(atree)
3377 self.assertFalse(btree is atree)
3378 self.assertTrue(btree.getroot() is atree.getroot())
3379 self.assertEqual('Foo', atree.getroot().text)
3380
3382 # deprecated as of ET 1.3/lxml 2.0
3383 etree = self.etree
3384 e = etree.Element('foo')
3385 self.assertEqual(False, bool(e))
3386 etree.SubElement(e, 'bar')
3387 self.assertEqual(True, bool(e))
3388 e = etree.Element('foo')
3389 e.text = 'hey'
3390 self.assertEqual(False, bool(e))
3391 e = etree.Element('foo')
3392 e.tail = 'bar'
3393 self.assertEqual(False, bool(e))
3394 e = etree.Element('foo')
3395 e.set('bar', 'Bar')
3396 self.assertEqual(False, bool(e))
3397
3399 etree = self.etree
3400
3401 a = etree.Element('a')
3402 b = etree.SubElement(a, 'b')
3403
3404 t = etree.ElementTree(a)
3405 self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
3406
3407 t1 = etree.ElementTree(a)
3408 self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
3409 self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
3410
3411 t2 = etree.ElementTree(b)
3412 self.assertEqual(self._rootstring(t2), _bytes('<b/>'))
3413 self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
3414 self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
3415
3417 etree = self.etree
3418 qname = etree.QName('myns', 'a')
3419 a1 = etree.Element(qname)
3420 a2 = etree.SubElement(a1, qname)
3421 self.assertEqual(a1.tag, "{myns}a")
3422 self.assertEqual(a2.tag, "{myns}a")
3423
3425 etree = self.etree
3426 qname1 = etree.QName('myns', 'a')
3427 qname2 = etree.QName('myns', 'a')
3428 self.assertEqual(qname1, "{myns}a")
3429 self.assertEqual("{myns}a", qname2)
3430 self.assertEqual(qname1, qname1)
3431 self.assertEqual(qname1, qname2)
3432
3434 etree = self.etree
3435 qname = etree.QName('myns', 'a')
3436
3437 a = etree.Element(qname)
3438 a.set(qname, "value")
3439
3440 self.assertEqual(a.get(qname), "value")
3441 self.assertEqual(a.get("{myns}a"), "value")
3442
3444 etree = self.etree
3445 qname = etree.QName('myns', 'a')
3446
3447 a = etree.Element(qname)
3448 a.attrib[qname] = "value"
3449
3450 self.assertEqual(a.attrib[qname], "value")
3451 self.assertEqual(a.attrib.get(qname), "value")
3452
3453 self.assertEqual(a.attrib["{myns}a"], "value")
3454 self.assertEqual(a.attrib.get("{myns}a"), "value")
3455
3457 etree = self.etree
3458 qname = etree.QName('http://myns', 'a')
3459 a = etree.Element(qname)
3460 a.set(qname, qname)
3461
3462 self.assertXML(
3463 _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
3464 a)
3465
3467 etree = self.etree
3468 qname = etree.QName('http://myns', 'a')
3469 a = etree.Element('a')
3470 a.set('a', qname)
3471
3472 self.assertXML(
3473 _bytes('<a xmlns:ns0="http://myns" a="ns0:a"></a>'),
3474 a)
3475
3477 etree = self.etree
3478 qname = etree.QName('http://myns', 'a')
3479 a = etree.Element(qname)
3480 a.attrib[qname] = qname
3481
3482 self.assertXML(
3483 _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
3484 a)
3485
3487 etree = self.etree
3488 parser = etree.XMLParser()
3489 if hasattr(parser, "version"):
3490 # ElementTree 1.3+, cET
3491 self.assertTrue(re.match("[^ ]+ [0-9.]+", parser.version))
3492
3493 # feed parser interface
3494
3496 parser = self.XMLParser()
3497
3498 parser.feed(_bytes('<?xml version='))
3499 parser.feed(_bytes('"1.0"?><ro'))
3500 parser.feed(_bytes('ot><'))
3501 parser.feed(_bytes('a test="works"/'))
3502 parser.feed(_bytes('></root'))
3503 parser.feed(_bytes('>'))
3504
3505 root = parser.close()
3506
3507 self.assertEqual(root.tag, "root")
3508 self.assertEqual(root[0].tag, "a")
3509 self.assertEqual(root[0].get("test"), "works")
3510
3512 parser = self.XMLParser()
3513
3514 parser.feed(_str('<ro'))
3515 parser.feed(_str('ot><'))
3516 parser.feed(_str('a test="works"/'))
3517 parser.feed(_str('></root'))
3518 parser.feed(_str('>'))
3519
3520 root = parser.close()
3521
3522 self.assertEqual(root.tag, "root")
3523 self.assertEqual(root[0].tag, "a")
3524 self.assertEqual(root[0].get("test"), "works")
3525
3526 required_versions_ET['test_feed_parser_error_close_empty'] = (1,3)
3528 ParseError = self.etree.ParseError
3529 parser = self.XMLParser()
3530 self.assertRaises(ParseError, parser.close)
3531
3532 required_versions_ET['test_feed_parser_error_close_incomplete'] = (1,3)
3534 ParseError = self.etree.ParseError
3535 parser = self.XMLParser()
3536
3537 parser.feed('<?xml version=')
3538 parser.feed('"1.0"?><ro')
3539
3540 self.assertRaises(ParseError, parser.close)
3541
3542 required_versions_ET['test_feed_parser_error_broken'] = (1,3)
3544 ParseError = self.etree.ParseError
3545 parser = self.XMLParser()
3546
3547 parser.feed('<?xml version=')
3548 parser.feed('"1.0"?><ro')
3549 try:
3550 parser.feed('<><><><><><><')
3551 except ParseError:
3552 # can raise, but not required before close()
3553 pass
3554
3555 self.assertRaises(ParseError, parser.close)
3556
3557 required_versions_ET['test_feed_parser_error_position'] = (1,3)
3559 ParseError = self.etree.ParseError
3560 parser = self.XMLParser()
3561 try:
3562 parser.close()
3563 except ParseError:
3564 e = sys.exc_info()[1]
3565 self.assertNotEqual(None, e.code)
3566 self.assertNotEqual(0, e.code)
3567 self.assertTrue(isinstance(e.position, tuple))
3568 self.assertTrue(e.position >= (0, 0))
3569
3570 # parser target interface
3571
3572 required_versions_ET['test_parser_target_property'] = (1,3)
3576
3577 target = Target()
3578 parser = self.XMLParser(target=target)
3579
3580 self.assertEqual(target, parser.target)
3581
3583 assertEqual = self.assertEqual
3584 assertFalse = self.assertFalse
3585
3586 events = []
3587 class Target(object):
3588 def start(self, tag, attrib):
3589 events.append("start")
3590 assertFalse(attrib)
3591 assertEqual("TAG", tag)
3592 def end(self, tag):
3593 events.append("end")
3594 assertEqual("TAG", tag)
3595 def close(self):
3596 return "DONE"
3597
3598 parser = self.XMLParser(target=Target())
3599
3600 parser.feed("<TAG/>")
3601 done = parser.close()
3602
3603 self.assertEqual("DONE", done)
3604 self.assertEqual(["start", "end"], events)
3605
3607 assertEqual = self.assertEqual
3608
3609 events = []
3610 class Target(object):
3611 def start(self, tag, attrib):
3612 events.append("start")
3613 assertEqual("TAG", tag)
3614 raise ValueError("TEST")
3615 def end(self, tag):
3616 events.append("end")
3617 assertEqual("TAG", tag)
3618 def close(self):
3619 return "DONE"
3620
3621 parser = self.XMLParser(target=Target())
3622
3623 try:
3624 parser.feed("<TAG/>")
3625 except ValueError:
3626 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3627 else:
3628 self.assertTrue(False)
3629 if 'lxml' in self.etree.__name__:
3630 self.assertEqual(["start"], events)
3631 else:
3632 # cElementTree calls end() as well
3633 self.assertTrue("start" in events)
3634
3636 assertEqual = self.assertEqual
3637
3638 events = []
3639 class Target(object):
3640 def start(self, tag, attrib):
3641 events.append("start")
3642 assertEqual("TAG", tag)
3643 def end(self, tag):
3644 events.append("end")
3645 assertEqual("TAG", tag)
3646 raise ValueError("TEST")
3647 def close(self):
3648 return "DONE"
3649
3650 parser = self.XMLParser(target=Target())
3651
3652 try:
3653 parser.feed("<TAG/>")
3654 except ValueError:
3655 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3656 else:
3657 self.assertTrue(False)
3658 self.assertEqual(["start", "end"], events)
3659
3661 assertEqual = self.assertEqual
3662
3663 events = []
3664 class Target(object):
3665 def start(self, tag, attrib):
3666 events.append("start")
3667 assertEqual("TAG", tag)
3668 def end(self, tag):
3669 events.append("end")
3670 assertEqual("TAG", tag)
3671 def close(self):
3672 raise ValueError("TEST")
3673
3674 parser = self.XMLParser(target=Target())
3675
3676 try:
3677 parser.feed("<TAG/>")
3678 parser.close()
3679 except ValueError:
3680 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3681 else:
3682 self.assertTrue(False)
3683 self.assertEqual(["start", "end"], events)
3684
3686 assertEqual = self.assertEqual
3687
3688 events = []
3689 class Target(object):
3690 def start(self, tag, attrib):
3691 events.append("start")
3692 assertEqual("TAG", tag)
3693 raise IndexError("TEST-IE")
3694 def end(self, tag):
3695 events.append("end")
3696 assertEqual("TAG", tag)
3697 def close(self):
3698 raise ValueError("TEST-VE")
3699
3700 parser = self.XMLParser(target=Target())
3701
3702 try:
3703 parser.feed("<TAG/>")
3704 parser.close()
3705 except IndexError:
3706 if 'lxml' in self.etree.__name__:
3707 # we try not to swallow the initial exception in Py2
3708 self.assertTrue(sys.version_info[0] < 3)
3709 self.assertTrue('TEST-IE' in str(sys.exc_info()[1]))
3710 except ValueError:
3711 if 'lxml' in self.etree.__name__:
3712 self.assertTrue(sys.version_info[0] >= 3)
3713 self.assertTrue('TEST-VE' in str(sys.exc_info()[1]))
3714 else:
3715 self.assertTrue(False)
3716
3717 if 'lxml' in self.etree.__name__:
3718 self.assertEqual(["start"], events)
3719 else:
3720 # cElementTree calls end() as well
3721 self.assertTrue("start" in events)
3722
3724 assertEqual = self.assertEqual
3725 assertFalse = self.assertFalse
3726 Element = self.etree.Element
3727
3728 events = []
3729 class Target(object):
3730 def start(self, tag, attrib):
3731 events.append("start")
3732 assertFalse(attrib)
3733 assertEqual("TAG", tag)
3734 def end(self, tag):
3735 events.append("end")
3736 assertEqual("TAG", tag)
3737 def close(self):
3738 return Element("DONE")
3739
3740 parser = self.XMLParser(target=Target())
3741 tree = self.etree.ElementTree()
3742 tree.parse(BytesIO("<TAG/>"), parser=parser)
3743
3744 self.assertEqual("DONE", tree.getroot().tag)
3745 self.assertEqual(["start", "end"], events)
3746
3748 assertEqual = self.assertEqual
3749
3750 events = []
3751 class Target(object):
3752 def start(self, tag, attrib):
3753 events.append("start-" + tag)
3754 for name, value in attrib.items():
3755 assertEqual(tag + name, value)
3756 def end(self, tag):
3757 events.append("end-" + tag)
3758 def close(self):
3759 return "DONE"
3760
3761 parser = self.XMLParser(target=Target())
3762
3763 parser.feed('<root a="roota" b="rootb"><sub c="subc"/></root>')
3764 done = parser.close()
3765
3766 self.assertEqual("DONE", done)
3767 self.assertEqual(["start-root", "start-sub", "end-sub", "end-root"],
3768 events)
3769
3771 events = []
3772 class Target(object):
3773 def start(self, tag, attrib):
3774 events.append("start-" + tag)
3775 def end(self, tag):
3776 events.append("end-" + tag)
3777 def data(self, data):
3778 events.append("data-" + data)
3779 def close(self):
3780 return "DONE"
3781
3782 parser = self.XMLParser(target=Target())
3783
3784 parser.feed('<root>A<sub/>B</root>')
3785 done = parser.close()
3786
3787 self.assertEqual("DONE", done)
3788 self.assertEqual(["start-root", "data-A", "start-sub",
3789 "end-sub", "data-B", "end-root"],
3790 events)
3791
3797 def _flush_data(self):
3798 if self._data:
3799 events.append("data-" + ''.join(self._data))
3800 del self._data[:]
3801 def start(self, tag, attrib):
3802 self._flush_data()
3803 events.append("start-" + tag)
3804 def end(self, tag):
3805 self._flush_data()
3806 events.append("end-" + tag)
3807 def data(self, data):
3808 self._data.append(data)
3809 def close(self):
3810 self._flush_data()
3811 return "DONE"
3812
3813 parser = self.XMLParser(target=Target())
3814
3815 dtd = '''
3816 <!DOCTYPE root [
3817 <!ELEMENT root (sub*)>
3818 <!ELEMENT sub (#PCDATA)>
3819 <!ENTITY ent "an entity">
3820 ]>
3821 '''
3822 parser.feed(dtd+'<root><sub/><sub>this is &ent;</sub><sub/></root>')
3823 done = parser.close()
3824
3825 self.assertEqual("DONE", done)
3826 self.assertEqual(["start-root", "start-sub", "end-sub", "start-sub",
3827 "data-this is an entity",
3828 "end-sub", "start-sub", "end-sub", "end-root"],
3829 events)
3830
3831 required_versions_ET['test_parser_target_entity_unknown'] = (1,3)
3837 def _flush_data(self):
3838 if self._data:
3839 events.append("data-" + ''.join(self._data))
3840 del self._data[:]
3841 def start(self, tag, attrib):
3842 self._flush_data()
3843 events.append("start-" + tag)
3844 def end(self, tag):
3845 self._flush_data()
3846 events.append("end-" + tag)
3847 def data(self, data):
3848 self._data.append(data)
3849 def close(self):
3850 self._flush_data()
3851 return "DONE"
3852
3853 parser = self.XMLParser(target=Target())
3854
3855 def feed():
3856 parser.feed('<root><sub/><sub>some &ent;</sub><sub/></root>')
3857 parser.close()
3858
3859 self.assertRaises(self.etree.ParseError, feed)
3860
3861 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3866 def end(self, tag):
3867 self.append(("end", tag))
3868 def data(self, text):
3869 pass
3870 def pi(self, target, data):
3871 self.append(("pi", target, data))
3872 def comment(self, data):
3873 self.append(("comment", data))
3874 def start_ns(self, prefix, uri):
3875 self.append(("start-ns", prefix, uri))
3876 def end_ns(self, prefix):
3877 self.append(("end-ns", prefix))
3878
3879 builder = Builder()
3880 parser = self.etree.XMLParser(target=builder)
3881 parser.feed(textwrap.dedent("""\
3882 <?pi data?>
3883 <!-- comment -->
3884 <root xmlns='namespace'>
3885 <element key='value'>text</element>
3886 <element>text</element>tail
3887 <empty-element/>
3888 </root>
3889 """))
3890 self.assertEqual(builder, [
3891 ('pi', 'pi', 'data'),
3892 ('comment', ' comment '),
3893 ('start-ns', '', 'namespace'),
3894 ('start', '{namespace}root'),
3895 ('start', '{namespace}element'),
3896 ('end', '{namespace}element'),
3897 ('start', '{namespace}element'),
3898 ('end', '{namespace}element'),
3899 ('start', '{namespace}empty-element'),
3900 ('end', '{namespace}empty-element'),
3901 ('end', '{namespace}root'),
3902 ('end-ns', ''),
3903 ])
3904
3905 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3910
3911 builder = Builder()
3912 parser = self.etree.XMLParser(target=builder)
3913 parser.feed(textwrap.dedent("""\
3914 <?pi data?>
3915 <!-- comment -->
3916 <root xmlns='namespace' xmlns:p='pns'>
3917 <element key='value'>text</element>
3918 <p:element>text</p:element>tail
3919 <empty-element/>
3920 </root>
3921 """))
3922 self.assertEqual(builder, [
3923 ('end-ns', 'p'),
3924 ('end-ns', ''),
3925 ])
3926
3928 builder = self.etree.TreeBuilder()
3929 el = builder.start("root", {'a':'A', 'b':'B'})
3930 self.assertEqual("root", el.tag)
3931 self.assertEqual({'a':'A', 'b':'B'}, el.attrib)
3932 builder.data("ROOTTEXT")
3933 el = builder.start("child", {'x':'X', 'y':'Y'})
3934 self.assertEqual("child", el.tag)
3935 self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
3936 builder.data("CHILDTEXT")
3937 el = builder.end("child")
3938 self.assertEqual("child", el.tag)
3939 self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
3940 self.assertEqual("CHILDTEXT", el.text)
3941 self.assertEqual(None, el.tail)
3942 builder.data("CHILDTAIL")
3943 root = builder.end("root")
3944
3945 self.assertEqual("root", root.tag)
3946 self.assertEqual("ROOTTEXT", root.text)
3947 self.assertEqual("CHILDTEXT", root[0].text)
3948 self.assertEqual("CHILDTAIL", root[0].tail)
3949
3951 parser = self.XMLParser(target=self.etree.TreeBuilder())
3952 parser.feed('<root>ROOTTEXT<child>CHILDTEXT</child>CHILDTAIL</root>')
3953 root = parser.close()
3954
3955 self.assertEqual("root", root.tag)
3956 self.assertEqual("ROOTTEXT", root.text)
3957 self.assertEqual("CHILDTEXT", root[0].text)
3958 self.assertEqual("CHILDTAIL", root[0].tail)
3959
3960 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3962 ET = self.etree
3963 b = ET.TreeBuilder()
3964 self.assertEqual(b.comment('ctext').tag, ET.Comment)
3965 self.assertEqual(b.comment('ctext').text, 'ctext')
3966
3967 b = ET.TreeBuilder(comment_factory=ET.Comment)
3968 self.assertEqual(b.comment('ctext').tag, ET.Comment)
3969 self.assertEqual(b.comment('ctext').text, 'ctext')
3970
3971 #b = ET.TreeBuilder(comment_factory=len)
3972 #self.assertEqual(b.comment('ctext'), len('ctext'))
3973
3974 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
3976 ET = self.etree
3977 is_lxml = ET.__name__ == 'lxml.etree'
3978
3979 b = ET.TreeBuilder()
3980 self.assertEqual(b.pi('target', None).tag, ET.PI)
3981 if is_lxml:
3982 self.assertEqual(b.pi('target', None).target, 'target')
3983 else:
3984 self.assertEqual(b.pi('target', None).text, 'target')
3985
3986 b = ET.TreeBuilder(pi_factory=ET.PI)
3987 self.assertEqual(b.pi('target').tag, ET.PI)
3988 if is_lxml:
3989 self.assertEqual(b.pi('target').target, "target")
3990 else:
3991 self.assertEqual(b.pi('target').text, "target")
3992 self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI)
3993 if is_lxml:
3994 self.assertEqual(b.pi('pitarget', ' text ').target, "pitarget")
3995 self.assertEqual(b.pi('pitarget', ' text ').text, " text ")
3996 else:
3997 self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget text ")
3998
3999 #b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text))
4000 #self.assertEqual(b.pi('target'), (len('target'), None))
4001 #self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text '))
4002
4004 # Issue #37399: The tail of an ignored comment could overwrite the text before it.
4005 ET = self.etree
4006 class TreeBuilderSubclass(ET.TreeBuilder):
4007 pass
4008
4009 if ET.__name__ == 'lxml.etree':
4010 def assert_content(a):
4011 self.assertEqual(a.text, "text")
4012 self.assertEqual(a[0].tail, "tail")
4013 else:
4014 def assert_content(a):
4015 self.assertEqual(a.text, "texttail")
4016
4017 xml = "<a>text<!-- comment -->tail</a>"
4018 a = ET.fromstring(xml)
4019 assert_content(a)
4020
4021 parser = ET.XMLParser(target=TreeBuilderSubclass())
4022 parser.feed(xml)
4023 a = parser.close()
4024 assert_content(a)
4025
4026 xml = "<a>text<?pi data?>tail</a>"
4027 a = ET.fromstring(xml)
4028 assert_content(a)
4029
4030 xml = "<a>text<?pi data?>tail</a>"
4031 parser = ET.XMLParser(target=TreeBuilderSubclass())
4032 parser.feed(xml)
4033 a = parser.close()
4034 assert_content(a)
4035
4036 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4038 # Issue #37399: The tail of an ignored comment could overwrite the text before it.
4039 # Test appending tails to comments/pis.
4040 ET = self.etree
4041 class TreeBuilderSubclass(ET.TreeBuilder):
4042 pass
4043
4044 xml = "<a>text<?pi1?> <!-- comment -->\n<?pi2?>tail</a>"
4045 parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True, insert_pis=False))
4046 parser.feed(xml)
4047 a = parser.close()
4048 self.assertEqual(a[0].text, ' comment ')
4049 self.assertEqual(a[0].tail, '\ntail')
4050 self.assertEqual(a.text, "text ")
4051
4052 parser = ET.XMLParser(target=TreeBuilderSubclass(insert_comments=True, insert_pis=False))
4053 parser.feed(xml)
4054 a = parser.close()
4055 self.assertEqual(a[0].text, ' comment ')
4056 self.assertEqual(a[0].tail, '\ntail')
4057 self.assertEqual(a.text, "text ")
4058
4059 xml = "<a>text<!-- comment -->\n<?pi data?>tail</a>"
4060 parser = ET.XMLParser(target=ET.TreeBuilder(insert_pis=True, insert_comments=False))
4061 parser.feed(xml)
4062 a = parser.close()
4063 self.assertEqual(a[0].text[-4:], 'data')
4064 self.assertEqual(a[0].tail, 'tail')
4065 self.assertEqual(a.text, "text\n")
4066
4067 parser = ET.XMLParser(target=TreeBuilderSubclass(insert_pis=True, insert_comments=False))
4068 parser.feed(xml)
4069 a = parser.close()
4070 self.assertEqual(a[0].text[-4:], 'data')
4071 self.assertEqual(a[0].tail, 'tail')
4072 self.assertEqual(a.text, "text\n")
4073
4074 # helper methods
4075
4077 """Write out element for comparison.
4078 """
4079 data = self.etree.tostring(element, encoding=encoding)
4080 return canonicalize(data)
4081
4083 """Write out element for comparison, using real file.
4084 """
4085 ElementTree = self.etree.ElementTree
4086 with tmpfile() as filename:
4087 with open(filename, 'wb') as f:
4088 tree = ElementTree(element=element)
4089 tree.write(f, encoding=encoding)
4090 with open(filename, 'rb') as f:
4091 data = f.read()
4092 return canonicalize(data)
4093
4095 """Writes element out and checks whether it is expected.
4096
4097 Does this two ways; once using BytesIO, once using a real file.
4098 """
4099 if isinstance(expected, unicode):
4100 expected = expected.encode(encoding)
4101 self.assertEqual(expected, self._writeElement(element, encoding))
4102 self.assertEqual(expected, self._writeElementFile(element, encoding))
4103
4105 "Checks if the result XML byte string specifies the encoding."
4106 enc_re = r"<\?xml[^>]+ encoding=[\"']([^\"']+)[\"']"
4107 if isinstance(result, str):
4108 has_encoding = re.compile(enc_re).match
4109 else:
4110 has_encoding = re.compile(_bytes(enc_re)).match
4111 self.assertTrue(has_encoding(result))
4112 result_encoding = has_encoding(result).group(1)
4113 self.assertEqual(result_encoding.upper(), encoding.upper())
4114
4116 return self.etree.tostring(tree.getroot()).replace(
4117 _bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes(''))
4118
4121
4123 self.assertTrue(hasattr(element, 'tag'))
4124 self.assertTrue(hasattr(element, 'attrib'))
4125 self.assertTrue(hasattr(element, 'text'))
4126 self.assertTrue(hasattr(element, 'tail'))
4127 self._check_string(element.tag)
4128 self._check_mapping(element.attrib)
4129 if element.text is not None:
4130 self._check_string(element.text)
4131 if element.tail is not None:
4132 self._check_string(element.tail)
4133
4135 len(string)
4136 for char in string:
4137 self.assertEqual(1, len(char))
4138 new_string = string + ""
4139 new_string = string + " "
4140 string[:0]
4141
4143 len(mapping)
4144 keys = mapping.keys()
4145 values = mapping.values()
4146 items = mapping.items()
4147 for key in keys:
4148 item = mapping[key]
4149 mapping["key"] = "value"
4150 self.assertEqual("value", mapping["key"])
4151
4154 etree = None
4155
4158
4161
4163 """Create an Element with a tag 'a', with the given amount of children
4164 named 'a0', 'a1' ... and so on.
4165
4166 """
4167 e = self.etree.Element('a')
4168 for i in range(numchildren):
4169 self.etree.SubElement(e, 'a%s' % i)
4170 return e
4171
4173 e = self._make_elem_with_children(10)
4174
4175 self.assertEqual(e[1].tag, 'a1')
4176 self.assertEqual(e[-2].tag, 'a8')
4177
4178 self.assertRaises(IndexError, lambda: e[12])
4179 self.assertRaises(IndexError, lambda: e[-12])
4180
4182 e = self._make_elem_with_children(6)
4183
4184 self.assertEqual(self._elem_tags(e[3:]), ['a3', 'a4', 'a5'])
4185 self.assertEqual(self._elem_tags(e[3:6]), ['a3', 'a4', 'a5'])
4186 self.assertEqual(self._elem_tags(e[3:16]), ['a3', 'a4', 'a5'])
4187 self.assertEqual(self._elem_tags(e[3:5]), ['a3', 'a4'])
4188 self.assertEqual(self._elem_tags(e[3:-1]), ['a3', 'a4'])
4189 self.assertEqual(self._elem_tags(e[:2]), ['a0', 'a1'])
4190
4192 e = self._make_elem_with_children(10)
4193
4194 self.assertEqual(self._elem_tags(e[8:10:1]), ['a8', 'a9'])
4195 self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
4196 self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
4197 self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
4198 self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
4199 self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
4200
4202 e = self._make_elem_with_children(4)
4203
4204 self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
4205 self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
4206 self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
4207 self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
4208 self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
4209
4211 e = self._make_elem_with_children(4)
4212 del e[0:2]
4213 self.assertEqual(self._subelem_tags(e), ['a2', 'a3'])
4214
4215 e = self._make_elem_with_children(4)
4216 del e[0:]
4217 self.assertEqual(self._subelem_tags(e), [])
4218
4219 e = self._make_elem_with_children(4)
4220 del e[::-1]
4221 self.assertEqual(self._subelem_tags(e), [])
4222
4223 e = self._make_elem_with_children(4)
4224 del e[::-2]
4225 self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
4226
4227 e = self._make_elem_with_children(4)
4228 del e[1::2]
4229 self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
4230
4231 e = self._make_elem_with_children(2)
4232 del e[::2]
4233 self.assertEqual(self._subelem_tags(e), ['a1'])
4234
4236 e = self._make_elem_with_children(4)
4237 e[1] = self.etree.Element('b')
4238 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4239
4240 e[-2] = self.etree.Element('c')
4241 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
4242
4243 with self.assertRaises(IndexError):
4244 e[5] = self.etree.Element('d')
4245 with self.assertRaises(IndexError):
4246 e[-5] = self.etree.Element('d')
4247 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
4248
4250 e = self._make_elem_with_children(4)
4251 e[1:3] = [self.etree.Element('b%s' % i) for i in range(2)]
4252 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
4253
4254 e = self._make_elem_with_children(4)
4255 e[1:3] = [self.etree.Element('b')]
4256 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
4257
4258 e = self._make_elem_with_children(4)
4259 e[1:3] = [self.etree.Element('b%s' % i) for i in range(3)]
4260 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
4261
4263 e = self._make_elem_with_children(6)
4264 e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(2)]
4265 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
4266
4267 e = self._make_elem_with_children(6)
4268 with self.assertRaises(ValueError):
4269 e[1:5:2] = [self.etree.Element('b')]
4270 with self.assertRaises(ValueError):
4271 e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(3)]
4272 with self.assertRaises(ValueError):
4273 e[1:5:2] = []
4274 self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
4275
4276 e = self._make_elem_with_children(4)
4277 e[1::sys.maxsize] = [self.etree.Element('b')]
4278 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4279 e[1::sys.maxsize<<64] = [self.etree.Element('c')]
4280 self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
4281
4283 e = self._make_elem_with_children(4)
4284 e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(2)]
4285 self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
4286
4287 e = self._make_elem_with_children(4)
4288 with self.assertRaises(ValueError):
4289 e[2:0:-1] = [self.etree.Element('b')]
4290 with self.assertRaises(ValueError):
4291 e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(3)]
4292 with self.assertRaises(ValueError):
4293 e[2:0:-1] = []
4294 self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
4295
4296 e = self._make_elem_with_children(4)
4297 e[1::-sys.maxsize] = [self.etree.Element('b')]
4298 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4299 e[1::-sys.maxsize-1] = [self.etree.Element('c')]
4300 self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
4301 e[1::-sys.maxsize<<64] = [self.etree.Element('d')]
4302 self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
4303
4306 etree = None
4307
4309 if 'ElementTree' in self.etree.__name__:
4310 # ElementTree's API is a bit unwieldy in Py3.4
4311 root = parser._close_and_return_root()
4312 else:
4313 root = parser.close()
4314 return root
4315
4317 if chunk_size is None:
4318 parser.feed(data)
4319 else:
4320 for i in range(0, len(data), chunk_size):
4321 parser.feed(data[i:i+chunk_size])
4322
4324 self.assertEqual(
4325 [(event, (elem.tag, elem.text))
4326 for event, elem in islice(parser.read_events(), max_events)],
4327 expected)
4328
4333
4338
4340 for chunk_size in (None, 1, 5):
4341 #with self.subTest(chunk_size=chunk_size):
4342 parser = self.etree.XMLPullParser()
4343 self.assert_event_tags(parser, [])
4344 self._feed(parser, "<!-- comment -->\n", chunk_size)
4345 self.assert_event_tags(parser, [])
4346 self._feed(parser,
4347 "<root>\n <element key='value'>text</element",
4348 chunk_size)
4349 self.assert_event_tags(parser, [])
4350 self._feed(parser, ">\n", chunk_size)
4351 self.assert_event_tags(parser, [('end', 'element')])
4352 self._feed(parser, "<element>text</element>tail\n", chunk_size)
4353 self._feed(parser, "<empty-element/>\n", chunk_size)
4354 self.assert_event_tags(parser, [
4355 ('end', 'element'),
4356 ('end', 'empty-element'),
4357 ])
4358 self._feed(parser, "</root>\n", chunk_size)
4359 self.assert_event_tags(parser, [('end', 'root')])
4360 root = self._close_and_return_root(parser)
4361 self.assertEqual(root.tag, 'root')
4362
4364 parser = self.etree.XMLPullParser()
4365 it = parser.read_events()
4366 self._feed(parser, "<root>\n <element key='value'>text</element>\n")
4367 action, elem = next(it)
4368 self.assertEqual((action, elem.tag), ('end', 'element'))
4369 self._feed(parser, "</root>\n")
4370 action, elem = next(it)
4371 self.assertEqual((action, elem.tag), ('end', 'root'))
4372 with self.assertRaises(StopIteration):
4373 next(it)
4374
4376 parser = self.etree.XMLPullParser()
4377 self.assert_event_tags(parser, [])
4378 self._feed(parser, "<!-- comment -->\n")
4379 self.assert_event_tags(parser, [])
4380 self._feed(parser, "<root xmlns='namespace'>\n")
4381 self.assert_event_tags(parser, [])
4382 self._feed(parser, "<element key='value'>text</element")
4383 self.assert_event_tags(parser, [])
4384 self._feed(parser, ">\n")
4385 self.assert_event_tags(parser, [('end', '{namespace}element')])
4386 self._feed(parser, "<element>text</element>tail\n")
4387 self._feed(parser, "<empty-element/>\n")
4388 self.assert_event_tags(parser, [
4389 ('end', '{namespace}element'),
4390 ('end', '{namespace}empty-element'),
4391 ])
4392 self._feed(parser, "</root>\n")
4393 self.assert_event_tags(parser, [('end', '{namespace}root')])
4394 root = self._close_and_return_root(parser)
4395 self.assertEqual(root.tag, '{namespace}root')
4396
4398 parser = self.etree.XMLPullParser(events=('start-ns', 'end-ns'))
4399 self._feed(parser, "<!-- comment -->\n")
4400 self._feed(parser, "<root xmlns='namespace'>\n")
4401 self.assertEqual(
4402 list(parser.read_events()),
4403 [('start-ns', ('', 'namespace'))])
4404 self._feed(parser, "<element key='value'>text</element")
4405 self._feed(parser, ">\n")
4406 self._feed(parser, "<element>text</element>tail\n")
4407 self._feed(parser, "<empty-element/>\n")
4408 self._feed(parser, "</root>\n")
4409 self.assertEqual(list(parser.read_events()), [('end-ns', None)])
4410 parser.close()
4411
4413 parser = self.etree.XMLPullParser(events=['end-ns'])
4414 self._feed(parser, "<!-- comment -->\n")
4415 self._feed(parser, "<root xmlns='namespace' xmlns:a='abc' xmlns:b='xyz'>\n")
4416 self.assertEqual(list(parser.read_events()), [])
4417 self._feed(parser, "<a:element key='value'>text</a:element")
4418 self._feed(parser, ">\n")
4419 self._feed(parser, "<b:element>text</b:element>tail\n")
4420 self._feed(parser, "<empty-element/>\n")
4421 self.assertEqual(list(parser.read_events()), [])
4422 self._feed(parser, "</root>\n")
4423 self.assertEqual(list(parser.read_events()), [
4424 ('end-ns', None),
4425 ('end-ns', None),
4426 ('end-ns', None),
4427 ])
4428 parser.close()
4429
4430 @et_needs_pyversion(3,8)
4432 parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end'))
4433 self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
4434 self.assert_event_tuples(parser, [
4435 ('start-ns', ('', 'abc')),
4436 ('start-ns', ('p', 'xyz')),
4437 ], max_events=2)
4438 self.assert_event_tags(parser, [
4439 ('start', '{abc}tag'),
4440 ], max_events=1)
4441
4442 self._feed(parser, "<child />\n")
4443 self.assert_event_tags(parser, [
4444 ('start', '{abc}child'),
4445 ('end', '{abc}child'),
4446 ])
4447
4448 self._feed(parser, "</tag>\n")
4449 parser.close()
4450 self.assert_event_tags(parser, [
4451 ('end', '{abc}tag'),
4452 ])
4453
4454 @et_needs_pyversion(3,8)
4456 parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns'))
4457 self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
4458 self.assert_event_tuples(parser, [
4459 ('start-ns', ('', 'abc')),
4460 ('start-ns', ('p', 'xyz')),
4461 ], max_events=2)
4462 self.assert_event_tags(parser, [
4463 ('start', '{abc}tag'),
4464 ], max_events=1)
4465
4466 self._feed(parser, "<child />\n")
4467 self.assert_event_tags(parser, [
4468 ('start', '{abc}child'),
4469 ('end', '{abc}child'),
4470 ])
4471
4472 self._feed(parser, "</tag>\n")
4473 parser.close()
4474 self.assert_event_tags(parser, [
4475 ('end', '{abc}tag'),
4476 ], max_events=1)
4477 self.assert_event_tuples(parser, [
4478 ('end-ns', None),
4479 ('end-ns', None),
4480 ])
4481
4483 parser = self.etree.XMLPullParser(events=())
4484 self._feed(parser, "<root/>\n")
4485 self.assert_event_tags(parser, [])
4486
4487 parser = self.etree.XMLPullParser(events=('start', 'end'))
4488 self._feed(parser, "<!-- text here -->\n")
4489 self.assert_events(parser, [])
4490
4491 parser = self.etree.XMLPullParser(events=('start', 'end'))
4492 self._feed(parser, "<root>\n")
4493 self.assert_event_tags(parser, [('start', 'root')])
4494 self._feed(parser, "<element key='value'>text</element")
4495 self.assert_event_tags(parser, [('start', 'element')])
4496 self._feed(parser, ">\n")
4497 self.assert_event_tags(parser, [('end', 'element')])
4498 self._feed(parser,
4499 "<element xmlns='foo'>text<empty-element/></element>tail\n")
4500 self.assert_event_tags(parser, [
4501 ('start', '{foo}element'),
4502 ('start', '{foo}empty-element'),
4503 ('end', '{foo}empty-element'),
4504 ('end', '{foo}element'),
4505 ])
4506 self._feed(parser, "</root>")
4507 root = self._close_and_return_root(parser)
4508 self.assert_event_tags(parser, [('end', 'root')])
4509 self.assertEqual(root.tag, 'root')
4510
4511 parser = self.etree.XMLPullParser(events=('start',))
4512 self._feed(parser, "<!-- comment -->\n")
4513 self.assert_event_tags(parser, [])
4514 self._feed(parser, "<root>\n")
4515 self.assert_event_tags(parser, [('start', 'root')])
4516 self._feed(parser, "<element key='value'>text</element")
4517 self.assert_event_tags(parser, [('start', 'element')])
4518 self._feed(parser, ">\n")
4519 self.assert_event_tags(parser, [])
4520 self._feed(parser,
4521 "<element xmlns='foo'>text<empty-element/></element>tail\n")
4522 self.assert_event_tags(parser, [
4523 ('start', '{foo}element'),
4524 ('start', '{foo}empty-element'),
4525 ])
4526 self._feed(parser, "</root>")
4527 root = self._close_and_return_root(parser)
4528 self.assertEqual(root.tag, 'root')
4529
4530 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4532 parser = self.etree.XMLPullParser(events=('start', 'comment', 'end'))
4533 self._feed(parser, "<!-- text here -->\n")
4534 self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
4535 self._feed(parser, "<!-- more text here -->\n")
4536 self.assert_events(parser, [('comment', (self.etree.Comment, ' more text here '))])
4537 self._feed(parser, "<root-tag>text")
4538 self.assert_event_tags(parser, [('start', 'root-tag')])
4539 self._feed(parser, "<!-- inner comment-->\n")
4540 self.assert_events(parser, [('comment', (self.etree.Comment, ' inner comment'))])
4541 self._feed(parser, "</root-tag>\n")
4542 self.assert_event_tags(parser, [('end', 'root-tag')])
4543 self._feed(parser, "<!-- outer comment -->\n")
4544 self.assert_events(parser, [('comment', (self.etree.Comment, ' outer comment '))])
4545
4546 parser = self.etree.XMLPullParser(events=('comment',))
4547 self._feed(parser, "<!-- text here -->\n")
4548 self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
4549
4550 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4552 # Note: lxml's PIs have target+text, ET's PIs have both in "text"
4553 parser = self.etree.XMLPullParser(events=('start', 'pi', 'end'))
4554 self._feed(parser, "<?pitarget?>\n")
4555 self.assert_event_tags(parser, [('pi', self.etree.PI)])
4556 parser = self.etree.XMLPullParser(events=('pi',))
4557 self._feed(parser, "<?pitarget some text ?>\n")
4558 self.assert_event_tags(parser, [('pi', self.etree.PI)])
4559
4561 # Test that events can be some sequence that's not just a tuple or list
4562 eventset = {'end', 'start'}
4563 parser = self.etree.XMLPullParser(events=eventset)
4564 self._feed(parser, "<foo>bar</foo>")
4565 self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
4566
4567 class DummyIter(object):
4568 def __init__(self):
4569 self.events = iter(['start', 'end', 'start-ns'])
4570 def __iter__(self):
4571 return self
4572 def __next__(self):
4573 return next(self.events)
4574 def next(self):
4575 return next(self.events)
4576
4577 parser = self.etree.XMLPullParser(events=DummyIter())
4578 self._feed(parser, "<foo>bar</foo>")
4579 self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
4580
4582 with self.assertRaises(ValueError):
4583 self.etree.XMLPullParser(events=('start', 'end', 'bogus'))
4584
4587 etree = None
4588 maxDiff = None
4589
4590 if not hasattr(unittest.TestCase, 'subTest'):
4591 @contextmanager
4593 try:
4594 yield
4595 except unittest.SkipTest:
4596 raise
4597 except Exception as e:
4598 print("Subtest {} failed: {}".format(name, e))
4599 raise
4600
4603
4604 #
4605 # simple roundtrip tests (from c14n.py)
4606
4609
4611 c14n_roundtrip = self.c14n_roundtrip
4612 # Basics
4613 self.assertEqual(c14n_roundtrip("<doc/>"), '<doc></doc>')
4614 self.assertEqual(c14n_roundtrip("<doc xmlns='uri'/>"), # FIXME
4615 '<doc xmlns="uri"></doc>')
4616 self.assertEqual(c14n_roundtrip("<prefix:doc xmlns:prefix='uri'/>"),
4617 '<prefix:doc xmlns:prefix="uri"></prefix:doc>')
4618 self.assertEqual(c14n_roundtrip("<doc xmlns:prefix='uri'><prefix:bar/></doc>"),
4619 '<doc><prefix:bar xmlns:prefix="uri"></prefix:bar></doc>')
4620 self.assertEqual(c14n_roundtrip("<elem xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' />"),
4621 '<elem></elem>')
4622
4623 # C14N spec
4624 self.assertEqual(c14n_roundtrip("<doc>Hello, world!<!-- Comment 1 --></doc>"),
4625 '<doc>Hello, world!</doc>')
4626 self.assertEqual(c14n_roundtrip("<value>2</value>"),
4627 '<value>2</value>')
4628 self.assertEqual(c14n_roundtrip('<compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>'),
4629 '<compute>value>"0" && value<"10" ?"valid":"error"</compute>')
4630 self.assertEqual(c14n_roundtrip('''<compute expr='value>"0" && value<"10" ?"valid":"error"'>valid</compute>'''),
4631 '<compute expr="value>"0" && value<"10" ?"valid":"error"">valid</compute>')
4632 self.assertEqual(c14n_roundtrip("<norm attr=' '   
	 ' '/>"),
4633 '<norm attr=" \' 
	 \' "></norm>')
4634 self.assertEqual(c14n_roundtrip("<normNames attr=' A   
	 B '/>"),
4635 '<normNames attr=" A 
	 B "></normNames>')
4636 self.assertEqual(c14n_roundtrip("<normId id=' '   
	 ' '/>"),
4637 '<normId id=" \' 
	 \' "></normId>')
4638
4639 # fragments from PJ's tests
4640 #self.assertEqual(c14n_roundtrip("<doc xmlns:x='http://example.com/x' xmlns='http://example.com/default'><b y:a1='1' xmlns='http://example.com/default' a3='3' xmlns:y='http://example.com/y' y:a2='2'/></doc>"),
4641 #'<doc xmlns:x="http://example.com/x"><b xmlns:y="http://example.com/y" a3="3" y:a1="1" y:a2="2"></b></doc>')
4642
4644 c14n_roundtrip = self.c14n_roundtrip
4645 xml = textwrap.dedent("""\
4646 <root xmlns:x="http://example.com/x">
4647 <a x:attr="attrx">
4648 <b>abtext</b>
4649 </a>
4650 <b>btext</b>
4651 <c>
4652 <x:d>dtext</x:d>
4653 </c>
4654 </root>
4655 """)
4656 self.assertEqual(
4657 c14n_roundtrip(xml, strip_text=True),
4658 '<root>'
4659 '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
4660 '<b>btext</b>'
4661 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4662 '</root>')
4663 self.assertEqual(
4664 c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']),
4665 '<root>'
4666 '<a><b>abtext</b></a>'
4667 '<b>btext</b>'
4668 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4669 '</root>')
4670 self.assertEqual(
4671 c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']),
4672 '<root>'
4673 '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
4674 '<b>btext</b>'
4675 '<c></c>'
4676 '</root>')
4677 self.assertEqual(
4678 c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'],
4679 exclude_tags=['{http://example.com/x}d']),
4680 '<root>'
4681 '<a><b>abtext</b></a>'
4682 '<b>btext</b>'
4683 '<c></c>'
4684 '</root>')
4685 self.assertEqual(
4686 c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']),
4687 '<root>'
4688 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4689 '</root>')
4690 self.assertEqual(
4691 c14n_roundtrip(xml, exclude_tags=['a', 'b']),
4692 '<root>\n'
4693 ' \n'
4694 ' \n'
4695 ' <c>\n'
4696 ' <x:d xmlns:x="http://example.com/x">dtext</x:d>\n'
4697 ' </c>\n'
4698 '</root>')
4699 self.assertEqual(
4700 c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']),
4701 '<root>'
4702 '<a xmlns:x="http://example.com/x" x:attr="attrx"></a>'
4703 '<c></c>'
4704 '</root>')
4705 self.assertEqual(
4706 c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']),
4707 '<root>\n'
4708 ' <a xmlns:x="http://example.com/x" x:attr="attrx">\n'
4709 ' \n'
4710 ' </a>\n'
4711 ' \n'
4712 ' <c>\n'
4713 ' \n'
4714 ' </c>\n'
4715 '</root>')
4716
4717 #
4718 # basic method=c14n tests from the c14n 2.0 specification. uses
4719 # test files under xmltestdata/c14n-20.
4720
4721 # note that this uses generated C14N versions of the standard ET.write
4722 # output, not roundtripped C14N (see above).
4723
4725 datadir = os.path.join(os.path.dirname(__file__), "c14n-20")
4726 full_path = partial(os.path.join, datadir)
4727
4728 files = [filename[:-4] for filename in sorted(os.listdir(datadir))
4729 if filename.endswith('.xml')]
4730 input_files = [
4731 filename for filename in files
4732 if filename.startswith('in')
4733 ]
4734 configs = {
4735 filename: {
4736 # <c14n2:PrefixRewrite>sequential</c14n2:PrefixRewrite>
4737 option.tag.split('}')[-1]: ((option.text or '').strip(), option)
4738 for option in self.etree.parse(full_path(filename) + ".xml").getroot()
4739 }
4740 for filename in files
4741 if filename.startswith('c14n')
4742 }
4743
4744 tests = {
4745 input_file: [
4746 (filename, configs[filename.rsplit('_', 1)[-1]])
4747 for filename in files
4748 if filename.startswith('out_%s_' % input_file)
4749 and filename.rsplit('_', 1)[-1] in configs
4750 ]
4751 for input_file in input_files
4752 }
4753
4754 # Make sure we found all test cases.
4755 self.assertEqual(30, len([
4756 output_file for output_files in tests.values()
4757 for output_file in output_files]))
4758
4759 def get_option(config, option_name, default=None):
4760 return config.get(option_name, (default, ()))[0]
4761
4762 for input_file, output_files in tests.items():
4763 for output_file, config in output_files:
4764 keep_comments = get_option(
4765 config, 'IgnoreComments') == 'true' # no, it's right :)
4766 strip_text = get_option(
4767 config, 'TrimTextNodes') == 'true'
4768 rewrite_prefixes = get_option(
4769 config, 'PrefixRewrite') == 'sequential'
4770 if 'QNameAware' in config:
4771 qattrs = [
4772 "{%s}%s" % (el.get('NS'), el.get('Name'))
4773 for el in config['QNameAware'][1].findall(
4774 '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr')
4775 ]
4776 qtags = [
4777 "{%s}%s" % (el.get('NS'), el.get('Name'))
4778 for el in config['QNameAware'][1].findall(
4779 '{http://www.w3.org/2010/xml-c14n2}Element')
4780 ]
4781 else:
4782 qtags = qattrs = None
4783
4784 # Build subtest description from config.
4785 config_descr = ','.join(
4786 "%s=%s" % (name, value or ','.join(c.tag.split('}')[-1] for c in children))
4787 for name, (value, children) in sorted(config.items())
4788 )
4789
4790 with self.subTest("{}({})".format(output_file, config_descr)):
4791 if input_file == 'inNsRedecl' and not rewrite_prefixes:
4792 self.skipTest(
4793 "Redeclared namespace handling is not supported in {}".format(
4794 output_file))
4795 if input_file == 'inNsSuperfluous' and not rewrite_prefixes:
4796 self.skipTest(
4797 "Redeclared namespace handling is not supported in {}".format(
4798 output_file))
4799 if 'QNameAware' in config and config['QNameAware'][1].find(
4800 '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None:
4801 self.skipTest(
4802 "QName rewriting in XPath text is not supported in {}".format(
4803 output_file))
4804
4805 f = full_path(input_file + ".xml")
4806 if input_file == 'inC14N5':
4807 # Hack: avoid setting up external entity resolution in the parser.
4808 with open(full_path('world.txt'), 'rb') as entity_file:
4809 with open(f, 'rb') as f:
4810 f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read().strip()))
4811
4812 text = self._canonicalize(
4813 f,
4814 with_comments=keep_comments,
4815 strip_text=strip_text,
4816 rewrite_prefixes=rewrite_prefixes,
4817 qname_aware_tags=qtags, qname_aware_attrs=qattrs)
4818
4819 with io.open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f:
4820 expected = f.read()
4821 if input_file == 'inC14N3' and self.etree is not etree:
4822 # FIXME: cET resolves default attributes but ET does not!
4823 expected = expected.replace(' attr="default"', '')
4824 text = text.replace(' attr="default"', '')
4825 self.assertEqual(expected, text)
4826
4827
4828 if etree:
4831
4834
4837
4840
4842 - def _canonicalize(self, input_file, with_comments=True, strip_text=False,
4843 rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
4844 **options):
4845 if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
4846 self.skipTest("C14N 2.0 feature not supported with ElementTree.write()")
4847
4848 parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
4849 tree = self.etree.parse(input_file, parser)
4850 out = io.BytesIO()
4851 tree.write(
4852 out, method='c14n2',
4853 with_comments=with_comments, strip_text=strip_text,
4854 **options)
4855 return out.getvalue().decode('utf8')
4856
4858 - def _canonicalize(self, input_file, with_comments=True, strip_text=False,
4859 rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
4860 **options):
4861 if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
4862 self.skipTest("C14N 2.0 feature not supported with ElementTree.tostring()")
4863
4864 parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
4865 tree = self.etree.parse(input_file, parser)
4866 return self.etree.tostring(
4867 tree, method='c14n2',
4868 with_comments=with_comments, strip_text=strip_text,
4869 **options).decode('utf8')
4870
4871
4872 if ElementTree:
4886
4887 filter_by_version(
4888 ElementTreeTestCase,
4889 ElementTreeTestCase.required_versions_ET, ET_VERSION)
4890
4891 if hasattr(ElementTree, 'XMLPullParser'):
4894 else:
4895 ElementTreePullTestCase = None
4896
4897 if hasattr(ElementTree, 'canonicalize'):
4900 else:
4901 ElementTreeC14NTest = None
4905
4906
4907 if cElementTree:
4910
4911 filter_by_version(
4912 CElementTreeTestCase,
4913 CElementTreeTestCase.required_versions_cET, CET_VERSION)
4917
4920 suite = unittest.TestSuite()
4921 if etree:
4922 suite.addTests([unittest.makeSuite(ETreeTestCase)])
4923 suite.addTests([unittest.makeSuite(ETreePullTestCase)])
4924 suite.addTests([unittest.makeSuite(ETreeElementSlicingTest)])
4925 suite.addTests([unittest.makeSuite(ETreeC14NTest)])
4926 suite.addTests([unittest.makeSuite(ETreeC14N2WriteTest)])
4927 suite.addTests([unittest.makeSuite(ETreeC14N2TostringTest)])
4928 if ElementTree:
4929 suite.addTests([unittest.makeSuite(ElementTreeTestCase)])
4930 if ElementTreePullTestCase:
4931 suite.addTests([unittest.makeSuite(ElementTreePullTestCase)])
4932 if ElementTreeC14NTest:
4933 suite.addTests([unittest.makeSuite(ElementTreeC14NTest)])
4934 suite.addTests([unittest.makeSuite(ElementTreeElementSlicingTest)])
4935 if cElementTree:
4936 suite.addTests([unittest.makeSuite(CElementTreeTestCase)])
4937 suite.addTests([unittest.makeSuite(CElementTreeElementSlicingTest)])
4938 return suite
4939
4940 if __name__ == '__main__':
4941 print('to test use test.py %s' % __file__)
4942
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Jul 11 05:50:13 2020 | http://epydoc.sourceforge.net |