1 # -*- coding: utf-8 -*-
4 Tests for the ElementTree API
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.
11 from __future__ import absolute_import
21 from contextlib import contextmanager
22 from functools import wraps, partial
23 from itertools import islice
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
32 if cElementTree is not None and (CET_VERSION <= (1,0,7) or sys.version_info[0] >= 3):
35 if ElementTree is not None:
36 print("Comparing with ElementTree %s" % getattr(ElementTree, "VERSION", "?"))
38 if cElementTree is not None:
39 print("Comparing with cElementTree %s" % getattr(cElementTree, "VERSION", "?"))
42 def et_needs_pyversion(*version):
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)
53 class _ETreeTestCaseBase(HelperTestCase):
55 required_versions_ET = {}
56 required_versions_cET = {}
58 def XMLParser(self, **kwargs):
60 XMLParser = self.etree.XMLParser
61 except AttributeError:
62 assert 'ElementTree' in self.etree.__name__
63 XMLParser = self.etree.TreeBuilder
64 return XMLParser(**kwargs)
67 HelperTestCase.assertRegex
68 except AttributeError:
69 def assertRegex(self, *args, **kwargs):
70 return self.assertRegexpMatches(*args, **kwargs)
72 @et_needs_pyversion(3, 6)
73 def test_interface(self):
74 # Test element tree interface.
76 def check_string(string):
79 self.assertEqual(len(char), 1,
80 msg="expected one-character string, got %r" % char)
81 new_string = string + ""
82 new_string = string + " "
85 def check_mapping(mapping):
88 items = mapping.items()
91 mapping["key"] = "value"
92 self.assertEqual(mapping["key"], "value",
93 msg="expected value string, got %r" % mapping["key"])
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)
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)
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")
123 # Make sure all standard element methods exist.
125 def check_method(method):
126 self.assertTrue(hasattr(method, '__call__'),
127 msg="%s not callable" % method)
129 check_method(element.append)
130 check_method(element.extend)
131 check_method(element.insert)
132 check_method(element.remove)
133 check_method(element.getchildren)
134 check_method(element.find)
135 check_method(element.iterfind)
136 check_method(element.findall)
137 check_method(element.findtext)
138 check_method(element.clear)
139 check_method(element.get)
140 check_method(element.set)
141 check_method(element.keys)
142 check_method(element.items)
143 check_method(element.iter)
144 check_method(element.itertext)
145 check_method(element.getiterator)
147 # These methods return an iterable. See bug 6472.
150 check_method(it.next if IS_PYTHON2 else it.__next__)
152 check_iter(element.iterfind("tag"))
153 check_iter(element.iterfind("*"))
154 check_iter(tree.iterfind("tag"))
155 check_iter(tree.iterfind("*"))
157 # These aliases are provided:
159 # not an alias in lxml
160 #self.assertEqual(self.etree.XML, self.etree.fromstring)
161 self.assertEqual(self.etree.PI, self.etree.ProcessingInstruction)
163 def test_element(self):
165 e = self.etree.Element('foo')
166 self.assertEqual(e.tag, 'foo')
167 self.assertEqual(e.text, None)
168 self.assertEqual(e.tail, None)
170 def test_simple(self):
171 Element = self.etree.Element
173 root = Element('root')
174 root.append(Element('one'))
175 root.append(Element('two'))
176 root.append(Element('three'))
177 self.assertEqual(3, len(root))
178 self.assertEqual('one', root[0].tag)
179 self.assertEqual('two', root[1].tag)
180 self.assertEqual('three', root[2].tag)
181 self.assertRaises(IndexError, operator.getitem, root, 3)
183 # test weird dictionary interaction leading to segfault previously
184 def test_weird_dict_interaction(self):
185 root = self.etree.Element('root')
186 self.assertEqual(root.tag, "root")
187 add = self.etree.ElementTree(file=BytesIO('<foo>Foo</foo>'))
188 self.assertEqual(add.getroot().tag, "foo")
189 self.assertEqual(add.getroot().text, "Foo")
190 root.append(self.etree.Element('baz'))
191 self.assertEqual(root.tag, "root")
192 self.assertEqual(root[0].tag, "baz")
194 def test_subelement(self):
195 Element = self.etree.Element
196 SubElement = self.etree.SubElement
198 root = Element('root')
199 SubElement(root, 'one')
200 SubElement(root, 'two')
201 SubElement(root, 'three')
202 self.assertEqual(3, len(root))
203 self.assertEqual('one', root[0].tag)
204 self.assertEqual('two', root[1].tag)
205 self.assertEqual('three', root[2].tag)
207 def test_element_contains(self):
208 Element = self.etree.Element
209 SubElement = self.etree.SubElement
211 root1 = Element('root')
212 SubElement(root1, 'one')
213 self.assertTrue(root1[0] in root1)
215 root2 = Element('root')
216 SubElement(root2, 'two')
217 SubElement(root2, 'three')
218 self.assertTrue(root2[0] in root2)
219 self.assertTrue(root2[1] in root2)
221 self.assertFalse(root1[0] in root2)
222 self.assertFalse(root2[0] in root1)
223 self.assertFalse(None in root2)
225 def test_element_indexing_with_text(self):
226 ElementTree = self.etree.ElementTree
228 f = BytesIO('<doc>Test<one>One</one></doc>')
229 doc = ElementTree(file=f)
231 self.assertEqual(1, len(root))
232 self.assertEqual('one', root[0].tag)
233 self.assertRaises(IndexError, operator.getitem, root, 1)
235 def test_element_indexing_with_text2(self):
236 ElementTree = self.etree.ElementTree
238 f = BytesIO('<doc><one>One</one><two>Two</two>hm<three>Three</three></doc>')
239 doc = ElementTree(file=f)
241 self.assertEqual(3, len(root))
242 self.assertEqual('one', root[0].tag)
243 self.assertEqual('two', root[1].tag)
244 self.assertEqual('three', root[2].tag)
246 def test_element_indexing_only_text(self):
247 ElementTree = self.etree.ElementTree
249 f = BytesIO('<doc>Test</doc>')
250 doc = ElementTree(file=f)
252 self.assertEqual(0, len(root))
254 def test_element_indexing_negative(self):
255 Element = self.etree.Element
256 SubElement = self.etree.SubElement
258 b = SubElement(a, 'b')
259 c = SubElement(a, 'c')
260 d = SubElement(a, 'd')
261 self.assertEqual(d, a[-1])
262 self.assertEqual(c, a[-2])
263 self.assertEqual(b, a[-3])
264 self.assertRaises(IndexError, operator.getitem, a, -4)
265 a[-1] = e = Element('e')
266 self.assertEqual(e, a[-1])
268 self.assertEqual(2, len(a))
270 def test_elementtree(self):
271 ElementTree = self.etree.ElementTree
273 f = BytesIO('<doc><one>One</one><two>Two</two></doc>')
274 doc = ElementTree(file=f)
276 self.assertEqual(2, len(root))
277 self.assertEqual('one', root[0].tag)
278 self.assertEqual('two', root[1].tag)
281 ElementTree = self.etree.ElementTree
283 f = BytesIO('<doc>This is a text</doc>')
284 doc = ElementTree(file=f)
286 self.assertEqual('This is a text', root.text)
288 def test_text_empty(self):
289 ElementTree = self.etree.ElementTree
291 f = BytesIO('<doc></doc>')
292 doc = ElementTree(file=f)
294 self.assertEqual(None, root.text)
296 def test_text_other(self):
297 ElementTree = self.etree.ElementTree
299 f = BytesIO('<doc><one>One</one></doc>')
300 doc = ElementTree(file=f)
302 self.assertEqual(None, root.text)
303 self.assertEqual('One', root[0].text)
305 def test_text_escape_in(self):
306 ElementTree = self.etree.ElementTree
308 f = BytesIO('<doc>This is > than a text</doc>')
309 doc = ElementTree(file=f)
311 self.assertEqual('This is > than a text', root.text)
313 def test_text_escape_out(self):
314 Element = self.etree.Element
318 self.assertXML(_bytes('<a><>&</a>'),
321 def test_text_escape_tostring(self):
322 tostring = self.etree.tostring
323 Element = self.etree.Element
327 self.assertEqual(_bytes('<a><>&</a>'),
330 def test_text_str_subclass(self):
331 Element = self.etree.Element
337 a.text = strTest("text")
338 self.assertXML(_bytes('<a>text</a>'),
342 ElementTree = self.etree.ElementTree
344 f = BytesIO('<doc>This is <i>mixed</i> content.</doc>')
345 doc = ElementTree(file=f)
347 self.assertEqual(1, len(root))
348 self.assertEqual('This is ', root.text)
349 self.assertEqual(None, root.tail)
350 self.assertEqual('mixed', root[0].text)
351 self.assertEqual(' content.', root[0].tail)
353 def test_tail_str_subclass(self):
354 Element = self.etree.Element
355 SubElement = self.etree.SubElement
361 SubElement(a, "t").tail = strTest("tail")
362 self.assertXML(_bytes('<a><t></t>tail</a>'),
365 def _test_del_tail(self):
366 # this is discouraged for ET compat, should not be tested...
369 root = XML(_bytes('<doc>This is <i>mixed</i> content.</doc>'))
370 self.assertEqual(1, len(root))
371 self.assertEqual('This is ', root.text)
372 self.assertEqual(None, root.tail)
373 self.assertEqual('mixed', root[0].text)
374 self.assertEqual(' content.', root[0].tail)
378 self.assertEqual(1, len(root))
379 self.assertEqual('This is ', root.text)
380 self.assertEqual(None, root.tail)
381 self.assertEqual('mixed', root[0].text)
382 self.assertEqual(None, root[0].tail)
384 root[0].tail = "TAIL"
386 self.assertEqual(1, len(root))
387 self.assertEqual('This is ', root.text)
388 self.assertEqual(None, root.tail)
389 self.assertEqual('mixed', root[0].text)
390 self.assertEqual('TAIL', root[0].tail)
392 def test_ElementTree(self):
393 Element = self.etree.Element
394 ElementTree = self.etree.ElementTree
397 doc = ElementTree(el)
399 self.assertEqual(None, root.text)
400 self.assertEqual('hoi', root.tag)
402 def test_attrib(self):
403 ElementTree = self.etree.ElementTree
405 f = BytesIO('<doc one="One" two="Two"/>')
406 doc = ElementTree(file=f)
408 self.assertEqual('One', root.attrib['one'])
409 self.assertEqual('Two', root.attrib['two'])
410 self.assertRaises(KeyError, operator.getitem, root.attrib, 'three')
412 def test_attrib_get(self):
413 ElementTree = self.etree.ElementTree
415 f = BytesIO('<doc one="One" two="Two"/>')
416 doc = ElementTree(file=f)
418 self.assertEqual('One', root.attrib.get('one'))
419 self.assertEqual('Two', root.attrib.get('two'))
420 self.assertEqual(None, root.attrib.get('three'))
421 self.assertEqual('foo', root.attrib.get('three', 'foo'))
423 def test_attrib_dict(self):
424 ElementTree = self.etree.ElementTree
426 f = BytesIO('<doc one="One" two="Two"/>')
427 doc = ElementTree(file=f)
429 attrib = dict(root.attrib)
430 self.assertEqual('One', attrib['one'])
431 self.assertEqual('Two', attrib['two'])
432 self.assertRaises(KeyError, operator.getitem, attrib, 'three')
434 def test_attrib_copy(self):
435 ElementTree = self.etree.ElementTree
437 f = BytesIO('<doc one="One" two="Two"/>')
438 doc = ElementTree(file=f)
440 attrib = copy.copy(root.attrib)
441 self.assertEqual('One', attrib['one'])
442 self.assertEqual('Two', attrib['two'])
443 self.assertRaises(KeyError, operator.getitem, attrib, 'three')
445 def test_attrib_deepcopy(self):
446 ElementTree = self.etree.ElementTree
448 f = BytesIO('<doc one="One" two="Two"/>')
449 doc = ElementTree(file=f)
451 attrib = copy.deepcopy(root.attrib)
452 self.assertEqual('One', attrib['one'])
453 self.assertEqual('Two', attrib['two'])
454 self.assertRaises(KeyError, operator.getitem, attrib, 'three')
456 def test_attributes_get(self):
457 ElementTree = self.etree.ElementTree
459 f = BytesIO('<doc one="One" two="Two"/>')
460 doc = ElementTree(file=f)
462 self.assertEqual('One', root.get('one'))
463 self.assertEqual('Two', root.get('two'))
464 self.assertEqual(None, root.get('three'))
465 self.assertEqual('foo', root.get('three', 'foo'))
467 def test_attrib_clear(self):
470 root = XML(_bytes('<doc one="One" two="Two"/>'))
471 self.assertEqual('One', root.get('one'))
472 self.assertEqual('Two', root.get('two'))
474 self.assertEqual(None, root.get('one'))
475 self.assertEqual(None, root.get('two'))
477 def test_attrib_set_clear(self):
478 Element = self.etree.Element
480 root = Element("root", one="One")
481 root.set("two", "Two")
482 self.assertEqual('One', root.get('one'))
483 self.assertEqual('Two', root.get('two'))
485 self.assertEqual(None, root.get('one'))
486 self.assertEqual(None, root.get('two'))
488 def test_attrib_ns_clear(self):
489 Element = self.etree.Element
490 SubElement = self.etree.SubElement
492 attribNS = '{http://foo/bar}x'
494 parent = Element('parent')
495 parent.set(attribNS, 'a')
496 child = SubElement(parent, 'child')
497 child.set(attribNS, 'b')
499 self.assertEqual('a', parent.get(attribNS))
500 self.assertEqual('b', child.get(attribNS))
503 self.assertEqual(None, parent.get(attribNS))
504 self.assertEqual('b', child.get(attribNS))
506 def test_attrib_pop(self):
507 ElementTree = self.etree.ElementTree
509 f = BytesIO('<doc one="One" two="Two"/>')
510 doc = ElementTree(file=f)
512 self.assertEqual('One', root.attrib['one'])
513 self.assertEqual('Two', root.attrib['two'])
515 self.assertEqual('One', root.attrib.pop('one'))
517 self.assertEqual(None, root.attrib.get('one'))
518 self.assertEqual('Two', root.attrib['two'])
520 def test_attrib_pop_unknown(self):
521 root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
522 self.assertRaises(KeyError, root.attrib.pop, 'NONE')
524 self.assertEqual('One', root.attrib['one'])
525 self.assertEqual('Two', root.attrib['two'])
527 def test_attrib_pop_default(self):
528 root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
529 self.assertEqual('Three', root.attrib.pop('three', 'Three'))
531 def test_attrib_pop_empty_default(self):
532 root = self.etree.XML(_bytes('<doc/>'))
533 self.assertEqual('Three', root.attrib.pop('three', 'Three'))
535 def test_attrib_pop_invalid_args(self):
536 root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
537 self.assertRaises(TypeError, root.attrib.pop, 'One', None, None)
539 def test_attribute_update_dict(self):
542 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
543 items = list(root.attrib.items())
546 [('alpha', 'Alpha'), ('beta', 'Beta')],
549 root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'})
551 items = list(root.attrib.items())
554 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
557 def test_attribute_update_sequence(self):
560 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
561 items = list(root.attrib.items())
564 [('alpha', 'Alpha'), ('beta', 'Beta')],
567 root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'}.items())
569 items = list(root.attrib.items())
572 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
575 def test_attribute_update_iter(self):
578 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
579 items = list(root.attrib.items())
582 [('alpha', 'Alpha'), ('beta', 'Beta')],
585 root.attrib.update(iter({'alpha' : 'test', 'gamma' : 'Gamma'}.items()))
587 items = list(root.attrib.items())
590 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
593 def test_attribute_update_attrib(self):
596 root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
597 items = list(root.attrib.items())
600 [('alpha', 'Alpha'), ('beta', 'Beta')],
603 other = XML(_bytes('<doc alpha="test" gamma="Gamma"/>'))
604 root.attrib.update(other.attrib)
606 items = list(root.attrib.items())
609 [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
612 def test_attribute_keys(self):
615 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
616 keys = list(root.attrib.keys())
618 self.assertEqual(['alpha', 'beta', 'gamma'], keys)
620 def test_attribute_keys2(self):
623 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
624 keys = list(root.keys())
626 self.assertEqual(['alpha', 'beta', 'gamma'], keys)
628 def test_attribute_items2(self):
631 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
632 items = list(root.items())
635 [('alpha','Alpha'), ('beta','Beta'), ('gamma','Gamma')],
638 def test_attribute_keys_ns(self):
641 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
642 keys = list(root.keys())
644 self.assertEqual(['bar', '{http://ns.codespeak.net/test}baz'],
647 def test_attribute_values(self):
650 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
651 values = list(root.attrib.values())
653 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
655 def test_attribute_values_ns(self):
658 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
659 values = list(root.attrib.values())
662 ['Bar', 'Baz'], values)
664 def test_attribute_items(self):
667 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
668 items = list(root.attrib.items())
677 def test_attribute_items_ns(self):
680 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
681 items = list(root.attrib.items())
684 [('bar', 'Bar'), ('{http://ns.codespeak.net/test}baz', 'Baz')],
687 def test_attribute_str(self):
690 expected = "{'{http://ns.codespeak.net/test}baz': 'Baz', 'bar': 'Bar'}"
691 alternative = "{'bar': 'Bar', '{http://ns.codespeak.net/test}baz': 'Baz'}"
693 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
695 self.assertEqual(expected, str(root.attrib))
696 except AssertionError:
697 self.assertEqual(alternative, str(root.attrib))
699 def test_attribute_contains(self):
702 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
704 True, 'bar' in root.attrib)
706 False, 'baz' in root.attrib)
708 False, 'hah' in root.attrib)
711 '{http://ns.codespeak.net/test}baz' in root.attrib)
713 def test_attribute_set(self):
714 Element = self.etree.Element
716 root = Element("root")
717 root.set("attr", "TEST")
718 self.assertEqual("TEST", root.get("attr"))
720 def test_attrib_as_attrib(self):
721 Element = self.etree.Element
723 root = Element("root")
724 root.set("attr", "TEST")
725 self.assertEqual("TEST", root.attrib["attr"])
727 root2 = Element("root2", root.attrib)
728 self.assertEqual("TEST", root2.attrib["attr"])
730 def test_attribute_iterator(self):
733 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma" />'))
735 for key in root.attrib:
738 self.assertEqual(['alpha', 'beta', 'gamma'], result)
740 def test_attribute_manipulation(self):
741 Element = self.etree.Element
744 a.attrib['foo'] = 'Foo'
745 a.attrib['bar'] = 'Bar'
746 self.assertEqual('Foo', a.attrib['foo'])
748 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
750 def test_del_attribute_ns(self):
751 Element = self.etree.Element
754 a.attrib['{http://a/}foo'] = 'Foo'
755 a.attrib['{http://a/}bar'] = 'Bar'
756 self.assertEqual(None, a.get('foo'))
757 self.assertEqual('Foo', a.get('{http://a/}foo'))
758 self.assertEqual('Foo', a.attrib['{http://a/}foo'])
760 self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
761 self.assertEqual('Foo', a.attrib['{http://a/}foo'])
763 del a.attrib['{http://a/}foo']
764 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
766 def test_del_attribute_ns_parsed(self):
769 a = XML(_bytes('<a xmlns:nsa="http://a/" nsa:foo="FooNS" foo="Foo" />'))
771 self.assertEqual('Foo', a.attrib['foo'])
772 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
775 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
776 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
777 self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
779 del a.attrib['{http://a/}foo']
780 self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
781 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
783 a = XML(_bytes('<a xmlns:nsa="http://a/" foo="Foo" nsa:foo="FooNS" />'))
785 self.assertEqual('Foo', a.attrib['foo'])
786 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
789 self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
790 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
792 del a.attrib['{http://a/}foo']
793 self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
794 self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
799 root = XML(_bytes('<doc>This is a text.</doc>'))
800 self.assertEqual(0, len(root))
801 self.assertEqual('This is a text.', root.text)
803 def test_XMLID(self):
804 XMLID = self.etree.XMLID
806 xml_text = _bytes('''
808 <h1 id="chapter1">...</h1>
809 <p id="note1" class="note">...</p>
810 <p>Regular paragraph.</p>
811 <p xml:id="xmlid">XML:ID paragraph.</p>
812 <p id="warn1" class="warning">...</p>
816 root, dic = XMLID(xml_text)
817 root2 = XML(xml_text)
818 self.assertEqual(self._writeElement(root),
819 self._writeElement(root2))
821 "chapter1" : root[0],
825 self.assertEqual(dic, expected)
827 def test_fromstring(self):
828 fromstring = self.etree.fromstring
830 root = fromstring('<doc>This is a text.</doc>')
831 self.assertEqual(0, len(root))
832 self.assertEqual('This is a text.', root.text)
834 required_versions_ET['test_fromstringlist'] = (1,3)
835 def test_fromstringlist(self):
836 fromstringlist = self.etree.fromstringlist
838 root = fromstringlist(["<do", "c>T", "hi", "s is",
839 " a text.<", "/doc", ">"])
840 self.assertEqual(0, len(root))
841 self.assertEqual('This is a text.', root.text)
843 required_versions_ET['test_fromstringlist_characters'] = (1,3)
844 def test_fromstringlist_characters(self):
845 fromstringlist = self.etree.fromstringlist
847 root = fromstringlist(list('<doc>This is a text.</doc>'))
848 self.assertEqual(0, len(root))
849 self.assertEqual('This is a text.', root.text)
851 required_versions_ET['test_fromstringlist_single'] = (1,3)
852 def test_fromstringlist_single(self):
853 fromstringlist = self.etree.fromstringlist
855 root = fromstringlist(['<doc>This is a text.</doc>'])
856 self.assertEqual(0, len(root))
857 self.assertEqual('This is a text.', root.text)
859 def test_iselement(self):
860 iselement = self.etree.iselement
861 Element = self.etree.Element
862 ElementTree = self.etree.ElementTree
864 Comment = self.etree.Comment
865 ProcessingInstruction = self.etree.ProcessingInstruction
868 self.assertTrue(iselement(el))
870 el2 = XML(_bytes('<foo/>'))
871 self.assertTrue(iselement(el2))
873 tree = ElementTree(element=Element('dag'))
874 self.assertTrue(not iselement(tree))
875 self.assertTrue(iselement(tree.getroot()))
878 self.assertTrue(iselement(c))
880 p = ProcessingInstruction("test", "some text")
881 self.assertTrue(iselement(p))
883 def test_iteration(self):
886 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
889 result.append(el.tag)
890 self.assertEqual(['one', 'two', 'three'], result)
892 def test_iteration_empty(self):
895 root = XML(_bytes('<doc></doc>'))
898 result.append(el.tag)
899 self.assertEqual([], result)
901 def test_iteration_text_only(self):
904 root = XML(_bytes('<doc>Text</doc>'))
907 result.append(el.tag)
908 self.assertEqual([], result)
910 def test_iteration_set_tail_empty(self):
911 # this would cause a crash in the past
912 fromstring = self.etree.fromstring
913 root = fromstring('<html><p></p>x</html>')
917 def test_iteration_clear_tail(self):
918 # this would cause a crash in the past
919 fromstring = self.etree.fromstring
920 root = fromstring('<html><p></p>x</html>')
924 def test_iteration_reversed(self):
926 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
928 for el in reversed(root):
929 result.append(el.tag)
930 self.assertEqual(['three', 'two', 'one'], result)
932 def test_iteration_subelement(self):
935 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
939 result.append(el.tag)
941 self.etree.SubElement(root, 'four')
943 self.assertEqual(['one', 'two', 'three', 'four'], result)
945 def test_iteration_del_child(self):
948 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
951 result.append(el.tag)
953 self.assertEqual(['one', 'two'], result)
955 def test_iteration_double(self):
958 root = XML(_bytes('<doc><one/><two/></doc>'))
961 result.append(el0.tag)
963 result.append(el1.tag)
964 self.assertEqual(['one','one', 'two', 'two', 'one', 'two'], result)
966 required_versions_ET['test_itertext'] = (1,3)
967 def test_itertext(self):
970 root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
972 text = list(root.itertext())
973 self.assertEqual(["RTEXT", "ATAIL", "CTEXT", "CTAIL"],
976 required_versions_ET['test_itertext_child'] = (1,3)
977 def test_itertext_child(self):
980 root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
982 text = list(root[2].itertext())
983 self.assertEqual(["CTEXT"],
986 def test_findall(self):
988 root = XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))
989 self.assertEqual(len(list(root.findall("c"))), 1)
990 self.assertEqual(len(list(root.findall(".//c"))), 2)
991 self.assertEqual(len(list(root.findall(".//b"))), 3)
992 self.assertEqual(len(list(root.findall(".//b"))[0]), 1)
993 self.assertEqual(len(list(root.findall(".//b"))[1]), 0)
994 self.assertEqual(len(list(root.findall(".//b"))[2]), 0)
996 def test_findall_ns(self):
998 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
999 self.assertEqual(len(list(root.findall(".//{X}b"))), 2)
1000 self.assertEqual(len(list(root.findall(".//b"))), 3)
1001 self.assertEqual(len(list(root.findall("b"))), 2)
1003 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
1004 def test_findall_wildcard(self):
1005 def summarize_list(l):
1006 return [el.tag for el in l]
1008 root = self.etree.XML('''
1009 <a xmlns:x="X" xmlns:y="Y">
1012 <c><x:b/><b/></c><y:b/>
1014 root.append(self.etree.Comment('test'))
1016 self.assertEqual(summarize_list(root.findall("{*}b")),
1017 ['{X}b', 'b', '{Y}b'])
1018 self.assertEqual(summarize_list(root.findall("{*}c")),
1020 self.assertEqual(summarize_list(root.findall("{X}*")),
1022 self.assertEqual(summarize_list(root.findall("{Y}*")),
1024 self.assertEqual(summarize_list(root.findall("{}*")),
1026 self.assertEqual(summarize_list(root.findall("{}b")), # only for consistency
1028 self.assertEqual(summarize_list(root.findall("{}b")),
1029 summarize_list(root.findall("b")))
1030 self.assertEqual(summarize_list(root.findall("{*}*")),
1031 ['{X}b', 'b', 'c', '{Y}b'])
1032 self.assertEqual(summarize_list(root.findall("{*}*")
1033 + ([] if self.etree is etree else [root[-1]])),
1034 summarize_list(root.findall("*")))
1036 self.assertEqual(summarize_list(root.findall(".//{*}b")),
1037 ['{X}b', 'b', '{X}b', 'b', '{Y}b'])
1038 self.assertEqual(summarize_list(root.findall(".//{*}c")),
1040 self.assertEqual(summarize_list(root.findall(".//{X}*")),
1042 self.assertEqual(summarize_list(root.findall(".//{Y}*")),
1044 self.assertEqual(summarize_list(root.findall(".//{}*")),
1045 ['c', 'b', 'c', 'b'])
1046 self.assertEqual(summarize_list(root.findall(".//{}b")),
1049 def test_element_with_attributes_keywords(self):
1050 Element = self.etree.Element
1052 el = Element('tag', foo='Foo', bar='Bar')
1053 self.assertEqual('Foo', el.attrib['foo'])
1054 self.assertEqual('Bar', el.attrib['bar'])
1056 def test_element_with_attributes(self):
1057 Element = self.etree.Element
1059 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'})
1060 self.assertEqual('Foo', el.attrib['foo'])
1061 self.assertEqual('Bar', el.attrib['bar'])
1063 def test_element_with_attributes_extra(self):
1064 Element = self.etree.Element
1066 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, baz='Baz')
1067 self.assertEqual('Foo', el.attrib['foo'])
1068 self.assertEqual('Bar', el.attrib['bar'])
1069 self.assertEqual('Baz', el.attrib['baz'])
1071 def test_element_with_attributes_extra_duplicate(self):
1072 Element = self.etree.Element
1074 el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, bar='Baz')
1075 self.assertEqual('Foo', el.attrib['foo'])
1076 self.assertEqual('Baz', el.attrib['bar'])
1078 def test_element_with_attributes_ns(self):
1079 Element = self.etree.Element
1081 el = Element('tag', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
1082 self.assertEqual('Foo', el.attrib['{ns1}foo'])
1083 self.assertEqual('Bar', el.attrib['{ns2}bar'])
1085 def test_subelement_with_attributes(self):
1086 Element = self.etree.Element
1087 SubElement = self.etree.SubElement
1090 SubElement(el, 'foo', {'foo':'Foo'}, baz="Baz")
1091 self.assertEqual("Baz", el[0].attrib['baz'])
1092 self.assertEqual('Foo', el[0].attrib['foo'])
1094 def test_subelement_with_attributes_ns(self):
1095 Element = self.etree.Element
1096 SubElement = self.etree.SubElement
1099 SubElement(el, 'foo', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
1100 self.assertEqual('Foo', el[0].attrib['{ns1}foo'])
1101 self.assertEqual('Bar', el[0].attrib['{ns2}bar'])
1103 def test_write(self):
1104 ElementTree = self.etree.ElementTree
1105 XML = self.etree.XML
1109 root = XML(_bytes('<doc%s>This is a test.</doc%s>' % (i, i)))
1110 tree = ElementTree(element=root)
1114 _bytes('<doc%s>This is a test.</doc%s>' % (i, i)),
1117 required_versions_ET['test_write_method_html'] = (1,3)
1118 def test_write_method_html(self):
1119 ElementTree = self.etree.ElementTree
1120 Element = self.etree.Element
1121 SubElement = self.etree.SubElement
1123 html = Element('html')
1124 body = SubElement(html, 'body')
1125 p = SubElement(body, 'p')
1127 SubElement(p, 'br').tail = "test"
1129 tree = ElementTree(element=html)
1131 tree.write(f, method="html")
1132 data = f.getvalue().replace(_bytes('\n'),_bytes(''))
1134 self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
1137 required_versions_ET['test_write_method_text'] = (1,3)
1138 def test_write_method_text(self):
1139 ElementTree = self.etree.ElementTree
1140 Element = self.etree.Element
1141 SubElement = self.etree.SubElement
1146 b = SubElement(a, 'b')
1149 c = SubElement(a, 'c')
1152 tree = ElementTree(element=a)
1154 tree.write(f, method="text")
1157 self.assertEqual(_bytes('ABTAILCtail'),
1160 def test_write_fail(self):
1161 ElementTree = self.etree.ElementTree
1162 XML = self.etree.XML
1164 tree = ElementTree( XML(_bytes('<doc>This is a test.</doc>')) )
1165 self.assertRaises(IOError, tree.write,
1166 "definitely////\\-\\nonexisting\\-\\////FILE")
1168 # this could trigger a crash, apparently because the document
1169 # reference was prematurely garbage collected
1170 def test_crash(self):
1171 Element = self.etree.Element
1173 element = Element('tag')
1175 element.attrib['key'] = 'value'
1176 value = element.attrib['key']
1177 self.assertEqual(value, 'value')
1179 # from doctest; for some reason this caused crashes too
1180 def test_write_ElementTreeDoctest(self):
1181 Element = self.etree.Element
1182 ElementTree = self.etree.ElementTree
1186 element = Element('tag%s' % i)
1187 self._check_element(element)
1188 tree = ElementTree(element)
1190 self._check_element_tree(tree)
1192 def test_subelement_reference(self):
1193 Element = self.etree.Element
1194 SubElement = self.etree.SubElement
1197 el2 = SubElement(el, 'bar')
1198 el3 = SubElement(el2, 'baz')
1200 al = Element('foo2')
1201 al2 = SubElement(al, 'bar2')
1202 al3 = SubElement(al2, 'baz2')
1204 # now move al2 into el
1207 # now change al3 directly
1208 al3.text = 'baz2-modified'
1210 # it should have changed through this route too
1215 def test_set_text(self):
1216 Element = self.etree.Element
1217 SubElement = self.etree.SubElement
1220 b = SubElement(a, 'b')
1229 def test_set_text2(self):
1230 Element = self.etree.Element
1231 SubElement = self.etree.SubElement
1235 b = SubElement(a ,'b')
1243 def test_set_text_none(self):
1244 Element = self.etree.Element
1254 self.assertXML(_bytes('<a></a>'), a)
1256 def test_set_text_empty(self):
1257 Element = self.etree.Element
1260 self.assertEqual(None, a.text)
1263 self.assertEqual('', a.text)
1264 self.assertXML(_bytes('<a></a>'), a)
1266 def test_tail1(self):
1267 Element = self.etree.Element
1268 SubElement = self.etree.SubElement
1272 self.assertEqual('dag',
1274 b = SubElement(a, 'b')
1276 self.assertEqual('hoi',
1278 self.assertEqual('dag',
1281 def test_tail_append(self):
1282 Element = self.etree.Element
1288 self.assertEqual('b_tail',
1291 def test_tail_set_twice(self):
1292 Element = self.etree.Element
1293 SubElement = self.etree.SubElement
1296 b = SubElement(a, 'b')
1299 self.assertEqual('bar',
1301 self.assertXML(_bytes('<a><b></b>bar</a>'), a)
1303 def test_tail_set_none(self):
1304 Element = self.etree.Element
1311 self.assertXML(_bytes('<a></a>'), a)
1313 required_versions_ET['test_extend'] = (1,3)
1314 def test_extend(self):
1315 root = self.etree.Element('foo')
1317 element = self.etree.SubElement(root, 'a%s' % i)
1318 element.text = "text%d" % i
1319 element.tail = "tail%d" % i
1323 new_element = self.etree.Element("test%s" % i)
1324 new_element.text = "TEXT%s" % i
1325 new_element.tail = "TAIL%s" % i
1326 elements.append(new_element)
1328 root.extend(elements)
1331 ["a0", "a1", "a2", "test0", "test1", "test2"],
1332 [ el.tag for el in root ])
1334 ["text0", "text1", "text2", "TEXT0", "TEXT1", "TEXT2"],
1335 [ el.text for el in root ])
1337 ["tail0", "tail1", "tail2", "TAIL0", "TAIL1", "TAIL2"],
1338 [ el.tail for el in root ])
1340 def test_comment(self):
1341 Element = self.etree.Element
1342 SubElement = self.etree.SubElement
1343 Comment = self.etree.Comment
1346 a.append(Comment('foo'))
1347 self.assertEqual(a[0].tag, Comment)
1348 self.assertEqual(a[0].text, 'foo')
1350 # ElementTree < 1.3 adds whitespace around comments
1351 required_versions_ET['test_comment_text'] = (1,3)
1352 def test_comment_text(self):
1353 Element = self.etree.Element
1354 SubElement = self.etree.SubElement
1355 Comment = self.etree.Comment
1356 tostring = self.etree.tostring
1359 a.append(Comment('foo'))
1360 self.assertEqual(a[0].text, 'foo')
1363 _bytes('<a><!--foo--></a>'),
1367 self.assertEqual(a[0].text, 'TEST')
1370 _bytes('<a><!--TEST--></a>'),
1373 # ElementTree < 1.3 adds whitespace around comments
1374 required_versions_ET['test_comment_whitespace'] = (1,3)
1375 def test_comment_whitespace(self):
1376 Element = self.etree.Element
1377 SubElement = self.etree.SubElement
1378 Comment = self.etree.Comment
1379 tostring = self.etree.tostring
1382 a.append(Comment(' foo '))
1383 self.assertEqual(a[0].text, ' foo ')
1385 _bytes('<a><!-- foo --></a>'),
1388 def test_comment_nonsense(self):
1389 Comment = self.etree.Comment
1391 self.assertEqual({}, c.attrib)
1392 self.assertEqual([], list(c.keys()))
1393 self.assertEqual([], list(c.items()))
1394 self.assertEqual(None, c.get('hoi'))
1395 self.assertEqual(0, len(c))
1396 # should not iterate
1401 # lxml.etree separates target and text
1402 Element = self.etree.Element
1403 SubElement = self.etree.SubElement
1404 ProcessingInstruction = self.etree.ProcessingInstruction
1407 a.append(ProcessingInstruction('foo', 'some more text'))
1408 self.assertEqual(a[0].tag, ProcessingInstruction)
1409 self.assertXML(_bytes("<a><?foo some more text?></a>"),
1412 def test_processinginstruction(self):
1413 # lxml.etree separates target and text
1414 Element = self.etree.Element
1415 SubElement = self.etree.SubElement
1416 ProcessingInstruction = self.etree.PI
1419 a.append(ProcessingInstruction('foo', 'some more text'))
1420 self.assertEqual(a[0].tag, ProcessingInstruction)
1421 self.assertXML(_bytes("<a><?foo some more text?></a>"),
1424 def test_pi_nonsense(self):
1425 ProcessingInstruction = self.etree.ProcessingInstruction
1426 pi = ProcessingInstruction('foo')
1427 self.assertEqual({}, pi.attrib)
1428 self.assertEqual([], list(pi.keys()))
1429 self.assertEqual([], list(pi.items()))
1430 self.assertEqual(None, pi.get('hoi'))
1431 self.assertEqual(0, len(pi))
1432 # should not iterate
1436 def test_setitem(self):
1437 Element = self.etree.Element
1438 SubElement = self.etree.SubElement
1441 b = SubElement(a, 'b')
1447 self.assertXML(_bytes('<a><c></c></a>'),
1449 self.assertXML(_bytes('<b></b>'),
1452 def test_setitem2(self):
1453 Element = self.etree.Element
1454 SubElement = self.etree.SubElement
1458 b = SubElement(a, 'b%s' % i)
1459 c = SubElement(b, 'c')
1462 e = SubElement(d, 'e')
1465 _bytes('<a><d><e></e></d><d><e></e></d><d><e></e></d><d><e></e></d><d><e></e></d></a>'),
1467 self.assertXML(_bytes('<c></c>'),
1470 def test_setitem_replace(self):
1471 Element = self.etree.Element
1472 SubElement = self.etree.SubElement
1478 self.assertXML(_bytes('<a><d></d></a>'), a)
1480 def test_setitem_indexerror(self):
1481 Element = self.etree.Element
1482 SubElement = self.etree.SubElement
1485 b = SubElement(a, 'b')
1487 self.assertRaises(IndexError, operator.setitem, a, 1, Element('c'))
1489 def test_setitem_tail(self):
1490 Element = self.etree.Element
1491 SubElement = self.etree.SubElement
1494 b = SubElement(a, 'b')
1501 _bytes('<a><c></c>C2</a>'),
1504 def test_tag_write(self):
1505 Element = self.etree.Element
1506 SubElement = self.etree.SubElement
1509 b = SubElement(a, 'b')
1518 _bytes('<c><b></b></c>'),
1521 def test_tag_reset_ns(self):
1522 Element = self.etree.Element
1523 SubElement = self.etree.SubElement
1524 tostring = self.etree.tostring
1527 b1 = SubElement(a, '{a}b')
1528 b2 = SubElement(a, '{b}b')
1530 self.assertEqual('{a}b', b1.tag)
1534 # can't use C14N here!
1535 self.assertEqual('c', b1.tag)
1536 self.assertEqual(_bytes('<c'), tostring(b1)[:2])
1537 self.assertTrue(_bytes('<c') in tostring(a))
1539 def test_tag_reset_root_ns(self):
1540 Element = self.etree.Element
1541 SubElement = self.etree.SubElement
1542 tostring = self.etree.tostring
1545 b1 = SubElement(a, '{a}b')
1546 b2 = SubElement(a, '{b}b')
1554 # can't use C14N here!
1555 self.assertEqual('c', a.tag)
1556 self.assertEqual(_bytes('<c'), tostring(a)[:2])
1558 def test_tag_str_subclass(self):
1559 Element = self.etree.Element
1565 a.tag = strTest("TAG")
1566 self.assertXML(_bytes('<TAG></TAG>'),
1569 def test_delitem(self):
1570 Element = self.etree.Element
1571 SubElement = self.etree.SubElement
1574 b = SubElement(a, 'b')
1575 c = SubElement(a, 'c')
1576 d = SubElement(a, 'd')
1580 _bytes('<a><b></b><d></d></a>'),
1585 _bytes('<a><d></d></a>'),
1592 # move deleted element into other tree afterwards
1593 other = Element('other')
1596 _bytes('<other><c></c></other>'),
1599 def test_del_insert(self):
1600 Element = self.etree.Element
1601 SubElement = self.etree.SubElement
1604 b = SubElement(a, 'b')
1605 bs = SubElement(b, 'bs')
1606 c = SubElement(a, 'c')
1607 cs = SubElement(c, 'cs')
1611 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1613 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1614 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1618 _bytes('<a><c><cs></cs></c></a>'),
1620 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1621 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1625 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1627 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1628 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1630 def test_del_setitem(self):
1631 Element = self.etree.Element
1632 SubElement = self.etree.SubElement
1635 b = SubElement(a, 'b')
1636 bs = SubElement(b, 'bs')
1637 c = SubElement(a, 'c')
1638 cs = SubElement(c, 'cs')
1644 _bytes('<a><b><bs></bs></b></a>'),
1646 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1647 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1649 def test_del_setslice(self):
1650 Element = self.etree.Element
1651 SubElement = self.etree.SubElement
1654 b = SubElement(a, 'b')
1655 bs = SubElement(b, 'bs')
1656 c = SubElement(a, 'c')
1657 cs = SubElement(c, 'cs')
1663 _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
1665 self.assertXML(_bytes('<b><bs></bs></b>'), b)
1666 self.assertXML(_bytes('<c><cs></cs></c>'), c)
1668 def test_replace_slice_tail(self):
1669 XML = self.etree.XML
1670 a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
1675 self.assertEqual("B2", b.tail)
1676 self.assertEqual("C2", c.tail)
1678 def test_merge_namespaced_subtree_as_slice(self):
1679 XML = self.etree.XML
1681 '<foo><bar xmlns:baz="http://huhu"><puh><baz:bump1 /><baz:bump2 /></puh></bar></foo>'))
1682 root[:] = root.findall('.//puh') # delete bar from hierarchy
1684 # previously, this lost a namespace declaration on bump2
1685 result = self.etree.tostring(root)
1686 foo = self.etree.fromstring(result)
1688 self.assertEqual('puh', foo[0].tag)
1689 self.assertEqual('{http://huhu}bump1', foo[0][0].tag)
1690 self.assertEqual('{http://huhu}bump2', foo[0][1].tag)
1692 def test_delitem_tail_dealloc(self):
1693 ElementTree = self.etree.ElementTree
1694 f = BytesIO('<a><b></b>B2<c></c>C2</a>')
1695 doc = ElementTree(file=f)
1699 _bytes('<a><c></c>C2</a>'),
1702 def test_delitem_tail(self):
1703 ElementTree = self.etree.ElementTree
1704 f = BytesIO('<a><b></b>B2<c></c>C2</a>')
1705 doc = ElementTree(file=f)
1710 _bytes('<a><c></c>C2</a>'),
1712 self.assertEqual("B2", b.tail)
1713 self.assertEqual("C2", c.tail)
1715 def test_clear(self):
1716 Element = self.etree.Element
1723 self.assertEqual(None, a.text)
1724 self.assertEqual(None, a.tail)
1725 self.assertEqual(None, a.get('hoi'))
1726 self.assertEqual('a', a.tag)
1728 def test_clear_sub(self):
1729 Element = self.etree.Element
1730 SubElement = self.etree.SubElement
1736 b = SubElement(a, 'b')
1737 c = SubElement(b, 'c')
1739 self.assertEqual(None, a.text)
1740 self.assertEqual(None, a.tail)
1741 self.assertEqual(None, a.get('hoi'))
1742 self.assertEqual('a', a.tag)
1743 self.assertEqual(0, len(a))
1744 self.assertXML(_bytes('<a></a>'),
1746 self.assertXML(_bytes('<b><c></c></b>'),
1749 def test_clear_tail(self):
1750 ElementTree = self.etree.ElementTree
1751 f = BytesIO('<a><b></b>B2<c></c>C2</a>')
1752 doc = ElementTree(file=f)
1759 def test_insert(self):
1760 Element = self.etree.Element
1761 SubElement = self.etree.SubElement
1764 b = SubElement(a, 'b')
1765 c = SubElement(a, 'c')
1774 _bytes('<a><d></d><b></b><c></c></a>'),
1783 _bytes('<a><d></d><b></b><e></e><c></c></a>'),
1786 def test_insert_name_interning(self):
1787 # See GH#268 / LP#1773749.
1788 Element = self.etree.Element
1789 SubElement = self.etree.SubElement
1791 # Use unique names to make sure they are new in the tag name dict.
1793 names = dict((k, 'tag-' + str(uuid.uuid4())) for k in 'abcde')
1795 a = Element(names['a'])
1796 b = SubElement(a, names['b'])
1797 c = SubElement(a, names['c'])
1798 d = Element(names['d'])
1806 _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(c)s></%(c)s></%(a)s>' % names),
1809 e = Element(names['e'])
1815 _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(e)s></%(e)s><%(c)s></%(c)s></%(a)s>' % names),
1818 def test_insert_beyond_index(self):
1819 Element = self.etree.Element
1820 SubElement = self.etree.SubElement
1823 b = SubElement(a, 'b')
1831 _bytes('<a><b></b><c></c></a>'),
1834 def test_insert_negative(self):
1835 Element = self.etree.Element
1836 SubElement = self.etree.SubElement
1839 b = SubElement(a, 'b')
1840 c = SubElement(a, 'c')
1848 _bytes('<a><b></b><d></d><c></c></a>'),
1851 def test_insert_tail(self):
1852 Element = self.etree.Element
1853 SubElement = self.etree.SubElement
1856 b = SubElement(a, 'b')
1863 _bytes('<a><c></c>C2<b></b></a>'),
1866 def test_remove(self):
1867 Element = self.etree.Element
1868 SubElement = self.etree.SubElement
1871 b = SubElement(a, 'b')
1872 c = SubElement(a, 'c')
1879 _bytes('<a><c></c></a>'),
1882 def test_remove_ns(self):
1883 Element = self.etree.Element
1884 SubElement = self.etree.SubElement
1886 a = Element('{http://test}a')
1887 b = SubElement(a, '{http://test}b')
1888 c = SubElement(a, '{http://test}c')
1892 _bytes('<ns0:a xmlns:ns0="http://test"><ns0:c></ns0:c></ns0:a>'),
1895 _bytes('<ns0:b xmlns:ns0="http://test"></ns0:b>'),
1898 def test_remove_nonexisting(self):
1899 Element = self.etree.Element
1900 SubElement = self.etree.SubElement
1903 b = SubElement(a, 'b')
1904 c = SubElement(a, 'c')
1907 ValueError, a.remove, d)
1909 def test_remove_tail(self):
1910 Element = self.etree.Element
1911 SubElement = self.etree.SubElement
1914 b = SubElement(a, 'b')
1920 self.assertEqual('b2', b.tail)
1922 def test_remove_while_iterating(self):
1923 # There is no guarantee that this "works", but it should
1924 # remove at least one child and not crash.
1925 Element = self.etree.Element
1926 SubElement = self.etree.SubElement
1934 self.assertLess(len(a), 3)
1936 def test_getchildren(self):
1937 Element = self.etree.Element
1938 SubElement = self.etree.SubElement
1941 b = SubElement(a, 'b')
1942 c = SubElement(a, 'c')
1943 d = SubElement(b, 'd')
1944 e = SubElement(c, 'e')
1946 _bytes('<a><b><d></d></b><c><e></e></c></a>'),
1958 def test_makeelement(self):
1959 Element = self.etree.Element
1962 b = a.makeelement('c', {'hoi':'dag'})
1964 _bytes('<c hoi="dag"></c>'),
1967 required_versions_ET['test_iter'] = (1,3)
1968 def test_iter(self):
1969 Element = self.etree.Element
1970 SubElement = self.etree.SubElement
1973 b = SubElement(a, 'b')
1974 c = SubElement(a, 'c')
1975 d = SubElement(b, 'd')
1976 e = SubElement(c, 'e')
1985 def test_iter_remove_tail(self):
1986 Element = self.etree.Element
1987 SubElement = self.etree.SubElement
1992 b = SubElement(a, 'b')
1995 c = SubElement(a, 'c')
1998 d = SubElement(b, 'd')
2001 e = SubElement(c, 'e')
2011 [el.tail for el in a.iter()])
2013 def test_getiterator(self):
2014 Element = self.etree.Element
2015 SubElement = self.etree.SubElement
2018 b = SubElement(a, 'b')
2019 c = SubElement(a, 'c')
2020 d = SubElement(b, 'd')
2021 e = SubElement(c, 'e')
2025 list(a.getiterator()))
2028 list(d.getiterator()))
2030 def test_getiterator_empty(self):
2031 Element = self.etree.Element
2032 SubElement = self.etree.SubElement
2035 b = SubElement(a, 'b')
2036 c = SubElement(a, 'c')
2037 d = SubElement(b, 'd')
2038 e = SubElement(c, 'e')
2042 list(a.getiterator('none')))
2045 list(e.getiterator('none')))
2048 list(e.getiterator()))
2050 def test_getiterator_filter(self):
2051 Element = self.etree.Element
2052 SubElement = self.etree.SubElement
2055 b = SubElement(a, 'b')
2056 c = SubElement(a, 'c')
2057 d = SubElement(b, 'd')
2058 e = SubElement(c, 'e')
2062 list(a.getiterator('a')))
2063 a2 = SubElement(e, 'a')
2066 list(a.getiterator('a')))
2069 list(c.getiterator('a')))
2071 def test_getiterator_filter_all(self):
2072 Element = self.etree.Element
2073 SubElement = self.etree.SubElement
2076 b = SubElement(a, 'b')
2077 c = SubElement(a, 'c')
2078 d = SubElement(b, 'd')
2079 e = SubElement(c, 'e')
2083 list(a.getiterator('*')))
2085 def test_getiterator_filter_comment(self):
2086 Element = self.etree.Element
2087 Comment = self.etree.Comment
2088 SubElement = self.etree.SubElement
2091 b = SubElement(a, 'b')
2092 comment_b = Comment("TEST-b")
2097 list(a.getiterator(Comment)))
2099 comment_a = Comment("TEST-a")
2103 [comment_b, comment_a],
2104 list(a.getiterator(Comment)))
2108 list(b.getiterator(Comment)))
2110 def test_getiterator_filter_pi(self):
2111 Element = self.etree.Element
2112 PI = self.etree.ProcessingInstruction
2113 SubElement = self.etree.SubElement
2116 b = SubElement(a, 'b')
2122 list(a.getiterator(PI)))
2129 list(a.getiterator(PI)))
2133 list(b.getiterator(PI)))
2135 def test_getiterator_with_text(self):
2136 Element = self.etree.Element
2137 SubElement = self.etree.SubElement
2141 b = SubElement(a, 'b')
2144 c = SubElement(a, 'c')
2147 d = SubElement(b, 'd')
2150 e = SubElement(c, 'e')
2156 list(a.getiterator()))
2159 # list(d.getiterator()))
2161 def test_getiterator_filter_with_text(self):
2162 Element = self.etree.Element
2163 SubElement = self.etree.SubElement
2167 b = SubElement(a, 'b')
2170 c = SubElement(a, 'c')
2173 d = SubElement(b, 'd')
2176 e = SubElement(c, 'e')
2182 list(a.getiterator('a')))
2183 a2 = SubElement(e, 'a')
2186 list(a.getiterator('a')))
2189 list(e.getiterator('a')))
2191 def test_getslice(self):
2192 Element = self.etree.Element
2193 SubElement = self.etree.SubElement
2196 b = SubElement(a, 'b')
2197 c = SubElement(a, 'c')
2198 d = SubElement(a, 'd')
2216 def test_getslice_negative(self):
2217 Element = self.etree.Element
2218 SubElement = self.etree.SubElement
2221 b = SubElement(a, 'b')
2222 c = SubElement(a, 'c')
2223 d = SubElement(a, 'd')
2241 def test_getslice_step(self):
2242 Element = self.etree.Element
2243 SubElement = self.etree.SubElement
2246 b = SubElement(a, 'b')
2247 c = SubElement(a, 'c')
2248 d = SubElement(a, 'd')
2249 e = SubElement(a, 'e')
2267 def test_getslice_text(self):
2268 ElementTree = self.etree.ElementTree
2270 f = BytesIO('<a><b>B</b>B1<c>C</c>C1</a>')
2271 doc = ElementTree(file=f)
2285 def test_comment_getitem_getslice(self):
2286 Element = self.etree.Element
2287 Comment = self.etree.Comment
2288 SubElement = self.etree.SubElement
2291 b = SubElement(a, 'b')
2292 foo = Comment('foo')
2294 c = SubElement(a, 'c')
2301 a[1] = new = Element('new')
2306 _bytes('<a><b></b><new></new><c></c></a>'),
2309 def test_delslice(self):
2310 Element = self.etree.Element
2311 SubElement = self.etree.SubElement
2314 b = SubElement(a, 'b')
2315 c = SubElement(a, 'c')
2316 d = SubElement(a, 'd')
2317 e = SubElement(a, 'e')
2324 def test_delslice_negative1(self):
2325 Element = self.etree.Element
2326 SubElement = self.etree.SubElement
2329 b = SubElement(a, 'b')
2330 c = SubElement(a, 'c')
2331 d = SubElement(a, 'd')
2332 e = SubElement(a, 'e')
2339 def test_delslice_negative2(self):
2340 Element = self.etree.Element
2341 SubElement = self.etree.SubElement
2344 b = SubElement(a, 'b')
2345 c = SubElement(a, 'c')
2346 d = SubElement(a, 'd')
2347 e = SubElement(a, 'e')
2354 def test_delslice_step(self):
2355 Element = self.etree.Element
2356 SubElement = self.etree.SubElement
2359 b = SubElement(a, 'b')
2360 c = SubElement(a, 'c')
2361 d = SubElement(a, 'd')
2362 e = SubElement(a, 'e')
2369 def test_delslice_step_negative(self):
2370 Element = self.etree.Element
2371 SubElement = self.etree.SubElement
2374 b = SubElement(a, 'b')
2375 c = SubElement(a, 'c')
2376 d = SubElement(a, 'd')
2377 e = SubElement(a, 'e')
2384 def test_delslice_step_negative2(self):
2385 Element = self.etree.Element
2386 SubElement = self.etree.SubElement
2389 b = SubElement(a, 'b')
2390 c = SubElement(a, 'c')
2391 d = SubElement(a, 'd')
2392 e = SubElement(a, 'e')
2399 def test_delslice_child_tail_dealloc(self):
2400 ElementTree = self.etree.ElementTree
2401 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2402 doc = ElementTree(file=f)
2406 _bytes('<a><b></b>B2<e></e>E2</a>'),
2409 def test_delslice_child_tail(self):
2410 ElementTree = self.etree.ElementTree
2411 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2412 doc = ElementTree(file=f)
2417 _bytes('<a><b></b>B2<e></e>E2</a>'),
2419 self.assertEqual("B2", b.tail)
2420 self.assertEqual("C2", c.tail)
2421 self.assertEqual("D2", d.tail)
2422 self.assertEqual("E2", e.tail)
2424 def test_delslice_tail(self):
2425 XML = self.etree.XML
2426 a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
2431 self.assertEqual("B2", b.tail)
2432 self.assertEqual("C2", c.tail)
2434 def test_delslice_memory(self):
2435 # this could trigger a crash
2436 Element = self.etree.Element
2437 SubElement = self.etree.SubElement
2439 b = SubElement(a, 'b')
2440 c = SubElement(b, 'c')
2441 del b # no more reference to b
2443 self.assertEqual('c', c.tag)
2445 def test_setslice(self):
2446 Element = self.etree.Element
2447 SubElement = self.etree.SubElement
2450 b = SubElement(a, 'b')
2451 c = SubElement(a, 'c')
2452 d = SubElement(a, 'd')
2464 def test_setslice_all(self):
2465 Element = self.etree.Element
2466 SubElement = self.etree.SubElement
2469 b = SubElement(a, 'b')
2470 c = SubElement(a, 'c')
2482 def test_setslice_all_empty(self):
2483 Element = self.etree.Element
2484 SubElement = self.etree.SubElement
2498 def test_setslice_all_replace(self):
2499 Element = self.etree.Element
2500 SubElement = self.etree.SubElement
2503 b = SubElement(a, 'b')
2504 c = SubElement(a, 'c')
2505 d = SubElement(a, 'd')
2513 def test_setslice_all_replace_reversed(self):
2514 Element = self.etree.Element
2515 SubElement = self.etree.SubElement
2518 b = SubElement(a, 'b')
2519 c = SubElement(a, 'c')
2520 d = SubElement(a, 'd')
2528 def test_setslice_all_replace_reversed_ns1(self):
2529 Element = self.etree.Element
2530 SubElement = self.etree.SubElement
2532 a = Element('{ns}a')
2533 b = SubElement(a, '{ns}b', {'{ns1}a1': 'test'})
2534 c = SubElement(a, '{ns}c', {'{ns2}a2': 'test'})
2535 d = SubElement(a, '{ns}d', {'{ns3}a3': 'test'})
2543 ['{ns}d', '{ns}c', '{ns}b'],
2544 [ child.tag for child in a ])
2547 [['{ns3}a3'], ['{ns2}a2'], ['{ns1}a1']],
2548 [ list(child.attrib.keys()) for child in a ])
2550 def test_setslice_all_replace_reversed_ns2(self):
2551 Element = self.etree.Element
2552 SubElement = self.etree.SubElement
2554 a = Element('{ns}a')
2555 b = SubElement(a, '{ns1}b', {'{ns}a1': 'test'})
2556 c = SubElement(a, '{ns2}c', {'{ns}a2': 'test'})
2557 d = SubElement(a, '{ns3}d', {'{ns}a3': 'test'})
2565 ['{ns3}d', '{ns2}c', '{ns1}b'],
2566 [ child.tag for child in a ])
2569 [['{ns}a3'], ['{ns}a2'], ['{ns}a1']],
2570 [ list(child.attrib.keys()) for child in a ])
2572 def test_setslice_end(self):
2573 Element = self.etree.Element
2574 SubElement = self.etree.SubElement
2577 b = SubElement(a, 'b')
2578 c = SubElement(a, 'c')
2597 def test_setslice_end_exact(self):
2598 Element = self.etree.Element
2599 SubElement = self.etree.SubElement
2602 b = SubElement(a, 'b')
2603 c = SubElement(a, 'c')
2604 d = SubElement(a, 'd')
2616 def test_setslice_single(self):
2617 Element = self.etree.Element
2618 SubElement = self.etree.SubElement
2621 b = SubElement(a, 'b')
2622 c = SubElement(a, 'c')
2639 def test_setslice_tail(self):
2640 ElementTree = self.etree.ElementTree
2641 Element = self.etree.Element
2642 f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
2643 doc = ElementTree(file=f)
2653 _bytes('<a><b></b>B2<x></x>X2<y></y>Y2<z></z>Z2<e></e>E2</a>'),
2656 def test_setslice_negative(self):
2657 Element = self.etree.Element
2658 SubElement = self.etree.SubElement
2661 b = SubElement(a, 'b')
2662 c = SubElement(a, 'c')
2663 d = SubElement(a, 'd')
2673 def test_setslice_negative2(self):
2674 Element = self.etree.Element
2675 SubElement = self.etree.SubElement
2678 b = SubElement(a, 'b')
2679 c = SubElement(a, 'c')
2680 d = SubElement(a, 'd')
2690 def test_setslice_empty(self):
2691 Element = self.etree.Element
2703 def test_tail_elementtree_root(self):
2704 Element = self.etree.Element
2705 ElementTree = self.etree.ElementTree
2709 t = ElementTree(element=a)
2710 self.assertEqual('A2',
2713 def test_elementtree_getiterator(self):
2714 Element = self.etree.Element
2715 SubElement = self.etree.SubElement
2716 ElementTree = self.etree.ElementTree
2719 b = SubElement(a, 'b')
2720 c = SubElement(a, 'c')
2721 d = SubElement(b, 'd')
2722 e = SubElement(c, 'e')
2723 t = ElementTree(element=a)
2727 list(t.getiterator()))
2729 def test_elementtree_getiterator_filter(self):
2730 Element = self.etree.Element
2731 SubElement = self.etree.SubElement
2732 ElementTree = self.etree.ElementTree
2734 b = SubElement(a, 'b')
2735 c = SubElement(a, 'c')
2736 d = SubElement(b, 'd')
2737 e = SubElement(c, 'e')
2738 t = ElementTree(element=a)
2742 list(t.getiterator('a')))
2743 a2 = SubElement(e, 'a')
2746 list(t.getiterator('a')))
2748 def test_ns_access(self):
2749 ElementTree = self.etree.ElementTree
2750 ns = 'http://xml.infrae.com/1'
2751 f = BytesIO('<x:a xmlns:x="%s"><x:b></x:b></x:a>' % ns)
2752 t = ElementTree(file=f)
2754 self.assertEqual('{%s}a' % ns,
2756 self.assertEqual('{%s}b' % ns,
2759 def test_ns_access2(self):
2760 ElementTree = self.etree.ElementTree
2761 ns = 'http://xml.infrae.com/1'
2762 ns2 = 'http://xml.infrae.com/2'
2763 f = BytesIO('<x:a xmlns:x="%s" xmlns:y="%s"><x:b></x:b><y:b></y:b></x:a>' % (ns, ns2))
2764 t = ElementTree(file=f)
2766 self.assertEqual('{%s}a' % ns,
2768 self.assertEqual('{%s}b' % ns,
2770 self.assertEqual('{%s}b' % ns2,
2773 def test_ns_setting(self):
2774 Element = self.etree.Element
2775 SubElement = self.etree.SubElement
2776 ns = 'http://xml.infrae.com/1'
2777 ns2 = 'http://xml.infrae.com/2'
2778 a = Element('{%s}a' % ns)
2779 b = SubElement(a, '{%s}b' % ns2)
2780 c = SubElement(a, '{%s}c' % ns)
2781 self.assertEqual('{%s}a' % ns,
2783 self.assertEqual('{%s}b' % ns2,
2785 self.assertEqual('{%s}c' % ns,
2787 self.assertEqual('{%s}a' % ns,
2789 self.assertEqual('{%s}b' % ns2,
2791 self.assertEqual('{%s}c' % ns,
2794 def test_ns_tag_parse(self):
2795 Element = self.etree.Element
2796 SubElement = self.etree.SubElement
2797 ElementTree = self.etree.ElementTree
2799 ns = 'http://xml.infrae.com/1'
2800 ns2 = 'http://xml.infrae.com/2'
2801 f = BytesIO('<a xmlns="%s" xmlns:x="%s"><x:b></x:b><b></b></a>' % (ns, ns2))
2802 t = ElementTree(file=f)
2805 self.assertEqual('{%s}a' % ns,
2807 self.assertEqual('{%s}b' % ns2,
2809 self.assertEqual('{%s}b' % ns,
2812 def test_ns_attr(self):
2813 Element = self.etree.Element
2814 ns = 'http://xml.infrae.com/1'
2815 ns2 = 'http://xml.infrae.com/2'
2817 a.set('{%s}foo' % ns, 'Foo')
2818 a.set('{%s}bar' % ns2, 'Bar')
2821 a.get('{%s}foo' % ns))
2824 a.get('{%s}bar' % ns2))
2827 _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns0:foo="Foo" ns1:bar="Bar"></a>' % (ns, ns2)),
2829 except AssertionError:
2831 _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns1:foo="Foo" ns0:bar="Bar"></a>' % (ns2, ns)),
2834 def test_ns_move(self):
2835 Element = self.etree.Element
2836 one = self.etree.fromstring(
2837 _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
2840 two = Element('root')
2842 # removing the originating document could cause a crash/error before
2843 # as namespace is not moved along with it
2845 self.assertEqual('{http://a.b.c}baz', two[0].tag)
2847 def test_ns_decl_tostring(self):
2848 tostring = self.etree.tostring
2849 root = self.etree.XML(
2850 _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
2853 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2855 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2857 def test_ns_decl_tostring_default(self):
2858 tostring = self.etree.tostring
2859 root = self.etree.XML(
2860 _bytes('<foo><bar xmlns="http://a.b.c"><baz/></bar></foo>'))
2863 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2865 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2867 def test_ns_decl_tostring_root(self):
2868 tostring = self.etree.tostring
2869 root = self.etree.XML(
2870 _bytes('<foo xmlns:ns="http://a.b.c"><bar><ns:baz/></bar></foo>'))
2873 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2876 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2878 def test_ns_decl_tostring_element(self):
2879 Element = self.etree.Element
2880 SubElement = self.etree.SubElement
2882 root = Element("foo")
2883 bar = SubElement(root, "{http://a.b.c}bar")
2884 baz = SubElement(bar, "{http://a.b.c}baz")
2886 nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
2887 self.etree.tostring(baz))
2889 self.assertEqual([_bytes("http://a.b.c")], nsdecl)
2891 def test_attribute_xmlns_move(self):
2892 Element = self.etree.Element
2894 root = Element('element')
2896 subelement = Element('subelement',
2897 {"{http://www.w3.org/XML/1998/namespace}id": "foo"})
2898 self.assertEqual(1, len(subelement.attrib))
2901 subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
2903 root.append(subelement)
2904 self.assertEqual(1, len(subelement.attrib))
2906 list({"{http://www.w3.org/XML/1998/namespace}id" : "foo"}.items()),
2907 list(subelement.attrib.items()))
2910 subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
2912 def test_namespaces_after_serialize(self):
2913 parse = self.etree.parse
2914 tostring = self.etree.tostring
2916 ns_href = "http://a.b.c"
2918 BytesIO('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2919 baz = one.getroot()[0][0]
2921 parsed = parse(BytesIO( tostring(baz) )).getroot()
2922 self.assertEqual('{%s}baz' % ns_href, parsed.tag)
2924 def test_attribute_namespace_roundtrip(self):
2925 fromstring = self.etree.fromstring
2926 tostring = self.etree.tostring
2928 ns_href = "http://a.b.c"
2929 xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
2931 root = fromstring(xml)
2932 self.assertEqual('test', root[0].get('{%s}a' % ns_href))
2934 xml2 = tostring(root)
2935 self.assertTrue(_bytes(':a=') in xml2, xml2)
2937 root2 = fromstring(xml2)
2938 self.assertEqual('test', root2[0].get('{%s}a' % ns_href))
2940 def test_attribute_namespace_roundtrip_replaced(self):
2941 fromstring = self.etree.fromstring
2942 tostring = self.etree.tostring
2944 ns_href = "http://a.b.c"
2945 xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
2947 root = fromstring(xml)
2948 self.assertEqual('test', root[0].get('{%s}a' % ns_href))
2950 root[0].set('{%s}a' % ns_href, 'TEST')
2952 xml2 = tostring(root)
2953 self.assertTrue(_bytes(':a=') in xml2, xml2)
2955 root2 = fromstring(xml2)
2956 self.assertEqual('TEST', root2[0].get('{%s}a' % ns_href))
2958 required_versions_ET['test_register_namespace'] = (1,3)
2959 def test_register_namespace(self):
2961 Element = self.etree.Element
2962 prefix = 'TESTPREFIX'
2963 namespace = 'http://seriously.unknown/namespace/URI'
2965 el = Element('{%s}test' % namespace)
2966 self.assertEqual(_bytes('<ns0:test xmlns:ns0="%s"></ns0:test>' % namespace),
2967 self._writeElement(el))
2969 self.etree.register_namespace(prefix, namespace)
2970 el = Element('{%s}test' % namespace)
2971 self.assertEqual(_bytes('<%s:test xmlns:%s="%s"></%s:test>' % (
2972 prefix, prefix, namespace, prefix)),
2973 self._writeElement(el))
2975 self.assertRaises(ValueError, self.etree.register_namespace, 'ns25', namespace)
2977 def test_tostring(self):
2978 tostring = self.etree.tostring
2979 Element = self.etree.Element
2980 SubElement = self.etree.SubElement
2983 b = SubElement(a, 'b')
2984 c = SubElement(a, 'c')
2986 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
2987 canonicalize(tostring(a)))
2989 def test_tostring_element(self):
2990 tostring = self.etree.tostring
2991 Element = self.etree.Element
2992 SubElement = self.etree.SubElement
2995 b = SubElement(a, 'b')
2996 c = SubElement(a, 'c')
2997 d = SubElement(c, 'd')
2998 self.assertEqual(_bytes('<b></b>'),
2999 canonicalize(tostring(b)))
3000 self.assertEqual(_bytes('<c><d></d></c>'),
3001 canonicalize(tostring(c)))
3003 def test_tostring_element_tail(self):
3004 tostring = self.etree.tostring
3005 Element = self.etree.Element
3006 SubElement = self.etree.SubElement
3009 b = SubElement(a, 'b')
3010 c = SubElement(a, 'c')
3011 d = SubElement(c, 'd')
3014 self.assertTrue(tostring(b) == _bytes('<b/>Foo') or
3015 tostring(b) == _bytes('<b />Foo'))
3017 required_versions_ET['test_tostring_method_html'] = (1,3)
3018 def test_tostring_method_html(self):
3019 tostring = self.etree.tostring
3020 Element = self.etree.Element
3021 SubElement = self.etree.SubElement
3023 html = Element('html')
3024 body = SubElement(html, 'body')
3025 p = SubElement(body, 'p')
3027 SubElement(p, 'br').tail = "test"
3029 self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
3030 tostring(html, method="html"))
3032 required_versions_ET['test_tostring_method_text'] = (1,3)
3033 def test_tostring_method_text(self):
3034 tostring = self.etree.tostring
3035 Element = self.etree.Element
3036 SubElement = self.etree.SubElement
3041 b = SubElement(a, 'b')
3044 c = SubElement(a, 'c')
3047 self.assertEqual(_bytes('ABTAILCtail'),
3048 tostring(a, method="text"))
3050 def test_iterparse(self):
3051 iterparse = self.etree.iterparse
3052 f = BytesIO('<a><b></b><c/></a>')
3054 iterator = iterparse(f)
3055 self.assertEqual(None,
3057 events = list(iterator)
3058 root = iterator.root
3060 [('end', root[0]), ('end', root[1]), ('end', root)],
3063 def test_iterparse_incomplete(self):
3064 iterparse = self.etree.iterparse
3065 f = BytesIO('<a><b></b><c/></a>')
3067 iterator = iterparse(f)
3068 self.assertEqual(None,
3070 event, element = next(iter(iterator))
3071 self.assertEqual('end', event)
3072 self.assertEqual('b', element.tag)
3074 def test_iterparse_file(self):
3075 iterparse = self.etree.iterparse
3076 iterator = iterparse(fileInTestDir("test.xml"))
3077 self.assertEqual(None,
3079 events = list(iterator)
3080 root = iterator.root
3082 [('end', root[0]), ('end', root)],
3085 def test_iterparse_start(self):
3086 iterparse = self.etree.iterparse
3087 f = BytesIO('<a><b></b><c/></a>')
3089 iterator = iterparse(f, events=('start',))
3090 events = list(iterator)
3091 root = iterator.root
3093 [('start', root), ('start', root[0]), ('start', root[1])],
3096 def test_iterparse_start_end(self):
3097 iterparse = self.etree.iterparse
3098 f = BytesIO('<a><b></b><c/></a>')
3100 iterator = iterparse(f, events=('start','end'))
3101 events = list(iterator)
3102 root = iterator.root
3104 [('start', root), ('start', root[0]), ('end', root[0]),
3105 ('start', root[1]), ('end', root[1]), ('end', root)],
3108 def test_iterparse_clear(self):
3109 iterparse = self.etree.iterparse
3110 f = BytesIO('<a><b></b><c/></a>')
3112 iterator = iterparse(f)
3113 for event, elem in iterator:
3116 root = iterator.root
3120 def test_iterparse_large(self):
3121 iterparse = self.etree.iterparse
3123 f = BytesIO('<a>%s</a>' % ('<b>test</b>'*CHILD_COUNT))
3126 for key in iterparse(f):
3127 event, element = key
3129 self.assertEqual(i, CHILD_COUNT + 1)
3131 def test_iterparse_set_ns_attribute(self):
3132 iterparse = self.etree.iterparse
3133 f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
3135 attr_name = '{http://testns/}bla'
3137 iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
3138 for event, elem in iterator:
3139 events.append(event)
3140 if event == 'start':
3141 if elem.tag != '{http://ns1/}a':
3142 elem.set(attr_name, 'value')
3145 ['start-ns', 'start', 'start', 'start-ns', 'start',
3146 'end', 'end-ns', 'end', 'end', 'end-ns'],
3149 root = iterator.root
3152 root.get(attr_name))
3155 root[0].get(attr_name))
3157 def test_iterparse_only_end_ns(self):
3158 iterparse = self.etree.iterparse
3159 f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
3161 attr_name = '{http://testns/}bla'
3163 iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
3164 for event, elem in iterator:
3165 events.append(event)
3166 if event == 'start':
3167 if elem.tag != '{http://ns1/}a':
3168 elem.set(attr_name, 'value')
3171 ['start-ns', 'start', 'start', 'start-ns', 'start',
3172 'end', 'end-ns', 'end', 'end', 'end-ns'],
3175 root = iterator.root
3178 root.get(attr_name))
3181 root[0].get(attr_name))
3183 def test_iterparse_getiterator(self):
3184 iterparse = self.etree.iterparse
3185 f = BytesIO('<a><b><d/></b><c/></a>')
3188 for event, elem in iterparse(f):
3189 counts.append(len(list(elem.getiterator())))
3194 def test_iterparse_move_elements(self):
3195 iterparse = self.etree.iterparse
3196 f = BytesIO('<a><b><d/></b><c/></a>')
3198 for event, node in etree.iterparse(f): pass
3200 root = etree.Element('new_root', {})
3205 [ el.tag for el in root ])
3207 def test_iterparse_cdata(self):
3208 tostring = self.etree.tostring
3209 f = BytesIO('<root><![CDATA[test]]></root>')
3210 context = self.etree.iterparse(f)
3211 content = [ el.text for event,el in context ]
3213 self.assertEqual(['test'], content)
3214 self.assertEqual(_bytes('<root>test</root>'),
3215 tostring(context.root))
3217 def test_parse_file(self):
3218 parse = self.etree.parse
3220 tree = parse(fileInTestDir('test.xml'))
3222 _bytes('<a><b></b></a>'),
3225 def test_parse_file_nonexistent(self):
3226 parse = self.etree.parse
3227 self.assertRaises(IOError, parse, fileInTestDir('notthere.xml'))
3229 def test_parse_error_none(self):
3230 parse = self.etree.parse
3231 self.assertRaises(TypeError, parse, None)
3233 required_versions_ET['test_parse_error'] = (1,3)
3234 def test_parse_error(self):
3235 # ET < 1.3 raises ExpatError
3236 parse = self.etree.parse
3237 f = BytesIO('<a><b></c></b></a>')
3238 self.assertRaises(SyntaxError, parse, f)
3241 required_versions_ET['test_parse_error_from_file'] = (1,3)
3242 def test_parse_error_from_file(self):
3243 parse = self.etree.parse
3245 f = open(fileInTestDir('test_broken.xml'), 'rb')
3246 self.assertRaises(SyntaxError, parse, f)
3249 def test_parse_file_object(self):
3250 parse = self.etree.parse
3252 f = open(fileInTestDir('test.xml'), 'rb')
3256 _bytes('<a><b></b></a>'),
3259 def test_parse_stringio(self):
3260 parse = self.etree.parse
3261 f = BytesIO('<a><b></b></a>')
3265 _bytes('<a><b></b></a>'),
3269 def test_parse_cdata(self):
3270 tostring = self.etree.tostring
3271 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'))
3273 self.assertEqual('test', root.text)
3274 self.assertEqual(_bytes('<root>test</root>'),
3277 def test_parse_with_encoding(self):
3278 # this can fail in libxml2 <= 2.6.22
3279 parse = self.etree.parse
3280 tree = parse(BytesIO('<?xml version="1.0" encoding="ascii"?><html/>'))
3281 self.assertXML(_bytes('<html></html>'),
3284 def test_encoding(self):
3285 Element = self.etree.Element
3288 a.text = _str('Søk på nettet')
3290 _str('<a>Søk på nettet</a>').encode('UTF-8'),
3293 def test_encoding_exact(self):
3294 ElementTree = self.etree.ElementTree
3295 Element = self.etree.Element
3298 a.text = _str('Søk på nettet')
3301 tree = ElementTree(element=a)
3302 tree.write(f, encoding='utf-8')
3303 self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
3304 f.getvalue().replace(_bytes('\n'),_bytes('')))
3306 def test_parse_file_encoding(self):
3307 parse = self.etree.parse
3309 tree = parse(fileInTestDir('test-string.xml'))
3311 _str('<a>Søk på nettet</a>').encode('UTF-8'),
3312 tree.getroot(), 'UTF-8')
3314 def test_parse_file_object_encoding(self):
3315 parse = self.etree.parse
3317 f = open(fileInTestDir('test-string.xml'), 'rb')
3321 _str('<a>Søk på nettet</a>').encode('UTF-8'),
3322 tree.getroot(), 'UTF-8')
3324 def test_encoding_8bit_latin1(self):
3325 ElementTree = self.etree.ElementTree
3326 Element = self.etree.Element
3329 a.text = _str('Søk på nettet')
3332 tree = ElementTree(element=a)
3333 tree.write(f, encoding='iso-8859-1')
3334 result = f.getvalue()
3335 declaration = _bytes("<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>")
3336 self.assertEncodingDeclaration(result, _bytes('iso-8859-1'))
3337 result = result.split(_bytes('?>'), 1)[-1].replace(_bytes('\n'),_bytes(''))
3338 self.assertEqual(_str('<a>Søk på nettet</a>').encode('iso-8859-1'),
3341 required_versions_ET['test_parse_encoding_8bit_explicit'] = (1,3)
3342 def test_parse_encoding_8bit_explicit(self):
3343 XMLParser = self.XMLParser
3345 text = _str('Søk på nettet')
3346 xml_latin1 = (_str('<a>%s</a>') % text).encode('iso-8859-1')
3348 self.assertRaises(self.etree.ParseError,
3350 BytesIO(xml_latin1))
3352 tree = self.etree.parse(BytesIO(xml_latin1),
3353 XMLParser(encoding="iso-8859-1"))
3355 self.assertEqual(a.text, text)
3357 required_versions_ET['test_parse_encoding_8bit_override'] = (1,3)
3358 def test_parse_encoding_8bit_override(self):
3359 XMLParser = self.XMLParser
3361 text = _str('Søk på nettet')
3362 wrong_declaration = _str("<?xml version='1.0' encoding='UTF-8'?>")
3363 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
3364 ).encode('iso-8859-1')
3366 self.assertRaises(self.etree.ParseError,
3368 BytesIO(xml_latin1))
3370 tree = self.etree.parse(BytesIO(xml_latin1),
3371 XMLParser(encoding="iso-8859-1"))
3373 self.assertEqual(a.text, text)
3375 def _test_wrong_unicode_encoding(self):
3376 # raise error on wrong encoding declaration in unicode strings
3377 XML = self.etree.XML
3378 test_utf = (_str('<?xml version="1.0" encoding="iso-8859-1"?>') +
3379 _str('<a>Søk på nettet</a>'))
3380 self.assertRaises(SyntaxError, XML, test_utf)
3382 def test_encoding_write_default_encoding(self):
3383 ElementTree = self.etree.ElementTree
3384 Element = self.etree.Element
3387 a.text = _str('Søk på nettet')
3390 tree = ElementTree(element=a)
3392 data = f.getvalue().replace(_bytes('\n'),_bytes(''))
3394 _str('<a>Søk på nettet</a>').encode('ASCII', 'xmlcharrefreplace'),
3397 def test_encoding_tostring(self):
3398 Element = self.etree.Element
3399 tostring = self.etree.tostring
3402 a.text = _str('Søk på nettet')
3403 self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
3404 tostring(a, encoding='utf-8'))
3406 def test_encoding_tostring_unknown(self):
3407 Element = self.etree.Element
3408 tostring = self.etree.tostring
3411 a.text = _str('Søk på nettet')
3412 self.assertRaises(LookupError, tostring, a,
3413 encoding='Invalid Encoding')
3415 def test_encoding_tostring_sub(self):
3416 Element = self.etree.Element
3417 SubElement = self.etree.SubElement
3418 tostring = self.etree.tostring
3421 b = SubElement(a, 'b')
3422 b.text = _str('Søk på nettet')
3423 self.assertEqual(_str('<b>Søk på nettet</b>').encode('UTF-8'),
3424 tostring(b, encoding='utf-8'))
3426 def test_encoding_tostring_sub_tail(self):
3427 Element = self.etree.Element
3428 SubElement = self.etree.SubElement
3429 tostring = self.etree.tostring
3432 b = SubElement(a, 'b')
3433 b.text = _str('Søk på nettet')
3434 b.tail = _str('Søk')
3435 self.assertEqual(_str('<b>Søk på nettet</b>Søk').encode('UTF-8'),
3436 tostring(b, encoding='utf-8'))
3438 def test_encoding_tostring_default_encoding(self):
3439 Element = self.etree.Element
3440 SubElement = self.etree.SubElement
3441 tostring = self.etree.tostring
3444 a.text = _str('Søk på nettet')
3446 expected = _bytes('<a>Søk på nettet</a>')
3451 def test_encoding_sub_tostring_default_encoding(self):
3452 Element = self.etree.Element
3453 SubElement = self.etree.SubElement
3454 tostring = self.etree.tostring
3457 b = SubElement(a, 'b')
3458 b.text = _str('Søk på nettet')
3460 expected = _bytes('<b>Søk på nettet</b>')
3465 def test_encoding_8bit_xml(self):
3466 utext = _str('Søk på nettet')
3467 uxml = _str('<p>%s</p>') % utext
3468 prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
3469 isoxml = prologue + uxml.encode('iso-8859-1')
3470 tree = self.etree.XML(isoxml)
3471 self.assertEqual(utext, tree.text)
3473 def test_encoding_utf8_bom(self):
3474 utext = _str('Søk på nettet')
3475 uxml = (_str('<?xml version="1.0" encoding="UTF-8"?>') +
3476 _str('<p>%s</p>') % utext)
3477 bom = _bytes('\\xEF\\xBB\\xBF').decode("unicode_escape").encode("latin1")
3478 xml = bom + uxml.encode("utf-8")
3479 tree = etree.XML(xml)
3480 self.assertEqual(utext, tree.text)
3482 def test_encoding_8bit_parse_stringio(self):
3483 utext = _str('Søk på nettet')
3484 uxml = _str('<p>%s</p>') % utext
3485 prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
3486 isoxml = prologue + uxml.encode('iso-8859-1')
3487 el = self.etree.parse(BytesIO(isoxml)).getroot()
3488 self.assertEqual(utext, el.text)
3490 def test_deepcopy_elementtree(self):
3491 Element = self.etree.Element
3492 ElementTree = self.etree.ElementTree
3496 atree = ElementTree(a)
3498 btree = copy.deepcopy(atree)
3499 self.assertEqual("Foo", atree.getroot().text)
3500 self.assertEqual("Foo", btree.getroot().text)
3501 self.assertFalse(btree is atree)
3502 self.assertFalse(btree.getroot() is atree.getroot())
3504 def test_deepcopy(self):
3505 Element = self.etree.Element
3510 b = copy.deepcopy(a)
3511 self.assertEqual('Foo', b.text)
3514 self.assertEqual('Bar', b.text)
3515 self.assertEqual('Foo', a.text)
3518 self.assertEqual('Bar', b.text)
3520 def test_deepcopy_tail(self):
3521 Element = self.etree.Element
3526 b = copy.deepcopy(a)
3527 self.assertEqual('Foo', b.tail)
3530 self.assertEqual('Bar', b.tail)
3531 self.assertEqual('Foo', a.tail)
3534 self.assertEqual('Bar', b.tail)
3536 def test_deepcopy_subelement(self):
3537 Element = self.etree.Element
3538 SubElement = self.etree.SubElement
3540 root = Element('root')
3541 a = SubElement(root, 'a')
3545 b = copy.deepcopy(a)
3546 self.assertEqual('FooText', b.text)
3547 self.assertEqual('FooTail', b.tail)
3551 self.assertEqual('BarTail', b.tail)
3552 self.assertEqual('FooTail', a.tail)
3553 self.assertEqual('BarText', b.text)
3554 self.assertEqual('FooText', a.text)
3557 self.assertEqual('BarTail', b.tail)
3558 self.assertEqual('BarText', b.text)
3560 def test_deepcopy_namespaces(self):
3561 root = self.etree.XML(_bytes('''<doc xmlns="dns" xmlns:t="tns">
3562 <parent><node t:foo="bar" /></parent>
3565 root[0][0].get('{tns}foo'),
3566 copy.deepcopy(root[0])[0].get('{tns}foo') )
3568 root[0][0].get('{tns}foo'),
3569 copy.deepcopy(root[0][0]).get('{tns}foo') )
3571 def test_deepcopy_append(self):
3572 # previously caused a crash
3573 Element = self.etree.Element
3574 tostring = self.etree.tostring
3577 b = copy.deepcopy(a)
3578 a.append( Element('C') )
3579 b.append( Element('X') )
3581 self.assertEqual(_bytes('<a><C/></a>'),
3582 tostring(a).replace(_bytes(' '), _bytes('')))
3583 self.assertEqual(_bytes('<a><X/></a>'),
3584 tostring(b).replace(_bytes(' '), _bytes('')))
3586 def test_deepcopy_comment(self):
3587 # previously caused a crash
3588 # not supported by ET < 1.3!
3589 Comment = self.etree.Comment
3592 b = copy.deepcopy(a)
3595 self.assertEqual('ONE', a.text)
3596 self.assertEqual('ANOTHER', b.text)
3598 def test_shallowcopy(self):
3599 Element = self.etree.Element
3605 self.assertEqual('Foo', b.text)
3608 self.assertEqual('Bar', b.text)
3609 self.assertEqual('Foo', a.text)
3610 # XXX ElementTree will share nodes, but lxml.etree won't..
3612 def test_shallowcopy_elementtree(self):
3613 Element = self.etree.Element
3614 ElementTree = self.etree.ElementTree
3618 atree = ElementTree(a)
3620 btree = copy.copy(atree)
3621 self.assertFalse(btree is atree)
3622 self.assertTrue(btree.getroot() is atree.getroot())
3623 self.assertEqual('Foo', atree.getroot().text)
3625 def _test_element_boolean(self):
3626 # deprecated as of ET 1.3/lxml 2.0
3628 e = etree.Element('foo')
3629 self.assertEqual(False, bool(e))
3630 etree.SubElement(e, 'bar')
3631 self.assertEqual(True, bool(e))
3632 e = etree.Element('foo')
3634 self.assertEqual(False, bool(e))
3635 e = etree.Element('foo')
3637 self.assertEqual(False, bool(e))
3638 e = etree.Element('foo')
3640 self.assertEqual(False, bool(e))
3642 def test_multiple_elementrees(self):
3645 a = etree.Element('a')
3646 b = etree.SubElement(a, 'b')
3648 t = etree.ElementTree(a)
3649 self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
3651 t1 = etree.ElementTree(a)
3652 self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
3653 self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
3655 t2 = etree.ElementTree(b)
3656 self.assertEqual(self._rootstring(t2), _bytes('<b/>'))
3657 self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
3658 self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
3660 def test_qname(self):
3662 qname = etree.QName('myns', 'a')
3663 a1 = etree.Element(qname)
3664 a2 = etree.SubElement(a1, qname)
3665 self.assertEqual(a1.tag, "{myns}a")
3666 self.assertEqual(a2.tag, "{myns}a")
3668 def test_qname_cmp(self):
3670 qname1 = etree.QName('myns', 'a')
3671 qname2 = etree.QName('myns', 'a')
3672 self.assertEqual(qname1, "{myns}a")
3673 self.assertEqual("{myns}a", qname2)
3674 self.assertEqual(qname1, qname1)
3675 self.assertEqual(qname1, qname2)
3677 def test_qname_attribute_getset(self):
3679 qname = etree.QName('myns', 'a')
3681 a = etree.Element(qname)
3682 a.set(qname, "value")
3684 self.assertEqual(a.get(qname), "value")
3685 self.assertEqual(a.get("{myns}a"), "value")
3687 def test_qname_attrib(self):
3689 qname = etree.QName('myns', 'a')
3691 a = etree.Element(qname)
3692 a.attrib[qname] = "value"
3694 self.assertEqual(a.attrib[qname], "value")
3695 self.assertEqual(a.attrib.get(qname), "value")
3697 self.assertEqual(a.attrib["{myns}a"], "value")
3698 self.assertEqual(a.attrib.get("{myns}a"), "value")
3700 def test_qname_attribute_resolve(self):
3702 qname = etree.QName('http://myns', 'a')
3703 a = etree.Element(qname)
3707 _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
3710 def test_qname_attribute_resolve_new(self):
3712 qname = etree.QName('http://myns', 'a')
3713 a = etree.Element('a')
3717 _bytes('<a xmlns:ns0="http://myns" a="ns0:a"></a>'),
3720 def test_qname_attrib_resolve(self):
3722 qname = etree.QName('http://myns', 'a')
3723 a = etree.Element(qname)
3724 a.attrib[qname] = qname
3727 _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
3730 def test_parser_version(self):
3732 parser = etree.XMLParser()
3733 if hasattr(parser, "version"):
3734 # ElementTree 1.3+, cET
3735 self.assertTrue(re.match("[^ ]+ [0-9.]+", parser.version))
3737 # feed parser interface
3739 def test_feed_parser_bytes(self):
3740 parser = self.XMLParser()
3742 parser.feed(_bytes('<?xml version='))
3743 parser.feed(_bytes('"1.0"?><ro'))
3744 parser.feed(_bytes('ot><'))
3745 parser.feed(_bytes('a test="works"/'))
3746 parser.feed(_bytes('></root'))
3747 parser.feed(_bytes('>'))
3749 root = parser.close()
3751 self.assertEqual(root.tag, "root")
3752 self.assertEqual(root[0].tag, "a")
3753 self.assertEqual(root[0].get("test"), "works")
3755 def test_feed_parser_unicode(self):
3756 parser = self.XMLParser()
3758 parser.feed(_str('<ro'))
3759 parser.feed(_str('ot><'))
3760 parser.feed(_str('a test="works"/'))
3761 parser.feed(_str('></root'))
3762 parser.feed(_str('>'))
3764 root = parser.close()
3766 self.assertEqual(root.tag, "root")
3767 self.assertEqual(root[0].tag, "a")
3768 self.assertEqual(root[0].get("test"), "works")
3770 required_versions_ET['test_feed_parser_error_close_empty'] = (1,3)
3771 def test_feed_parser_error_close_empty(self):
3772 ParseError = self.etree.ParseError
3773 parser = self.XMLParser()
3774 self.assertRaises(ParseError, parser.close)
3776 required_versions_ET['test_feed_parser_error_close_incomplete'] = (1,3)
3777 def test_feed_parser_error_close_incomplete(self):
3778 ParseError = self.etree.ParseError
3779 parser = self.XMLParser()
3781 parser.feed('<?xml version=')
3782 parser.feed('"1.0"?><ro')
3784 self.assertRaises(ParseError, parser.close)
3786 required_versions_ET['test_feed_parser_error_broken'] = (1,3)
3787 def test_feed_parser_error_broken(self):
3788 ParseError = self.etree.ParseError
3789 parser = self.XMLParser()
3791 parser.feed('<?xml version=')
3792 parser.feed('"1.0"?><ro')
3794 parser.feed('<><><><><><><')
3796 # can raise, but not required before close()
3799 self.assertRaises(ParseError, parser.close)
3801 required_versions_ET['test_feed_parser_error_position'] = (1,3)
3802 def test_feed_parser_error_position(self):
3803 ParseError = self.etree.ParseError
3804 parser = self.XMLParser()
3808 e = sys.exc_info()[1]
3809 self.assertNotEqual(None, e.code)
3810 self.assertNotEqual(0, e.code)
3811 self.assertTrue(isinstance(e.position, tuple))
3812 self.assertTrue(e.position >= (0, 0))
3814 # parser target interface
3816 required_versions_ET['test_parser_target_property'] = (1,3)
3817 def test_parser_target_property(self):
3818 class Target(object):
3822 parser = self.XMLParser(target=target)
3824 self.assertEqual(target, parser.target)
3826 def test_parser_target_tag(self):
3827 assertEqual = self.assertEqual
3828 assertFalse = self.assertFalse
3831 class Target(object):
3832 def start(self, tag, attrib):
3833 events.append("start")
3835 assertEqual("TAG", tag)
3837 events.append("end")
3838 assertEqual("TAG", tag)
3842 parser = self.XMLParser(target=Target())
3844 parser.feed("<TAG/>")
3845 done = parser.close()
3847 self.assertEqual("DONE", done)
3848 self.assertEqual(["start", "end"], events)
3850 def test_parser_target_error_in_start(self):
3851 assertEqual = self.assertEqual
3854 class Target(object):
3855 def start(self, tag, attrib):
3856 events.append("start")
3857 assertEqual("TAG", tag)
3858 raise ValueError("TEST")
3860 events.append("end")
3861 assertEqual("TAG", tag)
3865 parser = self.XMLParser(target=Target())
3868 parser.feed("<TAG/>")
3870 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3872 self.assertTrue(False)
3873 if 'lxml' in self.etree.__name__:
3874 self.assertEqual(["start"], events)
3876 # cElementTree calls end() as well
3877 self.assertTrue("start" in events)
3879 def test_parser_target_error_in_end(self):
3880 assertEqual = self.assertEqual
3883 class Target(object):
3884 def start(self, tag, attrib):
3885 events.append("start")
3886 assertEqual("TAG", tag)
3888 events.append("end")
3889 assertEqual("TAG", tag)
3890 raise ValueError("TEST")
3894 parser = self.XMLParser(target=Target())
3897 parser.feed("<TAG/>")
3899 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3901 self.assertTrue(False)
3902 self.assertEqual(["start", "end"], events)
3904 def test_parser_target_error_in_close(self):
3905 assertEqual = self.assertEqual
3908 class Target(object):
3909 def start(self, tag, attrib):
3910 events.append("start")
3911 assertEqual("TAG", tag)
3913 events.append("end")
3914 assertEqual("TAG", tag)
3916 raise ValueError("TEST")
3918 parser = self.XMLParser(target=Target())
3921 parser.feed("<TAG/>")
3924 self.assertTrue('TEST' in str(sys.exc_info()[1]))
3926 self.assertTrue(False)
3927 self.assertEqual(["start", "end"], events)
3929 def test_parser_target_error_in_start_and_close(self):
3930 assertEqual = self.assertEqual
3933 class Target(object):
3934 def start(self, tag, attrib):
3935 events.append("start")
3936 assertEqual("TAG", tag)
3937 raise IndexError("TEST-IE")
3939 events.append("end")
3940 assertEqual("TAG", tag)
3942 raise ValueError("TEST-VE")
3944 parser = self.XMLParser(target=Target())
3947 parser.feed("<TAG/>")
3950 if 'lxml' in self.etree.__name__:
3951 # we try not to swallow the initial exception in Py2
3952 self.assertTrue(sys.version_info[0] < 3)
3953 self.assertTrue('TEST-IE' in str(sys.exc_info()[1]))
3955 if 'lxml' in self.etree.__name__:
3956 self.assertTrue(sys.version_info[0] >= 3)
3957 self.assertTrue('TEST-VE' in str(sys.exc_info()[1]))
3959 self.assertTrue(False)
3961 if 'lxml' in self.etree.__name__:
3962 self.assertEqual(["start"], events)
3964 # cElementTree calls end() as well
3965 self.assertTrue("start" in events)
3967 def test_elementtree_parser_target(self):
3968 assertEqual = self.assertEqual
3969 assertFalse = self.assertFalse
3970 Element = self.etree.Element
3973 class Target(object):
3974 def start(self, tag, attrib):
3975 events.append("start")
3977 assertEqual("TAG", tag)
3979 events.append("end")
3980 assertEqual("TAG", tag)
3982 return Element("DONE")
3984 parser = self.XMLParser(target=Target())
3985 tree = self.etree.ElementTree()
3986 tree.parse(BytesIO("<TAG/>"), parser=parser)
3988 self.assertEqual("DONE", tree.getroot().tag)
3989 self.assertEqual(["start", "end"], events)
3991 def test_parser_target_attrib(self):
3992 assertEqual = self.assertEqual
3995 class Target(object):
3996 def start(self, tag, attrib):
3997 events.append("start-" + tag)
3998 for name, value in attrib.items():
3999 assertEqual(tag + name, value)
4001 events.append("end-" + tag)
4005 parser = self.XMLParser(target=Target())
4007 parser.feed('<root a="roota" b="rootb"><sub c="subc"/></root>')
4008 done = parser.close()
4010 self.assertEqual("DONE", done)
4011 self.assertEqual(["start-root", "start-sub", "end-sub", "end-root"],
4014 def test_parser_target_data(self):
4016 class Target(object):
4017 def start(self, tag, attrib):
4018 events.append("start-" + tag)
4020 events.append("end-" + tag)
4021 def data(self, data):
4022 events.append("data-" + data)
4026 parser = self.XMLParser(target=Target())
4028 parser.feed('<root>A<sub/>B</root>')
4029 done = parser.close()
4031 self.assertEqual("DONE", done)
4032 self.assertEqual(["start-root", "data-A", "start-sub",
4033 "end-sub", "data-B", "end-root"],
4036 def test_parser_target_entity(self):
4038 class Target(object):
4041 def _flush_data(self):
4043 events.append("data-" + ''.join(self._data))
4045 def start(self, tag, attrib):
4047 events.append("start-" + tag)
4050 events.append("end-" + tag)
4051 def data(self, data):
4052 self._data.append(data)
4057 parser = self.XMLParser(target=Target())
4061 <!ELEMENT root (sub*)>
4062 <!ELEMENT sub (#PCDATA)>
4063 <!ENTITY ent "an entity">
4066 parser.feed(dtd+'<root><sub/><sub>this is &ent;</sub><sub/></root>')
4067 done = parser.close()
4069 self.assertEqual("DONE", done)
4070 self.assertEqual(["start-root", "start-sub", "end-sub", "start-sub",
4071 "data-this is an entity",
4072 "end-sub", "start-sub", "end-sub", "end-root"],
4075 required_versions_ET['test_parser_target_entity_unknown'] = (1,3)
4076 def test_parser_target_entity_unknown(self):
4078 class Target(object):
4081 def _flush_data(self):
4083 events.append("data-" + ''.join(self._data))
4085 def start(self, tag, attrib):
4087 events.append("start-" + tag)
4090 events.append("end-" + tag)
4091 def data(self, data):
4092 self._data.append(data)
4097 parser = self.XMLParser(target=Target())
4100 parser.feed('<root><sub/><sub>some &ent;</sub><sub/></root>')
4103 self.assertRaises(self.etree.ParseError, feed)
4105 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4106 def test_parser_target_start_end_ns(self):
4107 class Builder(list):
4108 def start(self, tag, attrib):
4109 self.append(("start", tag))
4111 self.append(("end", tag))
4112 def data(self, text):
4114 def pi(self, target, data):
4115 self.append(("pi", target, data))
4116 def comment(self, data):
4117 self.append(("comment", data))
4118 def start_ns(self, prefix, uri):
4119 self.append(("start-ns", prefix, uri))
4120 def end_ns(self, prefix):
4121 self.append(("end-ns", prefix))
4124 parser = self.etree.XMLParser(target=builder)
4125 parser.feed(textwrap.dedent("""\
4128 <root xmlns='namespace'>
4129 <element key='value'>text</element>
4130 <element>text</element>tail
4134 self.assertEqual(builder, [
4135 ('pi', 'pi', 'data'),
4136 ('comment', ' comment '),
4137 ('start-ns', '', 'namespace'),
4138 ('start', '{namespace}root'),
4139 ('start', '{namespace}element'),
4140 ('end', '{namespace}element'),
4141 ('start', '{namespace}element'),
4142 ('end', '{namespace}element'),
4143 ('start', '{namespace}empty-element'),
4144 ('end', '{namespace}empty-element'),
4145 ('end', '{namespace}root'),
4149 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4150 def test_parser_target_end_ns(self):
4151 class Builder(list):
4152 def end_ns(self, prefix):
4153 self.append(("end-ns", prefix))
4156 parser = self.etree.XMLParser(target=builder)
4157 parser.feed(textwrap.dedent("""\
4160 <root xmlns='namespace' xmlns:p='pns'>
4161 <element key='value'>text</element>
4162 <p:element>text</p:element>tail
4166 self.assertEqual(builder, [
4171 def test_treebuilder(self):
4172 builder = self.etree.TreeBuilder()
4173 el = builder.start("root", {'a':'A', 'b':'B'})
4174 self.assertEqual("root", el.tag)
4175 self.assertEqual({'a':'A', 'b':'B'}, el.attrib)
4176 builder.data("ROOTTEXT")
4177 el = builder.start("child", {'x':'X', 'y':'Y'})
4178 self.assertEqual("child", el.tag)
4179 self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
4180 builder.data("CHILDTEXT")
4181 el = builder.end("child")
4182 self.assertEqual("child", el.tag)
4183 self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
4184 self.assertEqual("CHILDTEXT", el.text)
4185 self.assertEqual(None, el.tail)
4186 builder.data("CHILDTAIL")
4187 root = builder.end("root")
4189 self.assertEqual("root", root.tag)
4190 self.assertEqual("ROOTTEXT", root.text)
4191 self.assertEqual("CHILDTEXT", root[0].text)
4192 self.assertEqual("CHILDTAIL", root[0].tail)
4194 def test_treebuilder_target(self):
4195 parser = self.XMLParser(target=self.etree.TreeBuilder())
4196 parser.feed('<root>ROOTTEXT<child>CHILDTEXT</child>CHILDTAIL</root>')
4197 root = parser.close()
4199 self.assertEqual("root", root.tag)
4200 self.assertEqual("ROOTTEXT", root.text)
4201 self.assertEqual("CHILDTEXT", root[0].text)
4202 self.assertEqual("CHILDTAIL", root[0].tail)
4204 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4205 def test_treebuilder_comment(self):
4207 b = ET.TreeBuilder()
4208 self.assertEqual(b.comment('ctext').tag, ET.Comment)
4209 self.assertEqual(b.comment('ctext').text, 'ctext')
4211 b = ET.TreeBuilder(comment_factory=ET.Comment)
4212 self.assertEqual(b.comment('ctext').tag, ET.Comment)
4213 self.assertEqual(b.comment('ctext').text, 'ctext')
4215 #b = ET.TreeBuilder(comment_factory=len)
4216 #self.assertEqual(b.comment('ctext'), len('ctext'))
4218 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4219 def test_treebuilder_pi(self):
4221 is_lxml = ET.__name__ == 'lxml.etree'
4223 b = ET.TreeBuilder()
4224 self.assertEqual(b.pi('target', None).tag, ET.PI)
4226 self.assertEqual(b.pi('target', None).target, 'target')
4228 self.assertEqual(b.pi('target', None).text, 'target')
4230 b = ET.TreeBuilder(pi_factory=ET.PI)
4231 self.assertEqual(b.pi('target').tag, ET.PI)
4233 self.assertEqual(b.pi('target').target, "target")
4235 self.assertEqual(b.pi('target').text, "target")
4236 self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI)
4238 self.assertEqual(b.pi('pitarget', ' text ').target, "pitarget")
4239 self.assertEqual(b.pi('pitarget', ' text ').text, " text ")
4241 self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget text ")
4243 #b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text))
4244 #self.assertEqual(b.pi('target'), (len('target'), None))
4245 #self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text '))
4247 def test_late_tail(self):
4248 # Issue #37399: The tail of an ignored comment could overwrite the text before it.
4250 class TreeBuilderSubclass(ET.TreeBuilder):
4253 if ET.__name__ == 'lxml.etree':
4254 def assert_content(a):
4255 self.assertEqual(a.text, "text")
4256 self.assertEqual(a[0].tail, "tail")
4258 def assert_content(a):
4259 self.assertEqual(a.text, "texttail")
4261 xml = "<a>text<!-- comment -->tail</a>"
4262 a = ET.fromstring(xml)
4265 parser = ET.XMLParser(target=TreeBuilderSubclass())
4270 xml = "<a>text<?pi data?>tail</a>"
4271 a = ET.fromstring(xml)
4274 xml = "<a>text<?pi data?>tail</a>"
4275 parser = ET.XMLParser(target=TreeBuilderSubclass())
4280 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4281 def test_late_tail_mix_pi_comments(self):
4282 # Issue #37399: The tail of an ignored comment could overwrite the text before it.
4283 # Test appending tails to comments/pis.
4285 class TreeBuilderSubclass(ET.TreeBuilder):
4288 xml = "<a>text<?pi1?> <!-- comment -->\n<?pi2?>tail</a>"
4289 parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True, insert_pis=False))
4292 self.assertEqual(a[0].text, ' comment ')
4293 self.assertEqual(a[0].tail, '\ntail')
4294 self.assertEqual(a.text, "text ")
4296 parser = ET.XMLParser(target=TreeBuilderSubclass(insert_comments=True, insert_pis=False))
4299 self.assertEqual(a[0].text, ' comment ')
4300 self.assertEqual(a[0].tail, '\ntail')
4301 self.assertEqual(a.text, "text ")
4303 xml = "<a>text<!-- comment -->\n<?pi data?>tail</a>"
4304 parser = ET.XMLParser(target=ET.TreeBuilder(insert_pis=True, insert_comments=False))
4307 self.assertEqual(a[0].text[-4:], 'data')
4308 self.assertEqual(a[0].tail, 'tail')
4309 self.assertEqual(a.text, "text\n")
4311 parser = ET.XMLParser(target=TreeBuilderSubclass(insert_pis=True, insert_comments=False))
4314 self.assertEqual(a[0].text[-4:], 'data')
4315 self.assertEqual(a[0].tail, 'tail')
4316 self.assertEqual(a.text, "text\n")
4320 def _writeElement(self, element, encoding='us-ascii'):
4321 """Write out element for comparison.
4323 data = self.etree.tostring(element, encoding=encoding)
4324 return canonicalize(data)
4326 def _writeElementFile(self, element, encoding='us-ascii'):
4327 """Write out element for comparison, using real file.
4329 ElementTree = self.etree.ElementTree
4330 with tmpfile() as filename:
4331 with open(filename, 'wb') as f:
4332 tree = ElementTree(element=element)
4333 tree.write(f, encoding=encoding)
4334 with open(filename, 'rb') as f:
4336 return canonicalize(data)
4338 def assertXML(self, expected, element, encoding='us-ascii'):
4339 """Writes element out and checks whether it is expected.
4341 Does this two ways; once using BytesIO, once using a real file.
4343 if isinstance(expected, unicode):
4344 expected = expected.encode(encoding)
4345 self.assertEqual(expected, self._writeElement(element, encoding))
4346 self.assertEqual(expected, self._writeElementFile(element, encoding))
4348 def assertEncodingDeclaration(self, result, encoding):
4349 "Checks if the result XML byte string specifies the encoding."
4350 enc_re = r"<\?xml[^>]+ encoding=[\"']([^\"']+)[\"']"
4351 if isinstance(result, str):
4352 has_encoding = re.compile(enc_re).match
4354 has_encoding = re.compile(_bytes(enc_re)).match
4355 self.assertTrue(has_encoding(result))
4356 result_encoding = has_encoding(result).group(1)
4357 self.assertEqual(result_encoding.upper(), encoding.upper())
4359 def _rootstring(self, tree):
4360 return self.etree.tostring(tree.getroot()).replace(
4361 _bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes(''))
4363 def _check_element_tree(self, tree):
4364 self._check_element(tree.getroot())
4366 def _check_element(self, element):
4367 self.assertTrue(hasattr(element, 'tag'))
4368 self.assertTrue(hasattr(element, 'attrib'))
4369 self.assertTrue(hasattr(element, 'text'))
4370 self.assertTrue(hasattr(element, 'tail'))
4371 self._check_string(element.tag)
4372 self._check_mapping(element.attrib)
4373 if element.text is not None:
4374 self._check_string(element.text)
4375 if element.tail is not None:
4376 self._check_string(element.tail)
4378 def _check_string(self, string):
4381 self.assertEqual(1, len(char))
4382 new_string = string + ""
4383 new_string = string + " "
4386 def _check_mapping(self, mapping):
4388 keys = mapping.keys()
4389 values = mapping.values()
4390 items = mapping.items()
4393 mapping["key"] = "value"
4394 self.assertEqual("value", mapping["key"])
4397 class _ElementSlicingTest(unittest.TestCase):
4400 def _elem_tags(self, elemlist):
4401 return [e.tag for e in elemlist]
4403 def _subelem_tags(self, elem):
4404 return self._elem_tags(list(elem))
4406 def _make_elem_with_children(self, numchildren):
4407 """Create an Element with a tag 'a', with the given amount of children
4408 named 'a0', 'a1' ... and so on.
4411 e = self.etree.Element('a')
4412 for i in range(numchildren):
4413 self.etree.SubElement(e, 'a%s' % i)
4416 def test_getslice_single_index(self):
4417 e = self._make_elem_with_children(10)
4419 self.assertEqual(e[1].tag, 'a1')
4420 self.assertEqual(e[-2].tag, 'a8')
4422 self.assertRaises(IndexError, lambda: e[12])
4423 self.assertRaises(IndexError, lambda: e[-12])
4425 def test_getslice_range(self):
4426 e = self._make_elem_with_children(6)
4428 self.assertEqual(self._elem_tags(e[3:]), ['a3', 'a4', 'a5'])
4429 self.assertEqual(self._elem_tags(e[3:6]), ['a3', 'a4', 'a5'])
4430 self.assertEqual(self._elem_tags(e[3:16]), ['a3', 'a4', 'a5'])
4431 self.assertEqual(self._elem_tags(e[3:5]), ['a3', 'a4'])
4432 self.assertEqual(self._elem_tags(e[3:-1]), ['a3', 'a4'])
4433 self.assertEqual(self._elem_tags(e[:2]), ['a0', 'a1'])
4435 def test_getslice_steps(self):
4436 e = self._make_elem_with_children(10)
4438 self.assertEqual(self._elem_tags(e[8:10:1]), ['a8', 'a9'])
4439 self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
4440 self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
4441 self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
4442 self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
4443 self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
4445 def test_getslice_negative_steps(self):
4446 e = self._make_elem_with_children(4)
4448 self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
4449 self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
4450 self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
4451 self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
4452 self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
4454 def test_delslice(self):
4455 e = self._make_elem_with_children(4)
4457 self.assertEqual(self._subelem_tags(e), ['a2', 'a3'])
4459 e = self._make_elem_with_children(4)
4461 self.assertEqual(self._subelem_tags(e), [])
4463 e = self._make_elem_with_children(4)
4465 self.assertEqual(self._subelem_tags(e), [])
4467 e = self._make_elem_with_children(4)
4469 self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
4471 e = self._make_elem_with_children(4)
4473 self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
4475 e = self._make_elem_with_children(2)
4477 self.assertEqual(self._subelem_tags(e), ['a1'])
4479 def test_setslice_single_index(self):
4480 e = self._make_elem_with_children(4)
4481 e[1] = self.etree.Element('b')
4482 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4484 e[-2] = self.etree.Element('c')
4485 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
4487 with self.assertRaises(IndexError):
4488 e[5] = self.etree.Element('d')
4489 with self.assertRaises(IndexError):
4490 e[-5] = self.etree.Element('d')
4491 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
4493 def test_setslice_range(self):
4494 e = self._make_elem_with_children(4)
4495 e[1:3] = [self.etree.Element('b%s' % i) for i in range(2)]
4496 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
4498 e = self._make_elem_with_children(4)
4499 e[1:3] = [self.etree.Element('b')]
4500 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
4502 e = self._make_elem_with_children(4)
4503 e[1:3] = [self.etree.Element('b%s' % i) for i in range(3)]
4504 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
4506 def test_setslice_steps(self):
4507 e = self._make_elem_with_children(6)
4508 e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(2)]
4509 self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
4511 e = self._make_elem_with_children(6)
4512 with self.assertRaises(ValueError):
4513 e[1:5:2] = [self.etree.Element('b')]
4514 with self.assertRaises(ValueError):
4515 e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(3)]
4516 with self.assertRaises(ValueError):
4518 self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
4520 e = self._make_elem_with_children(4)
4521 e[1::sys.maxsize] = [self.etree.Element('b')]
4522 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4523 e[1::sys.maxsize<<64] = [self.etree.Element('c')]
4524 self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
4526 def test_setslice_negative_steps(self):
4527 e = self._make_elem_with_children(4)
4528 e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(2)]
4529 self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
4531 e = self._make_elem_with_children(4)
4532 with self.assertRaises(ValueError):
4533 e[2:0:-1] = [self.etree.Element('b')]
4534 with self.assertRaises(ValueError):
4535 e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(3)]
4536 with self.assertRaises(ValueError):
4538 self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
4540 e = self._make_elem_with_children(4)
4541 e[1::-sys.maxsize] = [self.etree.Element('b')]
4542 self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
4543 e[1::-sys.maxsize-1] = [self.etree.Element('c')]
4544 self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
4545 e[1::-sys.maxsize<<64] = [self.etree.Element('d')]
4546 self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
4549 class _XMLPullParserTest(unittest.TestCase):
4552 def _close_and_return_root(self, parser):
4553 if 'ElementTree' in self.etree.__name__:
4554 # ElementTree's API is a bit unwieldy in Py3.4
4555 root = parser._close_and_return_root()
4557 root = parser.close()
4560 def _feed(self, parser, data, chunk_size=None):
4561 if chunk_size is None:
4564 for i in range(0, len(data), chunk_size):
4565 parser.feed(data[i:i+chunk_size])
4567 def assert_events(self, parser, expected, max_events=None):
4569 [(event, (elem.tag, elem.text))
4570 for event, elem in islice(parser.read_events(), max_events)],
4573 def assert_event_tuples(self, parser, expected, max_events=None):
4575 list(islice(parser.read_events(), max_events)),
4578 def assert_event_tags(self, parser, expected, max_events=None):
4579 events = islice(parser.read_events(), max_events)
4580 self.assertEqual([(action, elem.tag) for action, elem in events],
4583 def test_simple_xml(self):
4584 for chunk_size in (None, 1, 5):
4585 #with self.subTest(chunk_size=chunk_size):
4586 parser = self.etree.XMLPullParser()
4587 self.assert_event_tags(parser, [])
4588 self._feed(parser, "<!-- comment -->\n", chunk_size)
4589 self.assert_event_tags(parser, [])
4591 "<root>\n <element key='value'>text</element",
4593 self.assert_event_tags(parser, [])
4594 self._feed(parser, ">\n", chunk_size)
4595 self.assert_event_tags(parser, [('end', 'element')])
4596 self._feed(parser, "<element>text</element>tail\n", chunk_size)
4597 self._feed(parser, "<empty-element/>\n", chunk_size)
4598 self.assert_event_tags(parser, [
4600 ('end', 'empty-element'),
4602 self._feed(parser, "</root>\n", chunk_size)
4603 self.assert_event_tags(parser, [('end', 'root')])
4604 root = self._close_and_return_root(parser)
4605 self.assertEqual(root.tag, 'root')
4607 def test_feed_while_iterating(self):
4608 parser = self.etree.XMLPullParser()
4609 it = parser.read_events()
4610 self._feed(parser, "<root>\n <element key='value'>text</element>\n")
4611 action, elem = next(it)
4612 self.assertEqual((action, elem.tag), ('end', 'element'))
4613 self._feed(parser, "</root>\n")
4614 action, elem = next(it)
4615 self.assertEqual((action, elem.tag), ('end', 'root'))
4616 with self.assertRaises(StopIteration):
4619 def test_simple_xml_with_ns(self):
4620 parser = self.etree.XMLPullParser()
4621 self.assert_event_tags(parser, [])
4622 self._feed(parser, "<!-- comment -->\n")
4623 self.assert_event_tags(parser, [])
4624 self._feed(parser, "<root xmlns='namespace'>\n")
4625 self.assert_event_tags(parser, [])
4626 self._feed(parser, "<element key='value'>text</element")
4627 self.assert_event_tags(parser, [])
4628 self._feed(parser, ">\n")
4629 self.assert_event_tags(parser, [('end', '{namespace}element')])
4630 self._feed(parser, "<element>text</element>tail\n")
4631 self._feed(parser, "<empty-element/>\n")
4632 self.assert_event_tags(parser, [
4633 ('end', '{namespace}element'),
4634 ('end', '{namespace}empty-element'),
4636 self._feed(parser, "</root>\n")
4637 self.assert_event_tags(parser, [('end', '{namespace}root')])
4638 root = self._close_and_return_root(parser)
4639 self.assertEqual(root.tag, '{namespace}root')
4641 def test_ns_events(self):
4642 parser = self.etree.XMLPullParser(events=('start-ns', 'end-ns'))
4643 self._feed(parser, "<!-- comment -->\n")
4644 self._feed(parser, "<root xmlns='namespace'>\n")
4646 list(parser.read_events()),
4647 [('start-ns', ('', 'namespace'))])
4648 self._feed(parser, "<element key='value'>text</element")
4649 self._feed(parser, ">\n")
4650 self._feed(parser, "<element>text</element>tail\n")
4651 self._feed(parser, "<empty-element/>\n")
4652 self._feed(parser, "</root>\n")
4653 self.assertEqual(list(parser.read_events()), [('end-ns', None)])
4656 def test_ns_events_end_ns_only(self):
4657 parser = self.etree.XMLPullParser(events=['end-ns'])
4658 self._feed(parser, "<!-- comment -->\n")
4659 self._feed(parser, "<root xmlns='namespace' xmlns:a='abc' xmlns:b='xyz'>\n")
4660 self.assertEqual(list(parser.read_events()), [])
4661 self._feed(parser, "<a:element key='value'>text</a:element")
4662 self._feed(parser, ">\n")
4663 self._feed(parser, "<b:element>text</b:element>tail\n")
4664 self._feed(parser, "<empty-element/>\n")
4665 self.assertEqual(list(parser.read_events()), [])
4666 self._feed(parser, "</root>\n")
4667 self.assertEqual(list(parser.read_events()), [
4674 @et_needs_pyversion(3,8)
4675 def test_ns_events_start(self):
4676 parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end'))
4677 self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
4678 self.assert_event_tuples(parser, [
4679 ('start-ns', ('', 'abc')),
4680 ('start-ns', ('p', 'xyz')),
4682 self.assert_event_tags(parser, [
4683 ('start', '{abc}tag'),
4686 self._feed(parser, "<child />\n")
4687 self.assert_event_tags(parser, [
4688 ('start', '{abc}child'),
4689 ('end', '{abc}child'),
4692 self._feed(parser, "</tag>\n")
4694 self.assert_event_tags(parser, [
4695 ('end', '{abc}tag'),
4698 @et_needs_pyversion(3,8)
4699 def test_ns_events_start_end(self):
4700 parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns'))
4701 self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
4702 self.assert_event_tuples(parser, [
4703 ('start-ns', ('', 'abc')),
4704 ('start-ns', ('p', 'xyz')),
4706 self.assert_event_tags(parser, [
4707 ('start', '{abc}tag'),
4710 self._feed(parser, "<child />\n")
4711 self.assert_event_tags(parser, [
4712 ('start', '{abc}child'),
4713 ('end', '{abc}child'),
4716 self._feed(parser, "</tag>\n")
4718 self.assert_event_tags(parser, [
4719 ('end', '{abc}tag'),
4721 self.assert_event_tuples(parser, [
4726 def test_events(self):
4727 parser = self.etree.XMLPullParser(events=())
4728 self._feed(parser, "<root/>\n")
4729 self.assert_event_tags(parser, [])
4731 parser = self.etree.XMLPullParser(events=('start', 'end'))
4732 self._feed(parser, "<!-- text here -->\n")
4733 self.assert_events(parser, [])
4735 parser = self.etree.XMLPullParser(events=('start', 'end'))
4736 self._feed(parser, "<root>\n")
4737 self.assert_event_tags(parser, [('start', 'root')])
4738 self._feed(parser, "<element key='value'>text</element")
4739 self.assert_event_tags(parser, [('start', 'element')])
4740 self._feed(parser, ">\n")
4741 self.assert_event_tags(parser, [('end', 'element')])
4743 "<element xmlns='foo'>text<empty-element/></element>tail\n")
4744 self.assert_event_tags(parser, [
4745 ('start', '{foo}element'),
4746 ('start', '{foo}empty-element'),
4747 ('end', '{foo}empty-element'),
4748 ('end', '{foo}element'),
4750 self._feed(parser, "</root>")
4751 root = self._close_and_return_root(parser)
4752 self.assert_event_tags(parser, [('end', 'root')])
4753 self.assertEqual(root.tag, 'root')
4755 parser = self.etree.XMLPullParser(events=('start',))
4756 self._feed(parser, "<!-- comment -->\n")
4757 self.assert_event_tags(parser, [])
4758 self._feed(parser, "<root>\n")
4759 self.assert_event_tags(parser, [('start', 'root')])
4760 self._feed(parser, "<element key='value'>text</element")
4761 self.assert_event_tags(parser, [('start', 'element')])
4762 self._feed(parser, ">\n")
4763 self.assert_event_tags(parser, [])
4765 "<element xmlns='foo'>text<empty-element/></element>tail\n")
4766 self.assert_event_tags(parser, [
4767 ('start', '{foo}element'),
4768 ('start', '{foo}empty-element'),
4770 self._feed(parser, "</root>")
4771 root = self._close_and_return_root(parser)
4772 self.assertEqual(root.tag, 'root')
4774 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4775 def test_events_comment(self):
4776 parser = self.etree.XMLPullParser(events=('start', 'comment', 'end'))
4777 self._feed(parser, "<!-- text here -->\n")
4778 self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
4779 self._feed(parser, "<!-- more text here -->\n")
4780 self.assert_events(parser, [('comment', (self.etree.Comment, ' more text here '))])
4781 self._feed(parser, "<root-tag>text")
4782 self.assert_event_tags(parser, [('start', 'root-tag')])
4783 self._feed(parser, "<!-- inner comment-->\n")
4784 self.assert_events(parser, [('comment', (self.etree.Comment, ' inner comment'))])
4785 self._feed(parser, "</root-tag>\n")
4786 self.assert_event_tags(parser, [('end', 'root-tag')])
4787 self._feed(parser, "<!-- outer comment -->\n")
4788 self.assert_events(parser, [('comment', (self.etree.Comment, ' outer comment '))])
4790 parser = self.etree.XMLPullParser(events=('comment',))
4791 self._feed(parser, "<!-- text here -->\n")
4792 self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
4794 @et_needs_pyversion(3, 8, 0, 'alpha', 4)
4795 def test_events_pi(self):
4796 # Note: lxml's PIs have target+text, ET's PIs have both in "text"
4797 parser = self.etree.XMLPullParser(events=('start', 'pi', 'end'))
4798 self._feed(parser, "<?pitarget?>\n")
4799 self.assert_event_tags(parser, [('pi', self.etree.PI)])
4800 parser = self.etree.XMLPullParser(events=('pi',))
4801 self._feed(parser, "<?pitarget some text ?>\n")
4802 self.assert_event_tags(parser, [('pi', self.etree.PI)])
4804 def test_events_sequence(self):
4805 # Test that events can be some sequence that's not just a tuple or list
4806 eventset = {'end', 'start'}
4807 parser = self.etree.XMLPullParser(events=eventset)
4808 self._feed(parser, "<foo>bar</foo>")
4809 self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
4811 class DummyIter(object):
4813 self.events = iter(['start', 'end', 'start-ns'])
4817 return next(self.events)
4819 return next(self.events)
4821 parser = self.etree.XMLPullParser(events=DummyIter())
4822 self._feed(parser, "<foo>bar</foo>")
4823 self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
4825 def test_unknown_event(self):
4826 with self.assertRaises(ValueError):
4827 self.etree.XMLPullParser(events=('start', 'end', 'bogus'))
4830 class _C14NTest(unittest.TestCase):
4834 if not hasattr(unittest.TestCase, 'subTest'):
4836 def subTest(self, name, **kwargs):
4839 except unittest.SkipTest:
4841 except Exception as e:
4842 print("Subtest {} failed: {}".format(name, e))
4845 def _canonicalize(self, input_file, **options):
4846 return self.etree.canonicalize(from_file=input_file, **options)
4849 # simple roundtrip tests (from c14n.py)
4851 def c14n_roundtrip(self, xml, **options):
4852 return self.etree.canonicalize(xml, **options)
4854 def test_simple_roundtrip(self):
4855 c14n_roundtrip = self.c14n_roundtrip
4857 self.assertEqual(c14n_roundtrip("<doc/>"), '<doc></doc>')
4858 self.assertEqual(c14n_roundtrip("<doc xmlns='uri'/>"), # FIXME
4859 '<doc xmlns="uri"></doc>')
4860 self.assertEqual(c14n_roundtrip("<prefix:doc xmlns:prefix='uri'/>"),
4861 '<prefix:doc xmlns:prefix="uri"></prefix:doc>')
4862 self.assertEqual(c14n_roundtrip("<doc xmlns:prefix='uri'><prefix:bar/></doc>"),
4863 '<doc><prefix:bar xmlns:prefix="uri"></prefix:bar></doc>')
4864 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/' />"),
4868 self.assertEqual(c14n_roundtrip("<doc>Hello, world!<!-- Comment 1 --></doc>"),
4869 '<doc>Hello, world!</doc>')
4870 self.assertEqual(c14n_roundtrip("<value>2</value>"),
4872 self.assertEqual(c14n_roundtrip('<compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>'),
4873 '<compute>value>"0" && value<"10" ?"valid":"error"</compute>')
4874 self.assertEqual(c14n_roundtrip('''<compute expr='value>"0" && value<"10" ?"valid":"error"'>valid</compute>'''),
4875 '<compute expr="value>"0" && value<"10" ?"valid":"error"">valid</compute>')
4876 self.assertEqual(c14n_roundtrip("<norm attr=' '   
	 ' '/>"),
4877 '<norm attr=" \' 
	 \' "></norm>')
4878 self.assertEqual(c14n_roundtrip("<normNames attr=' A   
	 B '/>"),
4879 '<normNames attr=" A 
	 B "></normNames>')
4880 self.assertEqual(c14n_roundtrip("<normId id=' '   
	 ' '/>"),
4881 '<normId id=" \' 
	 \' "></normId>')
4883 # fragments from PJ's tests
4884 #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>"),
4885 #'<doc xmlns:x="http://example.com/x"><b xmlns:y="http://example.com/y" a3="3" y:a1="1" y:a2="2"></b></doc>')
4887 def test_c14n_exclusion(self):
4888 c14n_roundtrip = self.c14n_roundtrip
4889 xml = textwrap.dedent("""\
4890 <root xmlns:x="http://example.com/x">
4901 c14n_roundtrip(xml, strip_text=True),
4903 '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
4905 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4908 c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']),
4910 '<a><b>abtext</b></a>'
4912 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4915 c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']),
4917 '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
4922 c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'],
4923 exclude_tags=['{http://example.com/x}d']),
4925 '<a><b>abtext</b></a>'
4930 c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']),
4932 '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
4935 c14n_roundtrip(xml, exclude_tags=['a', 'b']),
4940 ' <x:d xmlns:x="http://example.com/x">dtext</x:d>\n'
4944 c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']),
4946 '<a xmlns:x="http://example.com/x" x:attr="attrx"></a>'
4950 c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']),
4952 ' <a xmlns:x="http://example.com/x" x:attr="attrx">\n'
4962 # basic method=c14n tests from the c14n 2.0 specification. uses
4963 # test files under xmltestdata/c14n-20.
4965 # note that this uses generated C14N versions of the standard ET.write
4966 # output, not roundtripped C14N (see above).
4968 def test_xml_c14n2(self):
4969 datadir = os.path.join(os.path.dirname(__file__), "c14n-20")
4970 full_path = partial(os.path.join, datadir)
4972 files = [filename[:-4] for filename in sorted(os.listdir(datadir))
4973 if filename.endswith('.xml')]
4975 filename for filename in files
4976 if filename.startswith('in')
4980 # <c14n2:PrefixRewrite>sequential</c14n2:PrefixRewrite>
4981 option.tag.split('}')[-1]: ((option.text or '').strip(), option)
4982 for option in self.etree.parse(full_path(filename) + ".xml").getroot()
4984 for filename in files
4985 if filename.startswith('c14n')
4990 (filename, configs[filename.rsplit('_', 1)[-1]])
4991 for filename in files
4992 if filename.startswith('out_%s_' % input_file)
4993 and filename.rsplit('_', 1)[-1] in configs
4995 for input_file in input_files
4998 # Make sure we found all test cases.
4999 self.assertEqual(30, len([
5000 output_file for output_files in tests.values()
5001 for output_file in output_files]))
5003 def get_option(config, option_name, default=None):
5004 return config.get(option_name, (default, ()))[0]
5006 for input_file, output_files in tests.items():
5007 for output_file, config in output_files:
5008 keep_comments = get_option(
5009 config, 'IgnoreComments') == 'true' # no, it's right :)
5010 strip_text = get_option(
5011 config, 'TrimTextNodes') == 'true'
5012 rewrite_prefixes = get_option(
5013 config, 'PrefixRewrite') == 'sequential'
5014 if 'QNameAware' in config:
5016 "{%s}%s" % (el.get('NS'), el.get('Name'))
5017 for el in config['QNameAware'][1].findall(
5018 '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr')
5021 "{%s}%s" % (el.get('NS'), el.get('Name'))
5022 for el in config['QNameAware'][1].findall(
5023 '{http://www.w3.org/2010/xml-c14n2}Element')
5026 qtags = qattrs = None
5028 # Build subtest description from config.
5029 config_descr = ','.join(
5030 "%s=%s" % (name, value or ','.join(c.tag.split('}')[-1] for c in children))
5031 for name, (value, children) in sorted(config.items())
5034 with self.subTest("{}({})".format(output_file, config_descr)):
5035 if input_file == 'inNsRedecl' and not rewrite_prefixes:
5037 "Redeclared namespace handling is not supported in {}".format(
5039 if input_file == 'inNsSuperfluous' and not rewrite_prefixes:
5041 "Redeclared namespace handling is not supported in {}".format(
5043 if 'QNameAware' in config and config['QNameAware'][1].find(
5044 '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None:
5046 "QName rewriting in XPath text is not supported in {}".format(
5049 f = full_path(input_file + ".xml")
5050 if input_file == 'inC14N5':
5051 # Hack: avoid setting up external entity resolution in the parser.
5052 with open(full_path('world.txt'), 'rb') as entity_file:
5053 with open(f, 'rb') as f:
5054 f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read().strip()))
5056 text = self._canonicalize(
5058 with_comments=keep_comments,
5059 strip_text=strip_text,
5060 rewrite_prefixes=rewrite_prefixes,
5061 qname_aware_tags=qtags, qname_aware_attrs=qattrs)
5063 with io.open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f:
5065 if input_file == 'inC14N3' and self.etree is not etree:
5066 # FIXME: cET resolves default attributes but ET does not!
5067 expected = expected.replace(' attr="default"', '')
5068 text = text.replace(' attr="default"', '')
5069 self.assertEqual(expected, text)
5073 class ETreeTestCase(_ETreeTestCaseBase):
5076 class ETreePullTestCase(_XMLPullParserTest):
5079 class ETreeElementSlicingTest(_ElementSlicingTest):
5082 class ETreeC14NTest(_C14NTest):
5085 class ETreeC14N2WriteTest(ETreeC14NTest):
5086 def _canonicalize(self, input_file, with_comments=True, strip_text=False,
5087 rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
5089 if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
5090 self.skipTest("C14N 2.0 feature not supported with ElementTree.write()")
5092 parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
5093 tree = self.etree.parse(input_file, parser)
5096 out, method='c14n2',
5097 with_comments=with_comments, strip_text=strip_text,
5099 return out.getvalue().decode('utf8')
5101 class ETreeC14N2TostringTest(ETreeC14NTest):
5102 def _canonicalize(self, input_file, with_comments=True, strip_text=False,
5103 rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
5105 if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
5106 self.skipTest("C14N 2.0 feature not supported with ElementTree.tostring()")
5108 parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
5109 tree = self.etree.parse(input_file, parser)
5110 return self.etree.tostring(
5111 tree, method='c14n2',
5112 with_comments=with_comments, strip_text=strip_text,
5113 **options).decode('utf8')
5117 class ElementTreeTestCase(_ETreeTestCaseBase):
5121 def setUpClass(cls):
5123 # ElementTree warns about getiterator() in recent Pythons
5124 warnings.filterwarnings(
5126 r'This method will be removed.*\.iter\(\).*instead',
5127 PendingDeprecationWarning)
5130 ElementTreeTestCase,
5131 ElementTreeTestCase.required_versions_ET, ET_VERSION)
5133 if hasattr(ElementTree, 'XMLPullParser'):
5134 class ElementTreePullTestCase(_XMLPullParserTest):
5137 ElementTreePullTestCase = None
5139 if hasattr(ElementTree, 'canonicalize'):
5140 class ElementTreeC14NTest(_C14NTest):
5143 ElementTreeC14NTest = None
5145 class ElementTreeElementSlicingTest(_ElementSlicingTest):
5150 class CElementTreeTestCase(_ETreeTestCaseBase):
5151 etree = cElementTree
5154 CElementTreeTestCase,
5155 CElementTreeTestCase.required_versions_cET, CET_VERSION)
5157 class CElementTreeElementSlicingTest(_ElementSlicingTest):
5158 etree = cElementTree
5162 suite = unittest.TestSuite()
5164 suite.addTests([unittest.makeSuite(ETreeTestCase)])
5165 suite.addTests([unittest.makeSuite(ETreePullTestCase)])
5166 suite.addTests([unittest.makeSuite(ETreeElementSlicingTest)])
5167 suite.addTests([unittest.makeSuite(ETreeC14NTest)])
5168 suite.addTests([unittest.makeSuite(ETreeC14N2WriteTest)])
5169 suite.addTests([unittest.makeSuite(ETreeC14N2TostringTest)])
5171 suite.addTests([unittest.makeSuite(ElementTreeTestCase)])
5172 if ElementTreePullTestCase:
5173 suite.addTests([unittest.makeSuite(ElementTreePullTestCase)])
5174 if ElementTreeC14NTest:
5175 suite.addTests([unittest.makeSuite(ElementTreeC14NTest)])
5176 suite.addTests([unittest.makeSuite(ElementTreeElementSlicingTest)])
5178 suite.addTests([unittest.makeSuite(CElementTreeTestCase)])
5179 suite.addTests([unittest.makeSuite(CElementTreeElementSlicingTest)])
5182 if __name__ == '__main__':
5183 print('to test use test.py %s' % __file__)