| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2
3 """
4 Tests specific to the extended etree API
5
6 Tests that apply to the general ElementTree API should go into
7 test_elementtree
8 """
9
10 from __future__ import absolute_import
11
12 import os.path
13 import unittest
14 import copy
15 import sys
16 import re
17 import gc
18 import operator
19 import tempfile
20 import textwrap
21 import zlib
22 import gzip
23 from contextlib import closing, contextmanager
24
25 from .common_imports import etree, StringIO, BytesIO, HelperTestCase
26 from .common_imports import fileInTestDir, fileUrlInTestDir, read_file, path2url
27 from .common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
28 from .common_imports import canonicalize, _str, _bytes
29
30 print("")
31 print("TESTED VERSION: %s" % etree.__version__)
32 print(" Python: " + repr(sys.version_info))
33 print(" lxml.etree: " + repr(etree.LXML_VERSION))
34 print(" libxml used: " + repr(etree.LIBXML_VERSION))
35 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION))
36 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION))
37 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
38 print("")
39
40 try:
41 _unicode = unicode
42 except NameError:
43 # Python 3
44 _unicode = str
49 handle, filename = tempfile.mkstemp()
50 try:
51 yield filename
52 finally:
53 os.close(handle)
54 os.remove(filename)
55
58 """Tests only for etree, not ElementTree"""
59 etree = etree
60
62 self.assertTrue(isinstance(etree.__version__, _unicode))
63 self.assertTrue(isinstance(etree.LXML_VERSION, tuple))
64 self.assertEqual(len(etree.LXML_VERSION), 4)
65 self.assertTrue(isinstance(etree.LXML_VERSION[0], int))
66 self.assertTrue(isinstance(etree.LXML_VERSION[1], int))
67 self.assertTrue(isinstance(etree.LXML_VERSION[2], int))
68 self.assertTrue(isinstance(etree.LXML_VERSION[3], int))
69 self.assertTrue(etree.__version__.startswith(
70 str(etree.LXML_VERSION[0])))
71
73 if hasattr(self.etree, '__pyx_capi__'):
74 # newer Pyrex compatible C-API
75 self.assertTrue(isinstance(self.etree.__pyx_capi__, dict))
76 self.assertTrue(len(self.etree.__pyx_capi__) > 0)
77 else:
78 # older C-API mechanism
79 self.assertTrue(hasattr(self.etree, '_import_c_api'))
80
82 import lxml
83 includes = lxml.get_include()
84 self.assertTrue(includes)
85 self.assertTrue(len(includes) >= 2)
86 self.assertTrue(os.path.join(os.path.dirname(lxml.__file__), 'includes') in includes,
87 includes)
88
90 Element = self.etree.Element
91 el = Element('name')
92 self.assertEqual(el.tag, 'name')
93 el = Element('{}name')
94 self.assertEqual(el.tag, 'name')
95
97 Element = self.etree.Element
98 el = Element('name')
99 self.assertRaises(ValueError, Element, '{}')
100 self.assertRaises(ValueError, setattr, el, 'tag', '{}')
101
102 self.assertRaises(ValueError, Element, '{test}')
103 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
104
106 Element = self.etree.Element
107 self.assertRaises(ValueError, Element, 'p:name')
108 self.assertRaises(ValueError, Element, '{test}p:name')
109
110 el = Element('name')
111 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
112
114 Element = self.etree.Element
115 self.assertRaises(ValueError, Element, "p'name")
116 self.assertRaises(ValueError, Element, 'p"name')
117
118 self.assertRaises(ValueError, Element, "{test}p'name")
119 self.assertRaises(ValueError, Element, '{test}p"name')
120
121 el = Element('name')
122 self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
123 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
124
126 Element = self.etree.Element
127 self.assertRaises(ValueError, Element, ' name ')
128 self.assertRaises(ValueError, Element, 'na me')
129 self.assertRaises(ValueError, Element, '{test} name')
130
131 el = Element('name')
132 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
133
135 Element = self.etree.Element
136 SubElement = self.etree.SubElement
137
138 el = Element('name')
139 self.assertRaises(ValueError, SubElement, el, '{}')
140 self.assertRaises(ValueError, SubElement, el, '{test}')
141
143 Element = self.etree.Element
144 SubElement = self.etree.SubElement
145
146 el = Element('name')
147 self.assertRaises(ValueError, SubElement, el, 'p:name')
148 self.assertRaises(ValueError, SubElement, el, '{test}p:name')
149
151 Element = self.etree.Element
152 SubElement = self.etree.SubElement
153
154 el = Element('name')
155 self.assertRaises(ValueError, SubElement, el, "p'name")
156 self.assertRaises(ValueError, SubElement, el, "{test}p'name")
157
158 self.assertRaises(ValueError, SubElement, el, 'p"name')
159 self.assertRaises(ValueError, SubElement, el, '{test}p"name')
160
162 Element = self.etree.Element
163 SubElement = self.etree.SubElement
164
165 el = Element('name')
166 self.assertRaises(ValueError, SubElement, el, ' name ')
167 self.assertRaises(ValueError, SubElement, el, 'na me')
168 self.assertRaises(ValueError, SubElement, el, '{test} name')
169
171 Element = self.etree.Element
172 SubElement = self.etree.SubElement
173
174 el = Element('name')
175 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'})
176 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'})
177 self.assertEqual(0, len(el))
178
180 QName = self.etree.QName
181 self.assertRaises(ValueError, QName, '')
182 self.assertRaises(ValueError, QName, None)
183 self.assertRaises(ValueError, QName, None, None)
184 self.assertRaises(ValueError, QName, 'test', '')
185
187 QName = self.etree.QName
188 q = QName(None, 'TAG')
189 self.assertEqual('TAG', q)
190 self.assertEqual('TAG', q.localname)
191 self.assertEqual(None, q.namespace)
192
194 QName = self.etree.QName
195 self.assertRaises(ValueError, QName, 'p:name')
196 self.assertRaises(ValueError, QName, 'test', 'p:name')
197
199 QName = self.etree.QName
200 self.assertRaises(ValueError, QName, ' name ')
201 self.assertRaises(ValueError, QName, 'na me')
202 self.assertRaises(ValueError, QName, 'test', ' name')
203
205 # ET doesn't have namespace/localname properties on QNames
206 QName = self.etree.QName
207 namespace, localname = 'http://myns', 'a'
208 qname = QName(namespace, localname)
209 self.assertEqual(namespace, qname.namespace)
210 self.assertEqual(localname, qname.localname)
211
213 # ET doesn't have namespace/localname properties on QNames
214 QName = self.etree.QName
215 qname1 = QName('http://myns', 'a')
216 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
217
218 qname2 = QName(a)
219 self.assertEqual(a.tag, qname1.text)
220 self.assertEqual(a.tag, qname1)
221 self.assertEqual(qname1.text, qname2.text)
222 self.assertEqual(qname1, qname2.text)
223 self.assertEqual(qname1.text, qname2)
224 self.assertEqual(qname1, qname2)
225
227 # ET doesn't resove QNames as text values
228 etree = self.etree
229 qname = etree.QName('http://myns', 'a')
230 a = etree.Element(qname, nsmap={'p' : 'http://myns'})
231 a.text = qname
232
233 self.assertEqual("p:a", a.text)
234
236 etree = self.etree
237 self.assertRaises(ValueError,
238 etree.Element, "root", nsmap={'"' : 'testns'})
239 self.assertRaises(ValueError,
240 etree.Element, "root", nsmap={'&' : 'testns'})
241 self.assertRaises(ValueError,
242 etree.Element, "root", nsmap={'a:b' : 'testns'})
243
245 # ET in Py 3.x has no "attrib.has_key()" method
246 XML = self.etree.XML
247
248 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
249 self.assertEqual(
250 True, root.attrib.has_key('bar'))
251 self.assertEqual(
252 False, root.attrib.has_key('baz'))
253 self.assertEqual(
254 False, root.attrib.has_key('hah'))
255 self.assertEqual(
256 True,
257 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
258
260 Element = self.etree.Element
261 root = Element("root")
262 root.set("attr", "TEST")
263 self.assertEqual("TEST", root.get("attr"))
264
266 # ElementTree accepts arbitrary attribute values
267 # lxml.etree allows only strings
268 Element = self.etree.Element
269
270 root = Element("root")
271 root.set("attr", "TEST")
272 self.assertEqual("TEST", root.get("attr"))
273 self.assertRaises(TypeError, root.set, "newattr", 5)
274
276 Element = self.etree.Element
277
278 root = Element("root")
279 root.set("attr", "TEST")
280 self.assertEqual("TEST", root.attrib["attr"])
281
282 root2 = Element("root2", root.attrib, attr2='TOAST')
283 self.assertEqual("TEST", root2.attrib["attr"])
284 self.assertEqual("TOAST", root2.attrib["attr2"])
285 self.assertEqual(None, root.attrib.get("attr2"))
286
288 Element = self.etree.Element
289
290 keys = ["attr%d" % i for i in range(10)]
291 values = ["TEST-%d" % i for i in range(10)]
292 items = list(zip(keys, values))
293
294 root = Element("root")
295 for key, value in items:
296 root.set(key, value)
297 self.assertEqual(keys, root.attrib.keys())
298 self.assertEqual(values, root.attrib.values())
299
300 root2 = Element("root2", root.attrib,
301 attr_99='TOAST-1', attr_98='TOAST-2')
302 self.assertEqual(['attr_98', 'attr_99'] + keys,
303 root2.attrib.keys())
304 self.assertEqual(['TOAST-2', 'TOAST-1'] + values,
305 root2.attrib.values())
306
307 self.assertEqual(keys, root.attrib.keys())
308 self.assertEqual(values, root.attrib.values())
309
311 # ElementTree accepts arbitrary attribute values
312 # lxml.etree allows only strings, or None for (html5) boolean attributes
313 Element = self.etree.Element
314 root = Element("root")
315 self.assertRaises(TypeError, root.set, "newattr", 5)
316 self.assertRaises(TypeError, root.set, "newattr", object)
317 self.assertRaises(TypeError, root.set, "newattr", None)
318 self.assertRaises(TypeError, root.set, "newattr")
319
321 XML = self.etree.XML
322 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>')
323
324 root = XML(xml)
325 self.etree.strip_attributes(root, 'a')
326 self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'),
327 self._writeElement(root))
328
329 root = XML(xml)
330 self.etree.strip_attributes(root, 'b', 'c')
331 self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'),
332 self._writeElement(root))
333
335 XML = self.etree.XML
336 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>')
337
338 root = XML(xml)
339 self.etree.strip_attributes(root, 'a')
340 self.assertEqual(
341 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'),
342 self._writeElement(root))
343
344 root = XML(xml)
345 self.etree.strip_attributes(root, '{http://test/ns}a', 'c')
346 self.assertEqual(
347 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'),
348 self._writeElement(root))
349
350 root = XML(xml)
351 self.etree.strip_attributes(root, '{http://test/ns}*')
352 self.assertEqual(
353 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'),
354 self._writeElement(root))
355
357 XML = self.etree.XML
358 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
359
360 root = XML(xml)
361 self.etree.strip_elements(root, 'a')
362 self.assertEqual(_bytes('<test><x></x></test>'),
363 self._writeElement(root))
364
365 root = XML(xml)
366 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
367 self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'),
368 self._writeElement(root))
369
370 root = XML(xml)
371 self.etree.strip_elements(root, 'c')
372 self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
373 self._writeElement(root))
374
376 XML = self.etree.XML
377 xml = _bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"/>C</b>BT</n:a>AT<x>X<a>A<b xmlns="urn:a"/>BT<c xmlns="urn:x"/>CT</a>AT</x>XT</test>')
378
379 root = XML(xml)
380 self.etree.strip_elements(root, 'a')
381 self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>C</b>BT</n:a>AT<x>X</x>XT</test>'),
382 self._writeElement(root))
383
384 root = XML(xml)
385 self.etree.strip_elements(root, '{urn:a}b', 'c')
386 self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>C</b>BT</n:a>AT<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
387 self._writeElement(root))
388
389 root = XML(xml)
390 self.etree.strip_elements(root, '{urn:a}*', 'c')
391 self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
392 self._writeElement(root))
393
394 root = XML(xml)
395 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
396 self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
397 self._writeElement(root))
398
417
443
470
497
516
529
531 # lxml.etree separates target and text
532 Element = self.etree.Element
533 SubElement = self.etree.SubElement
534 ProcessingInstruction = self.etree.ProcessingInstruction
535
536 a = Element('a')
537 a.append(ProcessingInstruction('foo', 'some more text'))
538 self.assertEqual(a[0].target, 'foo')
539 self.assertEqual(a[0].text, 'some more text')
540
542 XML = self.etree.XML
543 root = XML(_bytes("<test><?mypi my test ?></test>"))
544 self.assertEqual(root[0].target, "mypi")
545 self.assertEqual(root[0].text, "my test ")
546
548 XML = self.etree.XML
549 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
550 self.assertEqual(root[0].target, "mypi")
551 self.assertEqual(root[0].get('my'), "1")
552 self.assertEqual(root[0].get('test'), " abc ")
553 self.assertEqual(root[0].get('quotes'), "' '")
554 self.assertEqual(root[0].get('only'), None)
555 self.assertEqual(root[0].get('names'), None)
556 self.assertEqual(root[0].get('nope'), None)
557
559 XML = self.etree.XML
560 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
561 self.assertEqual(root[0].target, "mypi")
562 self.assertEqual(root[0].attrib['my'], "1")
563 self.assertEqual(root[0].attrib['test'], " abc ")
564 self.assertEqual(root[0].attrib['quotes'], "' '")
565 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
566 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
567 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
568
570 # previously caused a crash
571 ProcessingInstruction = self.etree.ProcessingInstruction
572
573 a = ProcessingInstruction("PI", "ONE")
574 b = copy.deepcopy(a)
575 b.text = "ANOTHER"
576
577 self.assertEqual('ONE', a.text)
578 self.assertEqual('ANOTHER', b.text)
579
581 XML = self.etree.XML
582 tostring = self.etree.tostring
583 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->"))
584 tree1 = self.etree.ElementTree(root)
585 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"),
586 tostring(tree1))
587
588 tree2 = copy.deepcopy(tree1)
589 self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"),
590 tostring(tree2))
591
592 root2 = copy.deepcopy(tree1.getroot())
593 self.assertEqual(_bytes("<test/>"),
594 tostring(root2))
595
597 XML = self.etree.XML
598 tostring = self.etree.tostring
599 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
600 root = XML(xml)
601 tree1 = self.etree.ElementTree(root)
602 self.assertEqual(xml, tostring(tree1))
603
604 tree2 = copy.deepcopy(tree1)
605 self.assertEqual(xml, tostring(tree2))
606
607 root2 = copy.deepcopy(tree1.getroot())
608 self.assertEqual(_bytes("<test/>"),
609 tostring(root2))
610
612 XML = self.etree.XML
613 tostring = self.etree.tostring
614 xml = _bytes('<!-- comment --><!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
615 root = XML(xml)
616 tree1 = self.etree.ElementTree(root)
617 self.assertEqual(xml, tostring(tree1))
618
619 tree2 = copy.deepcopy(tree1)
620 self.assertEqual(xml, tostring(tree2))
621
623 fromstring = self.etree.fromstring
624 tostring = self.etree.tostring
625 XMLParser = self.etree.XMLParser
626
627 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
628 parser = XMLParser(remove_comments=True)
629 root = fromstring(xml, parser)
630 self.assertEqual(
631 _bytes('<a><b><c/></b></a>'),
632 tostring(root))
633
635 parse = self.etree.parse
636 tostring = self.etree.tostring
637 XMLParser = self.etree.XMLParser
638
639 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
640
641 f = BytesIO(xml)
642 tree = parse(f)
643 self.assertEqual(
644 xml,
645 tostring(tree))
646
647 parser = XMLParser(remove_pis=True)
648 tree = parse(f, parser)
649 self.assertEqual(
650 _bytes('<a><b><c/></b></a>'),
651 tostring(tree))
652
654 # ET raises IOError only
655 parse = self.etree.parse
656 self.assertRaises(TypeError, parse, 'notthere.xml', object())
657
659 # ET removes comments
660 iterparse = self.etree.iterparse
661 tostring = self.etree.tostring
662
663 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
664 events = list(iterparse(f))
665 root = events[-1][1]
666 self.assertEqual(3, len(events))
667 self.assertEqual(
668 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
669 tostring(root))
670
672 # ET removes comments
673 iterparse = self.etree.iterparse
674 tostring = self.etree.tostring
675
676 def name(event, el):
677 if event == 'comment':
678 return el.text
679 else:
680 return el.tag
681
682 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
683 events = list(iterparse(f, events=('end', 'comment')))
684 root = events[-1][1]
685 self.assertEqual(6, len(events))
686 self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'],
687 [ name(*item) for item in events ])
688 self.assertEqual(
689 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
690 tostring(root))
691
693 # ET removes pis
694 iterparse = self.etree.iterparse
695 tostring = self.etree.tostring
696 ElementTree = self.etree.ElementTree
697
698 def name(event, el):
699 if event == 'pi':
700 return el.target, el.text
701 else:
702 return el.tag
703
704 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
705 events = list(iterparse(f, events=('end', 'pi')))
706 root = events[-2][1]
707 self.assertEqual(8, len(events))
708 self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
709 ('pid','d'), 'a', ('pie','e')],
710 [ name(*item) for item in events ])
711 self.assertEqual(
712 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
713 tostring(ElementTree(root)))
714
716 iterparse = self.etree.iterparse
717 tostring = self.etree.tostring
718
719 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
720 events = list(iterparse(f, remove_comments=True,
721 events=('end', 'comment')))
722 root = events[-1][1]
723 self.assertEqual(3, len(events))
724 self.assertEqual(['c', 'b', 'a'],
725 [ el.tag for (event, el) in events ])
726 self.assertEqual(
727 _bytes('<a><b><c/></b></a>'),
728 tostring(root))
729
731 iterparse = self.etree.iterparse
732 f = BytesIO('<a><b><c/></a>')
733 # ET raises ExpatError, lxml raises XMLSyntaxError
734 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
735
737 iterparse = self.etree.iterparse
738 f = BytesIO('<a><b><c/></a>')
739 it = iterparse(f, events=('start', 'end'), recover=True)
740 events = [(ev, el.tag) for ev, el in it]
741 root = it.root
742 self.assertTrue(root is not None)
743
744 self.assertEqual(1, events.count(('start', 'a')))
745 self.assertEqual(1, events.count(('end', 'a')))
746
747 self.assertEqual(1, events.count(('start', 'b')))
748 self.assertEqual(1, events.count(('end', 'b')))
749
750 self.assertEqual(1, events.count(('start', 'c')))
751 self.assertEqual(1, events.count(('end', 'c')))
752
754 iterparse = self.etree.iterparse
755 f = BytesIO('<a><b><c/></d><b><c/></a></b>')
756 it = iterparse(f, events=('start', 'end'), recover=True)
757 events = [(ev, el.tag) for ev, el in it]
758 root = it.root
759 self.assertTrue(root is not None)
760
761 self.assertEqual(1, events.count(('start', 'a')))
762 self.assertEqual(1, events.count(('end', 'a')))
763
764 self.assertEqual(2, events.count(('start', 'b')))
765 self.assertEqual(2, events.count(('end', 'b')))
766
767 self.assertEqual(2, events.count(('start', 'c')))
768 self.assertEqual(2, events.count(('end', 'c')))
769
771 iterparse = self.etree.iterparse
772 f = BytesIO("""
773 <a> \n \n <b> b test </b> \n
774
775 \n\t <c> \n </c> </a> \n """)
776 iterator = iterparse(f, remove_blank_text=True)
777 text = [ (element.text, element.tail)
778 for event, element in iterator ]
779 self.assertEqual(
780 [(" b test ", None), (" \n ", None), (None, None)],
781 text)
782
784 iterparse = self.etree.iterparse
785 f = BytesIO('<a><b><d/></b><c/></a>')
786
787 iterator = iterparse(f, tag="b", events=('start', 'end'))
788 events = list(iterator)
789 root = iterator.root
790 self.assertEqual(
791 [('start', root[0]), ('end', root[0])],
792 events)
793
795 iterparse = self.etree.iterparse
796 f = BytesIO('<a><b><d/></b><c/></a>')
797
798 iterator = iterparse(f, tag="*", events=('start', 'end'))
799 events = list(iterator)
800 self.assertEqual(
801 8,
802 len(events))
803
805 iterparse = self.etree.iterparse
806 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
807
808 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
809 events = list(iterator)
810 root = iterator.root
811 self.assertEqual(
812 [('start', root[0]), ('end', root[0])],
813 events)
814
816 iterparse = self.etree.iterparse
817 f = BytesIO('<a><b><d/></b><c/></a>')
818 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
819 events = list(iterator)
820 root = iterator.root
821 self.assertEqual(
822 [('start', root[0]), ('end', root[0])],
823 events)
824
825 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
826 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
827 events = list(iterator)
828 root = iterator.root
829 self.assertEqual([], events)
830
832 iterparse = self.etree.iterparse
833 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
834 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
835 events = list(iterator)
836 self.assertEqual(8, len(events))
837
839 iterparse = self.etree.iterparse
840 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
841 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
842 events = list(iterator)
843 self.assertEqual([], events)
844
845 f = BytesIO('<a><b><d/></b><c/></a>')
846 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
847 events = list(iterator)
848 self.assertEqual(8, len(events))
849
851 text = _str('Søk på nettet')
852 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
853 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
854 ).encode('iso-8859-1')
855
856 self.assertRaises(self.etree.ParseError,
857 list, self.etree.iterparse(BytesIO(xml_latin1)))
858
860 text = _str('Søk på nettet', encoding="UTF-8")
861 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
862 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
863 ).encode('iso-8859-1')
864
865 iterator = self.etree.iterparse(BytesIO(xml_latin1),
866 encoding="iso-8859-1")
867 self.assertEqual(1, len(list(iterator)))
868
869 a = iterator.root
870 self.assertEqual(a.text, text)
871
873 tostring = self.etree.tostring
874 f = BytesIO('<root><![CDATA[test]]></root>')
875 context = self.etree.iterparse(f, strip_cdata=False)
876 content = [ el.text for event,el in context ]
877
878 self.assertEqual(['test'], content)
879 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
880 tostring(context.root))
881
885
887 self.etree.XMLParser(encoding="ascii")
888 self.etree.XMLParser(encoding="utf-8")
889 self.etree.XMLParser(encoding="iso-8859-1")
890
892 parser = self.etree.XMLParser(recover=True)
893
894 parser.feed('<?xml version=')
895 parser.feed('"1.0"?><ro')
896 parser.feed('ot><')
897 parser.feed('a test="works"')
898 parser.feed('><othertag/></root') # <a> not closed!
899 parser.feed('>')
900
901 root = parser.close()
902
903 self.assertEqual(root.tag, "root")
904 self.assertEqual(len(root), 1)
905 self.assertEqual(root[0].tag, "a")
906 self.assertEqual(root[0].get("test"), "works")
907 self.assertEqual(len(root[0]), 1)
908 self.assertEqual(root[0][0].tag, "othertag")
909 # FIXME: would be nice to get some errors logged ...
910 #self.assertTrue(len(parser.error_log) > 0, "error log is empty")
911
913 # test that recover mode plays nicely with the no-id-dict setup
914 parser = self.etree.XMLParser(recover=True, collect_ids=False)
915
916 parser.feed('<?xml version=')
917 parser.feed('"1.0"?><ro')
918 parser.feed('ot xml:id="123"><')
919 parser.feed('a test="works" xml:id=')
920 parser.feed('"321"><othertag/></root') # <a> not closed!
921 parser.feed('>')
922
923 root = parser.close()
924
925 self.assertEqual(root.tag, "root")
926 self.assertEqual(len(root), 1)
927 self.assertEqual(root[0].tag, "a")
928 self.assertEqual(root[0].get("test"), "works")
929 self.assertEqual(root[0].attrib, {
930 'test': 'works',
931 '{http://www.w3.org/XML/1998/namespace}id': '321'})
932 self.assertEqual(len(root[0]), 1)
933 self.assertEqual(root[0][0].tag, "othertag")
934 # FIXME: would be nice to get some errors logged ...
935 #self.assertTrue(len(parser.error_log) > 0, "error log is empty")
936
938 assertEqual = self.assertEqual
939 assertFalse = self.assertFalse
940
941 events = []
942 class Target(object):
943 def start(self, tag, attrib):
944 events.append("start")
945 assertFalse(attrib)
946 assertEqual("TAG", tag)
947 def end(self, tag):
948 events.append("end")
949 assertEqual("TAG", tag)
950 def close(self):
951 return "DONE" # no Element!
952
953 parser = self.etree.XMLParser(target=Target())
954 tree = self.etree.ElementTree()
955
956 self.assertRaises(TypeError,
957 tree.parse, BytesIO("<TAG/>"), parser=parser)
958 self.assertEqual(["start", "end"], events)
959
961 # ET doesn't call .close() on errors
962 events = []
963 class Target(object):
964 def start(self, tag, attrib):
965 events.append("start-" + tag)
966 def end(self, tag):
967 events.append("end-" + tag)
968 if tag == 'a':
969 raise ValueError("dead and gone")
970 def data(self, data):
971 events.append("data-" + data)
972 def close(self):
973 events.append("close")
974 return "DONE"
975
976 parser = self.etree.XMLParser(target=Target())
977
978 try:
979 parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
980 done = parser.close()
981 self.fail("error expected, but parsing succeeded")
982 except ValueError:
983 done = 'value error received as expected'
984
985 self.assertEqual(["start-root", "data-A", "start-a",
986 "data-ca", "end-a", "close"],
987 events)
988
990 # ET doesn't call .close() on errors
991 events = []
992 class Target(object):
993 def start(self, tag, attrib):
994 events.append("start-" + tag)
995 def end(self, tag):
996 events.append("end-" + tag)
997 if tag == 'a':
998 raise ValueError("dead and gone")
999 def data(self, data):
1000 events.append("data-" + data)
1001 def close(self):
1002 events.append("close")
1003 return "DONE"
1004
1005 parser = self.etree.XMLParser(target=Target())
1006
1007 try:
1008 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
1009 parser=parser)
1010 self.fail("error expected, but parsing succeeded")
1011 except ValueError:
1012 done = 'value error received as expected'
1013
1014 self.assertEqual(["start-root", "data-A", "start-a",
1015 "data-ca", "end-a", "close"],
1016 events)
1017
1019 # test that target parsing works nicely with the no-id-hash setup
1020 events = []
1021 class Target(object):
1022 def start(self, tag, attrib):
1023 events.append("start-" + tag)
1024 def end(self, tag):
1025 events.append("end-" + tag)
1026 def data(self, data):
1027 events.append("data-" + data)
1028 def comment(self, text):
1029 events.append("comment-" + text)
1030 def close(self):
1031 return "DONE"
1032
1033 parser = self.etree.XMLParser(target=Target(), collect_ids=False)
1034
1035 parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->'))
1036 parser.feed(_bytes('<sub xml:id="321"/>B</root>'))
1037 done = parser.close()
1038
1039 self.assertEqual("DONE", done)
1040 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1041 "start-sub", "end-sub", "data-B", "end-root"],
1042 events)
1043
1045 events = []
1046 class Target(object):
1047 def start(self, tag, attrib):
1048 events.append("start-" + tag)
1049 def end(self, tag):
1050 events.append("end-" + tag)
1051 def data(self, data):
1052 events.append("data-" + data)
1053 def comment(self, text):
1054 events.append("comment-" + text)
1055 def close(self):
1056 return "DONE"
1057
1058 parser = self.etree.XMLParser(target=Target())
1059
1060 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
1061 done = parser.close()
1062
1063 self.assertEqual("DONE", done)
1064 self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
1065 "start-sub", "end-sub", "comment-c", "data-B",
1066 "end-root", "comment-d"],
1067 events)
1068
1070 events = []
1071 class Target(object):
1072 def start(self, tag, attrib):
1073 events.append("start-" + tag)
1074 def end(self, tag):
1075 events.append("end-" + tag)
1076 def data(self, data):
1077 events.append("data-" + data)
1078 def pi(self, target, data):
1079 events.append("pi-" + target + "-" + data)
1080 def close(self):
1081 return "DONE"
1082
1083 parser = self.etree.XMLParser(target=Target())
1084
1085 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
1086 done = parser.close()
1087
1088 self.assertEqual("DONE", done)
1089 self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b",
1090 "data-B", "end-root", "pi-test-c"],
1091 events)
1092
1094 events = []
1095 class Target(object):
1096 def start(self, tag, attrib):
1097 events.append("start-" + tag)
1098 def end(self, tag):
1099 events.append("end-" + tag)
1100 def data(self, data):
1101 events.append("data-" + data)
1102 def close(self):
1103 return "DONE"
1104
1105 parser = self.etree.XMLParser(target=Target(),
1106 strip_cdata=False)
1107
1108 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
1109 done = parser.close()
1110
1111 self.assertEqual("DONE", done)
1112 self.assertEqual(["start-root", "data-A", "start-a",
1113 "data-ca", "end-a", "data-B", "end-root"],
1114 events)
1115
1117 events = []
1118 class Target(object):
1119 def start(self, tag, attrib):
1120 events.append("start-" + tag)
1121 def end(self, tag):
1122 events.append("end-" + tag)
1123 def data(self, data):
1124 events.append("data-" + data)
1125 def close(self):
1126 events.append("close")
1127 return "DONE"
1128
1129 parser = self.etree.XMLParser(target=Target(),
1130 recover=True)
1131
1132 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
1133 done = parser.close()
1134
1135 self.assertEqual("DONE", done)
1136 self.assertEqual(["start-root", "data-A", "start-a",
1137 "data-ca", "end-a", "data-B",
1138 "end-root", "close"],
1139 events)
1140
1142 iterwalk = self.etree.iterwalk
1143 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1144
1145 iterator = iterwalk(root, tag="b", events=('start', 'end'))
1146 events = list(iterator)
1147 self.assertEqual(
1148 [('start', root[0]), ('end', root[0])],
1149 events)
1150
1152 iterwalk = self.etree.iterwalk
1153 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1154
1155 iterator = iterwalk(root, tag="*", events=('start', 'end'))
1156 events = list(iterator)
1157 self.assertEqual(
1158 8,
1159 len(events))
1160
1162 iterwalk = self.etree.iterwalk
1163 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1164
1165 events = list(iterwalk(root))
1166 self.assertEqual(
1167 [('end', root[0]), ('end', root[1]), ('end', root)],
1168 events)
1169
1171 iterwalk = self.etree.iterwalk
1172 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1173
1174 iterator = iterwalk(root, events=('start',))
1175 events = list(iterator)
1176 self.assertEqual(
1177 [('start', root), ('start', root[0]), ('start', root[1])],
1178 events)
1179
1181 iterwalk = self.etree.iterwalk
1182 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1183
1184 iterator = iterwalk(root, events=('start','end'))
1185 events = list(iterator)
1186 self.assertEqual(
1187 [('start', root), ('start', root[0]), ('end', root[0]),
1188 ('start', root[1]), ('end', root[1]), ('end', root)],
1189 events)
1190
1200
1210
1224
1226 iterwalk = self.etree.iterwalk
1227 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1228
1229 iterator = iterwalk(root)
1230 for event, elem in iterator:
1231 elem.clear()
1232
1233 self.assertEqual(0,
1234 len(root))
1235
1237 iterwalk = self.etree.iterwalk
1238 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
1239
1240 attr_name = '{testns}bla'
1241 events = []
1242 iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
1243 for event, elem in iterator:
1244 events.append(event)
1245 if event == 'start':
1246 if elem.tag != '{ns1}a':
1247 elem.set(attr_name, 'value')
1248
1249 self.assertEqual(
1250 ['start-ns', 'start', 'start', 'start-ns', 'start',
1251 'end', 'end-ns', 'end', 'end', 'end-ns'],
1252 events)
1253
1254 self.assertEqual(
1255 None,
1256 root.get(attr_name))
1257 self.assertEqual(
1258 'value',
1259 root[0].get(attr_name))
1260
1262 iterwalk = self.etree.iterwalk
1263 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>'))
1264
1265 iterator = iterwalk(root)
1266 tags = []
1267 for event, elem in iterator:
1268 tags.append(elem.tag)
1269 # requesting a skip after an 'end' event should never have an effect
1270 iterator.skip_subtree()
1271
1272 self.assertEqual(['c', 'b', 'e', 'd', 'a'], tags)
1273
1275 iterwalk = self.etree.iterwalk
1276 root = self.etree.XML(_bytes('<a><b><c/></b><d><e/></d></a>'))
1277
1278 iterator = iterwalk(root, events=('start', 'end'))
1279 tags = []
1280 for event, elem in iterator:
1281 tags.append((event, elem.tag))
1282 if elem.tag in ('b', 'e'):
1283 # skipping should only have an effect on 'start', not on 'end'
1284 iterator.skip_subtree()
1285
1286 self.assertEqual(
1287 [('start', 'a'),
1288 ('start', 'b'), ('end', 'b'), # ignored child 'c'
1289 ('start', 'd'),
1290 ('start', 'e'), ('end', 'e'),
1291 ('end', 'd'),
1292 ('end', 'a')],
1293 tags)
1294
1296 iterwalk = self.etree.iterwalk
1297 root = self.etree.XML(_bytes(
1298 '<a xmlns="ns1"><b xmlns="nsb"><c xmlns="ns2"/></b><d xmlns="ns2"><e/></d></a>'))
1299
1300 events = []
1301 iterator = iterwalk(root, events=('start','start-ns','end-ns'))
1302 for event, elem in iterator:
1303 if event in ('start-ns', 'end-ns'):
1304 events.append((event, elem))
1305 if event == 'start-ns' and elem == ('', 'nsb'):
1306 events.append('skip')
1307 iterator.skip_subtree()
1308 else:
1309 events.append((event, elem.tag))
1310
1311 self.assertEqual(
1312 [('start-ns', ('', 'ns1')),
1313 ('start', '{ns1}a'),
1314 ('start-ns', ('', 'nsb')),
1315 'skip',
1316 ('start', '{nsb}b'),
1317 ('end-ns', None),
1318 ('start-ns', ('', 'ns2')),
1319 ('start', '{ns2}d'),
1320 ('start', '{ns2}e'),
1321 ('end-ns', None),
1322 ('end-ns', None)
1323 ],
1324 events)
1325
1327 iterwalk = self.etree.iterwalk
1328 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1329
1330 counts = []
1331 for event, elem in iterwalk(root):
1332 counts.append(len(list(elem.getiterator())))
1333 self.assertEqual(
1334 [1,2,1,4],
1335 counts)
1336
1338 parse = self.etree.parse
1339 parser = self.etree.XMLParser(dtd_validation=True)
1340 assertEqual = self.assertEqual
1341 test_url = _str("__nosuch.dtd")
1342
1343 class MyResolver(self.etree.Resolver):
1344 def resolve(self, url, id, context):
1345 assertEqual(url, test_url)
1346 return self.resolve_string(
1347 _str('''<!ENTITY myentity "%s">
1348 <!ELEMENT doc ANY>''') % url, context)
1349
1350 parser.resolvers.add(MyResolver())
1351
1352 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1353 tree = parse(StringIO(xml), parser)
1354 root = tree.getroot()
1355 self.assertEqual(root.text, test_url)
1356
1358 parse = self.etree.parse
1359 parser = self.etree.XMLParser(dtd_validation=True)
1360 assertEqual = self.assertEqual
1361 test_url = _str("__nosuch.dtd")
1362
1363 class MyResolver(self.etree.Resolver):
1364 def resolve(self, url, id, context):
1365 assertEqual(url, test_url)
1366 return self.resolve_string(
1367 (_str('''<!ENTITY myentity "%s">
1368 <!ELEMENT doc ANY>''') % url).encode('utf-8'),
1369 context)
1370
1371 parser.resolvers.add(MyResolver())
1372
1373 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1374 tree = parse(StringIO(xml), parser)
1375 root = tree.getroot()
1376 self.assertEqual(root.text, test_url)
1377
1379 parse = self.etree.parse
1380 parser = self.etree.XMLParser(dtd_validation=True)
1381 assertEqual = self.assertEqual
1382 test_url = _str("__nosuch.dtd")
1383
1384 class MyResolver(self.etree.Resolver):
1385 def resolve(self, url, id, context):
1386 assertEqual(url, test_url)
1387 return self.resolve_file(
1388 SillyFileLike(
1389 _str('''<!ENTITY myentity "%s">
1390 <!ELEMENT doc ANY>''') % url), context)
1391
1392 parser.resolvers.add(MyResolver())
1393
1394 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1395 tree = parse(StringIO(xml), parser)
1396 root = tree.getroot()
1397 self.assertEqual(root.text, test_url)
1398
1400 parse = self.etree.parse
1401 parser = self.etree.XMLParser(attribute_defaults=True)
1402 assertEqual = self.assertEqual
1403 test_url = _str("__nosuch.dtd")
1404
1405 class MyResolver(self.etree.Resolver):
1406 def resolve(self, url, id, context):
1407 assertEqual(url, test_url)
1408 return self.resolve_filename(
1409 fileInTestDir('test.dtd'), context)
1410
1411 parser.resolvers.add(MyResolver())
1412
1413 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1414 tree = parse(StringIO(xml), parser)
1415 root = tree.getroot()
1416 self.assertEqual(
1417 root.attrib, {'default': 'valueA'})
1418 self.assertEqual(
1419 root[0].attrib, {'default': 'valueB'})
1420
1422 parse = self.etree.parse
1423 parser = self.etree.XMLParser(attribute_defaults=True)
1424 assertEqual = self.assertEqual
1425 test_url = _str("__nosuch.dtd")
1426
1427 class MyResolver(self.etree.Resolver):
1428 def resolve(self, url, id, context):
1429 expected = fileUrlInTestDir(test_url)
1430 url = url.replace('file://', 'file:') # depends on libxml2 version
1431 expected = expected.replace('file://', 'file:')
1432 assertEqual(url, expected)
1433 return self.resolve_filename(
1434 fileUrlInTestDir('test.dtd'), context)
1435
1436 parser.resolvers.add(MyResolver())
1437
1438 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1439 tree = parse(StringIO(xml), parser,
1440 base_url=fileUrlInTestDir('__test.xml'))
1441 root = tree.getroot()
1442 self.assertEqual(
1443 root.attrib, {'default': 'valueA'})
1444 self.assertEqual(
1445 root[0].attrib, {'default': 'valueB'})
1446
1448 parse = self.etree.parse
1449 parser = self.etree.XMLParser(attribute_defaults=True)
1450 assertEqual = self.assertEqual
1451 test_url = _str("__nosuch.dtd")
1452
1453 class MyResolver(self.etree.Resolver):
1454 def resolve(self, url, id, context):
1455 assertEqual(url, test_url)
1456 return self.resolve_file(
1457 open(fileInTestDir('test.dtd'), 'rb'), context)
1458
1459 parser.resolvers.add(MyResolver())
1460
1461 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1462 tree = parse(StringIO(xml), parser)
1463 root = tree.getroot()
1464 self.assertEqual(
1465 root.attrib, {'default': 'valueA'})
1466 self.assertEqual(
1467 root[0].attrib, {'default': 'valueB'})
1468
1470 parse = self.etree.parse
1471 parser = self.etree.XMLParser(load_dtd=True)
1472 assertEqual = self.assertEqual
1473 test_url = _str("__nosuch.dtd")
1474
1475 class check(object):
1476 resolved = False
1477
1478 class MyResolver(self.etree.Resolver):
1479 def resolve(self, url, id, context):
1480 assertEqual(url, test_url)
1481 check.resolved = True
1482 return self.resolve_empty(context)
1483
1484 parser.resolvers.add(MyResolver())
1485
1486 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1487 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
1488 self.assertTrue(check.resolved)
1489
1491 parse = self.etree.parse
1492 parser = self.etree.XMLParser(dtd_validation=True)
1493
1494 class _LocalException(Exception):
1495 pass
1496
1497 class MyResolver(self.etree.Resolver):
1498 def resolve(self, url, id, context):
1499 raise _LocalException
1500
1501 parser.resolvers.add(MyResolver())
1502
1503 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
1504 self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
1505
1507 parse = self.etree.parse
1508 tostring = self.etree.tostring
1509 parser = self.etree.XMLParser(resolve_entities=False)
1510 Entity = self.etree.Entity
1511
1512 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>')
1513 tree = parse(BytesIO(xml), parser)
1514 root = tree.getroot()
1515 self.assertEqual(root[0].tag, Entity)
1516 self.assertEqual(root[0].text, "&myentity;")
1517 self.assertEqual(root[0].tail, None)
1518 self.assertEqual(root[0].name, "myentity")
1519
1520 self.assertEqual(_bytes('<doc>&myentity;</doc>'),
1521 tostring(root))
1522
1524 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]>
1525 <root>
1526 <child1/>
1527 <child2/>
1528 <child3> </child3>
1529 </root>''')
1530
1531 parser = self.etree.XMLParser(resolve_entities=False)
1532 root = etree.fromstring(xml, parser)
1533 self.assertEqual([ el.tag for el in root ],
1534 ['child1', 'child2', 'child3'])
1535
1536 root[0] = root[-1]
1537 self.assertEqual([ el.tag for el in root ],
1538 ['child3', 'child2'])
1539 self.assertEqual(root[0][0].text, ' ')
1540 self.assertEqual(root[0][0].name, 'nbsp')
1541
1543 Entity = self.etree.Entity
1544 Element = self.etree.Element
1545 tostring = self.etree.tostring
1546
1547 root = Element("root")
1548 root.append( Entity("test") )
1549
1550 self.assertEqual(root[0].tag, Entity)
1551 self.assertEqual(root[0].text, "&test;")
1552 self.assertEqual(root[0].tail, None)
1553 self.assertEqual(root[0].name, "test")
1554
1555 self.assertEqual(_bytes('<root>&test;</root>'),
1556 tostring(root))
1557
1559 Entity = self.etree.Entity
1560 self.assertEqual(Entity("test").text, '&test;')
1561 self.assertEqual(Entity("#17683").text, '䔓')
1562 self.assertEqual(Entity("#x1768").text, 'ᝨ')
1563 self.assertEqual(Entity("#x98AF").text, '颯')
1564
1566 Entity = self.etree.Entity
1567 self.assertRaises(ValueError, Entity, 'a b c')
1568 self.assertRaises(ValueError, Entity, 'a,b')
1569 self.assertRaises(ValueError, Entity, 'a\0b')
1570 self.assertRaises(ValueError, Entity, '#abc')
1571 self.assertRaises(ValueError, Entity, '#xxyz')
1572
1574 CDATA = self.etree.CDATA
1575 Element = self.etree.Element
1576 tostring = self.etree.tostring
1577
1578 root = Element("root")
1579 root.text = CDATA('test')
1580
1581 self.assertEqual('test',
1582 root.text)
1583 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
1584 tostring(root))
1585
1587 CDATA = self.etree.CDATA
1588 Element = self.etree.Element
1589 SubElement = self.etree.SubElement
1590 tostring = self.etree.tostring
1591
1592 root = Element("root")
1593 child = SubElement(root, 'child')
1594 child.tail = CDATA('test')
1595
1596 self.assertEqual('test', child.tail)
1597 self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'),
1598 tostring(root))
1599
1600 root = Element("root")
1601 root.tail = CDATA('test')
1602
1603 self.assertEqual('test', root.tail)
1604 self.assertEqual(_bytes('<root/><![CDATA[test]]>'),
1605 tostring(root))
1606
1608 CDATA = self.etree.CDATA
1609 Element = self.etree.Element
1610 root = Element("root")
1611
1612 root.text = CDATA("test")
1613 self.assertEqual('test', root.text)
1614
1615 root.text = CDATA(_str("test"))
1616 self.assertEqual('test', root.text)
1617
1618 self.assertRaises(TypeError, CDATA, 1)
1619
1621 CDATA = self.etree.CDATA
1622 Element = self.etree.Element
1623
1624 root = Element("root")
1625 cdata = CDATA('test')
1626
1627 self.assertRaises(TypeError,
1628 root.set, 'attr', cdata)
1629 self.assertRaises(TypeError,
1630 operator.setitem, root.attrib, 'attr', cdata)
1631
1633 tostring = self.etree.tostring
1634 parser = self.etree.XMLParser(strip_cdata=False)
1635 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1636
1637 self.assertEqual('test', root.text)
1638 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
1639 tostring(root))
1640
1642 tostring = self.etree.tostring
1643 parser = self.etree.XMLParser(strip_cdata=False)
1644 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1645 self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
1646 tostring(root))
1647
1648 self.assertEqual(['test'], root.xpath('//text()'))
1649
1650 # TypeError in etree, AssertionError in ElementTree;
1652 Element = self.etree.Element
1653 SubElement = self.etree.SubElement
1654
1655 a = Element('a')
1656 b = SubElement(a, 'b')
1657
1658 self.assertRaises(TypeError,
1659 a.__setitem__, 0, 'foo')
1660
1662 Element = self.etree.Element
1663 root = Element('root')
1664 # raises AssertionError in ElementTree
1665 self.assertRaises(TypeError, root.append, None)
1666 self.assertRaises(TypeError, root.extend, [None])
1667 self.assertRaises(TypeError, root.extend, [Element('one'), None])
1668 self.assertEqual('one', root[0].tag)
1669
1671 Element = self.etree.Element
1672 SubElement = self.etree.SubElement
1673 root = Element('root')
1674 self.assertRaises(ValueError, root.append, root)
1675 child = SubElement(root, 'child')
1676 self.assertRaises(ValueError, child.append, root)
1677 child2 = SubElement(child, 'child2')
1678 self.assertRaises(ValueError, child2.append, root)
1679 self.assertRaises(ValueError, child2.append, child)
1680 self.assertEqual('child2', root[0][0].tag)
1681
1683 Element = self.etree.Element
1684 SubElement = self.etree.SubElement
1685 root = Element('root')
1686 SubElement(root, 'a')
1687 SubElement(root, 'b')
1688
1689 self.assertEqual(['a', 'b'],
1690 [c.tag for c in root])
1691 root[1].addnext(root[0])
1692 self.assertEqual(['b', 'a'],
1693 [c.tag for c in root])
1694
1696 Element = self.etree.Element
1697 SubElement = self.etree.SubElement
1698 root = Element('root')
1699 SubElement(root, 'a')
1700 SubElement(root, 'b')
1701
1702 self.assertEqual(['a', 'b'],
1703 [c.tag for c in root])
1704 root[0].addprevious(root[1])
1705 self.assertEqual(['b', 'a'],
1706 [c.tag for c in root])
1707
1709 Element = self.etree.Element
1710 SubElement = self.etree.SubElement
1711 root = Element('root')
1712 a = SubElement(root, 'a')
1713 b = SubElement(a, 'b')
1714 # appending parent as sibling is forbidden
1715 self.assertRaises(ValueError, b.addnext, a)
1716 self.assertEqual(['a'], [c.tag for c in root])
1717 self.assertEqual(['b'], [c.tag for c in a])
1718
1720 Element = self.etree.Element
1721 SubElement = self.etree.SubElement
1722 root = Element('root')
1723 a = SubElement(root, 'a')
1724 b = SubElement(a, 'b')
1725 # appending parent as sibling is forbidden
1726 self.assertRaises(ValueError, b.addprevious, a)
1727 self.assertEqual(['a'], [c.tag for c in root])
1728 self.assertEqual(['b'], [c.tag for c in a])
1729
1731 Element = self.etree.Element
1732 SubElement = self.etree.SubElement
1733 root = Element('root')
1734 a = SubElement(root, 'a')
1735 b = SubElement(a, 'b')
1736 c = SubElement(b, 'c')
1737 # appending parent as sibling is forbidden
1738 self.assertRaises(ValueError, c.addnext, a)
1739
1741 Element = self.etree.Element
1742 SubElement = self.etree.SubElement
1743 root = Element('root')
1744 a = SubElement(root, 'a')
1745 b = SubElement(a, 'b')
1746 c = SubElement(b, 'c')
1747 # appending parent as sibling is forbidden
1748 self.assertRaises(ValueError, c.addprevious, a)
1749
1751 Element = self.etree.Element
1752 SubElement = self.etree.SubElement
1753 root = Element('root')
1754 a = SubElement(root, 'a')
1755 b = SubElement(root, 'b')
1756 a.addprevious(a)
1757 self.assertEqual('a', root[0].tag)
1758 self.assertEqual('b', root[1].tag)
1759 b.addprevious(b)
1760 self.assertEqual('a', root[0].tag)
1761 self.assertEqual('b', root[1].tag)
1762 b.addprevious(a)
1763 self.assertEqual('a', root[0].tag)
1764 self.assertEqual('b', root[1].tag)
1765
1767 Element = self.etree.Element
1768 SubElement = self.etree.SubElement
1769 root = Element('root')
1770 a = SubElement(root, 'a')
1771 b = SubElement(root, 'b')
1772 a.addnext(a)
1773 self.assertEqual('a', root[0].tag)
1774 self.assertEqual('b', root[1].tag)
1775 b.addnext(b)
1776 self.assertEqual('a', root[0].tag)
1777 self.assertEqual('b', root[1].tag)
1778 a.addnext(b)
1779 self.assertEqual('a', root[0].tag)
1780 self.assertEqual('b', root[1].tag)
1781
1783 Element = self.etree.Element
1784 a = Element('a')
1785 b = Element('b')
1786 self.assertRaises(TypeError, a.addnext, b)
1787
1789 Element = self.etree.Element
1790 SubElement = self.etree.SubElement
1791 PI = self.etree.PI
1792 root = Element('root')
1793 SubElement(root, 'a')
1794 pi = PI('TARGET', 'TEXT')
1795 pi.tail = "TAIL"
1796
1797 self.assertEqual(_bytes('<root><a></a></root>'),
1798 self._writeElement(root))
1799 root[0].addprevious(pi)
1800 self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
1801 self._writeElement(root))
1802
1804 Element = self.etree.Element
1805 PI = self.etree.PI
1806 root = Element('root')
1807 pi = PI('TARGET', 'TEXT')
1808 pi.tail = "TAIL"
1809
1810 self.assertEqual(_bytes('<root></root>'),
1811 self._writeElement(root))
1812 root.addprevious(pi)
1813 self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'),
1814 self._writeElement(root))
1815
1817 Element = self.etree.Element
1818 SubElement = self.etree.SubElement
1819 PI = self.etree.PI
1820 root = Element('root')
1821 SubElement(root, 'a')
1822 pi = PI('TARGET', 'TEXT')
1823 pi.tail = "TAIL"
1824
1825 self.assertEqual(_bytes('<root><a></a></root>'),
1826 self._writeElement(root))
1827 root[0].addnext(pi)
1828 self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
1829 self._writeElement(root))
1830
1832 Element = self.etree.Element
1833 PI = self.etree.PI
1834 root = Element('root')
1835 pi = PI('TARGET', 'TEXT')
1836 pi.tail = "TAIL"
1837
1838 self.assertEqual(_bytes('<root></root>'),
1839 self._writeElement(root))
1840 root.addnext(pi)
1841 self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'),
1842 self._writeElement(root))
1843
1845 Element = self.etree.Element
1846 SubElement = self.etree.SubElement
1847 Comment = self.etree.Comment
1848 root = Element('root')
1849 SubElement(root, 'a')
1850 comment = Comment('TEXT ')
1851 comment.tail = "TAIL"
1852
1853 self.assertEqual(_bytes('<root><a></a></root>'),
1854 self._writeElement(root))
1855 root[0].addnext(comment)
1856 self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
1857 self._writeElement(root))
1858
1860 Element = self.etree.Element
1861 Comment = self.etree.Comment
1862 root = Element('root')
1863 comment = Comment('TEXT ')
1864 comment.tail = "TAIL"
1865
1866 self.assertEqual(_bytes('<root></root>'),
1867 self._writeElement(root))
1868 root.addnext(comment)
1869 self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'),
1870 self._writeElement(root))
1871
1873 Element = self.etree.Element
1874 SubElement = self.etree.SubElement
1875 Comment = self.etree.Comment
1876 root = Element('root')
1877 SubElement(root, 'a')
1878 comment = Comment('TEXT ')
1879 comment.tail = "TAIL"
1880
1881 self.assertEqual(_bytes('<root><a></a></root>'),
1882 self._writeElement(root))
1883 root[0].addprevious(comment)
1884 self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
1885 self._writeElement(root))
1886
1888 Element = self.etree.Element
1889 Comment = self.etree.Comment
1890 root = Element('root')
1891 comment = Comment('TEXT ')
1892 comment.tail = "TAIL"
1893
1894 self.assertEqual(_bytes('<root></root>'),
1895 self._writeElement(root))
1896 root.addprevious(comment)
1897 self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'),
1898 self._writeElement(root))
1899
1900 # ET's Elements have items() and key(), but not values()
1902 XML = self.etree.XML
1903
1904 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
1905 values = root.values()
1906 values.sort()
1907 self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
1908
1909 # gives error in ElementTree
1911 Element = self.etree.Element
1912 Comment = self.etree.Comment
1913
1914 a = Element('a')
1915 a.append(Comment())
1916 self.assertEqual(
1917 _bytes('<a><!----></a>'),
1918 self._writeElement(a))
1919
1920 # ElementTree ignores comments
1922 ElementTree = self.etree.ElementTree
1923 tostring = self.etree.tostring
1924
1925 xml = _bytes('<a><b/><!----><c/></a>')
1926 f = BytesIO(xml)
1927 doc = ElementTree(file=f)
1928 a = doc.getroot()
1929 self.assertEqual(
1930 '',
1931 a[1].text)
1932 self.assertEqual(
1933 xml,
1934 tostring(a))
1935
1936 # ElementTree ignores comments
1938 ElementTree = self.etree.ElementTree
1939
1940 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
1941 doc = ElementTree(file=f)
1942 a = doc.getroot()
1943 self.assertEqual(
1944 ' hoi ',
1945 a[1].text)
1946
1947 # does not raise an exception in ElementTree
1949 Element = self.etree.Element
1950 Comment = self.etree.Comment
1951
1952 c = Comment()
1953 el = Element('myel')
1954
1955 self.assertRaises(TypeError, c.append, el)
1956 self.assertRaises(TypeError, c.insert, 0, el)
1957 self.assertRaises(TypeError, c.set, "myattr", "test")
1958
1960 c = self.etree.Comment()
1961 self.assertEqual(0, len(c.attrib))
1962
1963 self.assertFalse(c.attrib.__contains__('nope'))
1964 self.assertFalse('nope' in c.attrib)
1965 self.assertFalse('nope' in c.attrib.keys())
1966 self.assertFalse('nope' in c.attrib.values())
1967 self.assertFalse(('nope', 'huhu') in c.attrib.items())
1968
1969 self.assertEqual([], list(c.attrib))
1970 self.assertEqual([], list(c.attrib.keys()))
1971 self.assertEqual([], list(c.attrib.items()))
1972 self.assertEqual([], list(c.attrib.values()))
1973 self.assertEqual([], list(c.attrib.iterkeys()))
1974 self.assertEqual([], list(c.attrib.iteritems()))
1975 self.assertEqual([], list(c.attrib.itervalues()))
1976
1977 self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU'))
1978 self.assertRaises(KeyError, c.attrib.pop, 'nope')
1979
1980 self.assertRaises(KeyError, c.attrib.__getitem__, 'only')
1981 self.assertRaises(KeyError, c.attrib.__getitem__, 'names')
1982 self.assertRaises(KeyError, c.attrib.__getitem__, 'nope')
1983 self.assertRaises(KeyError, c.attrib.__setitem__, 'nope', 'yep')
1984 self.assertRaises(KeyError, c.attrib.__delitem__, 'nope')
1985
1986 # test passing 'None' to dump()
1989
1991 ElementTree = self.etree.ElementTree
1992
1993 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
1994 doc = ElementTree(file=f)
1995 a = doc.getroot()
1996 self.assertEqual(
1997 None,
1998 a.prefix)
1999 self.assertEqual(
2000 'foo',
2001 a[0].prefix)
2002
2004 ElementTree = self.etree.ElementTree
2005
2006 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
2007 doc = ElementTree(file=f)
2008 a = doc.getroot()
2009 self.assertEqual(
2010 None,
2011 a.prefix)
2012 self.assertEqual(
2013 None,
2014 a[0].prefix)
2015
2017 Element = self.etree.Element
2018 SubElement = self.etree.SubElement
2019
2020 a = Element('a')
2021 b = SubElement(a, 'b')
2022 c = SubElement(a, 'c')
2023 d = SubElement(b, 'd')
2024 self.assertEqual(
2025 None,
2026 a.getparent())
2027 self.assertEqual(
2028 a,
2029 b.getparent())
2030 self.assertEqual(
2031 b.getparent(),
2032 c.getparent())
2033 self.assertEqual(
2034 b,
2035 d.getparent())
2036
2038 XML = self.etree.XML
2039
2040 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
2041 result = []
2042 for el in root.iterchildren():
2043 result.append(el.tag)
2044 self.assertEqual(['one', 'two', 'three'], result)
2045
2047 XML = self.etree.XML
2048
2049 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
2050 result = []
2051 for el in root.iterchildren(reversed=True):
2052 result.append(el.tag)
2053 self.assertEqual(['three', 'two', 'one'], result)
2054
2056 XML = self.etree.XML
2057
2058 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
2059 result = []
2060 for el in root.iterchildren(tag='two'):
2061 result.append(el.text)
2062 self.assertEqual(['Two', 'Bla'], result)
2063
2065 XML = self.etree.XML
2066
2067 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
2068 result = []
2069 for el in root.iterchildren('two'):
2070 result.append(el.text)
2071 self.assertEqual(['Two', 'Bla'], result)
2072
2074 XML = self.etree.XML
2075
2076 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
2077 result = []
2078 for el in root.iterchildren(reversed=True, tag='two'):
2079 result.append(el.text)
2080 self.assertEqual(['Bla', 'Two'], result)
2081
2083 XML = self.etree.XML
2084
2085 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2086 result = []
2087 for el in root.iterchildren(tag=['two', 'three']):
2088 result.append(el.text)
2089 self.assertEqual(['Two', 'Bla', None], result)
2090
2092 XML = self.etree.XML
2093
2094 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2095 result = []
2096 for el in root.iterchildren('two', 'three'):
2097 result.append(el.text)
2098 self.assertEqual(['Two', 'Bla', None], result)
2099
2101 XML = self.etree.XML
2102
2103 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
2104 result = []
2105 for el in root.iterchildren(reversed=True, tag=['two', 'three']):
2106 result.append(el.text)
2107 self.assertEqual([None, 'Bla', 'Two'], result)
2108
2110 Element = self.etree.Element
2111 SubElement = self.etree.SubElement
2112
2113 a = Element('a')
2114 b = SubElement(a, 'b')
2115 c = SubElement(a, 'c')
2116 d = SubElement(b, 'd')
2117 self.assertEqual(
2118 [],
2119 list(a.iterancestors()))
2120 self.assertEqual(
2121 [a],
2122 list(b.iterancestors()))
2123 self.assertEqual(
2124 [a],
2125 list(c.iterancestors()))
2126 self.assertEqual(
2127 [b, a],
2128 list(d.iterancestors()))
2129
2131 Element = self.etree.Element
2132 SubElement = self.etree.SubElement
2133
2134 a = Element('a')
2135 b = SubElement(a, 'b')
2136 c = SubElement(a, 'c')
2137 d = SubElement(b, 'd')
2138 self.assertEqual(
2139 [a],
2140 list(d.iterancestors('a')))
2141 self.assertEqual(
2142 [a],
2143 list(d.iterancestors(tag='a')))
2144
2145 self.assertEqual(
2146 [b, a],
2147 list(d.iterancestors('*')))
2148 self.assertEqual(
2149 [b, a],
2150 list(d.iterancestors(tag='*')))
2151
2153 Element = self.etree.Element
2154 SubElement = self.etree.SubElement
2155
2156 a = Element('a')
2157 b = SubElement(a, 'b')
2158 c = SubElement(a, 'c')
2159 d = SubElement(b, 'd')
2160 self.assertEqual(
2161 [b, a],
2162 list(d.iterancestors(tag=('a', 'b'))))
2163 self.assertEqual(
2164 [b, a],
2165 list(d.iterancestors('a', 'b')))
2166
2167 self.assertEqual(
2168 [],
2169 list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
2170 self.assertEqual(
2171 [],
2172 list(d.iterancestors('w', 'x', 'y', 'z')))
2173
2174 self.assertEqual(
2175 [],
2176 list(d.iterancestors(tag=('d', 'x'))))
2177 self.assertEqual(
2178 [],
2179 list(d.iterancestors('d', 'x')))
2180
2181 self.assertEqual(
2182 [b, a],
2183 list(d.iterancestors(tag=('b', '*'))))
2184 self.assertEqual(
2185 [b, a],
2186 list(d.iterancestors('b', '*')))
2187
2188 self.assertEqual(
2189 [b],
2190 list(d.iterancestors(tag=('b', 'c'))))
2191 self.assertEqual(
2192 [b],
2193 list(d.iterancestors('b', 'c')))
2194
2196 Element = self.etree.Element
2197 SubElement = self.etree.SubElement
2198
2199 a = Element('a')
2200 b = SubElement(a, 'b')
2201 c = SubElement(a, 'c')
2202 d = SubElement(b, 'd')
2203 e = SubElement(c, 'e')
2204
2205 self.assertEqual(
2206 [b, d, c, e],
2207 list(a.iterdescendants()))
2208 self.assertEqual(
2209 [],
2210 list(d.iterdescendants()))
2211
2213 Element = self.etree.Element
2214 SubElement = self.etree.SubElement
2215
2216 a = Element('a')
2217 b = SubElement(a, 'b')
2218 c = SubElement(a, 'c')
2219 d = SubElement(b, 'd')
2220 e = SubElement(c, 'e')
2221
2222 self.assertEqual(
2223 [],
2224 list(a.iterdescendants('a')))
2225 self.assertEqual(
2226 [],
2227 list(a.iterdescendants(tag='a')))
2228
2229 a2 = SubElement(e, 'a')
2230 self.assertEqual(
2231 [a2],
2232 list(a.iterdescendants('a')))
2233
2234 self.assertEqual(
2235 [a2],
2236 list(c.iterdescendants('a')))
2237 self.assertEqual(
2238 [a2],
2239 list(c.iterdescendants(tag='a')))
2240
2242 Element = self.etree.Element
2243 SubElement = self.etree.SubElement
2244
2245 a = Element('a')
2246 b = SubElement(a, 'b')
2247 c = SubElement(a, 'c')
2248 d = SubElement(b, 'd')
2249 e = SubElement(c, 'e')
2250
2251 self.assertEqual(
2252 [b, e],
2253 list(a.iterdescendants(tag=('a', 'b', 'e'))))
2254 self.assertEqual(
2255 [b, e],
2256 list(a.iterdescendants('a', 'b', 'e')))
2257
2258 a2 = SubElement(e, 'a')
2259 self.assertEqual(
2260 [b, a2],
2261 list(a.iterdescendants(tag=('a', 'b'))))
2262 self.assertEqual(
2263 [b, a2],
2264 list(a.iterdescendants('a', 'b')))
2265
2266 self.assertEqual(
2267 [],
2268 list(c.iterdescendants(tag=('x', 'y', 'z'))))
2269 self.assertEqual(
2270 [],
2271 list(c.iterdescendants('x', 'y', 'z')))
2272
2273 self.assertEqual(
2274 [b, d, c, e, a2],
2275 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
2276 self.assertEqual(
2277 [b, d, c, e, a2],
2278 list(a.iterdescendants('x', 'y', 'z', '*')))
2279
2281 Element = self.etree.Element
2282 SubElement = self.etree.SubElement
2283
2284 a = Element('a')
2285 b = SubElement(a, 'b')
2286 c = SubElement(a, 'c')
2287 d = SubElement(b, 'd')
2288 self.assertEqual(
2289 a,
2290 a.getroottree().getroot())
2291 self.assertEqual(
2292 a,
2293 b.getroottree().getroot())
2294 self.assertEqual(
2295 a,
2296 d.getroottree().getroot())
2297
2299 Element = self.etree.Element
2300 SubElement = self.etree.SubElement
2301
2302 a = Element('a')
2303 b = SubElement(a, 'b')
2304 c = SubElement(a, 'c')
2305 self.assertEqual(
2306 None,
2307 a.getnext())
2308 self.assertEqual(
2309 c,
2310 b.getnext())
2311 self.assertEqual(
2312 None,
2313 c.getnext())
2314
2316 Element = self.etree.Element
2317 SubElement = self.etree.SubElement
2318
2319 a = Element('a')
2320 b = SubElement(a, 'b')
2321 c = SubElement(a, 'c')
2322 d = SubElement(b, 'd')
2323 self.assertEqual(
2324 None,
2325 a.getprevious())
2326 self.assertEqual(
2327 b,
2328 c.getprevious())
2329 self.assertEqual(
2330 None,
2331 b.getprevious())
2332
2334 Element = self.etree.Element
2335 SubElement = self.etree.SubElement
2336
2337 a = Element('a')
2338 b = SubElement(a, 'b')
2339 c = SubElement(a, 'c')
2340 d = SubElement(b, 'd')
2341 self.assertEqual(
2342 [],
2343 list(a.itersiblings()))
2344 self.assertEqual(
2345 [c],
2346 list(b.itersiblings()))
2347 self.assertEqual(
2348 [],
2349 list(c.itersiblings()))
2350 self.assertEqual(
2351 [b],
2352 list(c.itersiblings(preceding=True)))
2353 self.assertEqual(
2354 [],
2355 list(b.itersiblings(preceding=True)))
2356
2358 Element = self.etree.Element
2359 SubElement = self.etree.SubElement
2360
2361 a = Element('a')
2362 b = SubElement(a, 'b')
2363 c = SubElement(a, 'c')
2364 d = SubElement(b, 'd')
2365 self.assertEqual(
2366 [],
2367 list(a.itersiblings(tag='XXX')))
2368 self.assertEqual(
2369 [c],
2370 list(b.itersiblings(tag='c')))
2371 self.assertEqual(
2372 [c],
2373 list(b.itersiblings(tag='*')))
2374 self.assertEqual(
2375 [b],
2376 list(c.itersiblings(preceding=True, tag='b')))
2377 self.assertEqual(
2378 [],
2379 list(c.itersiblings(preceding=True, tag='c')))
2380
2382 Element = self.etree.Element
2383 SubElement = self.etree.SubElement
2384
2385 a = Element('a')
2386 b = SubElement(a, 'b')
2387 c = SubElement(a, 'c')
2388 d = SubElement(b, 'd')
2389 e = SubElement(a, 'e')
2390 self.assertEqual(
2391 [],
2392 list(a.itersiblings(tag=('XXX', 'YYY'))))
2393 self.assertEqual(
2394 [c, e],
2395 list(b.itersiblings(tag=('c', 'd', 'e'))))
2396 self.assertEqual(
2397 [b],
2398 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
2399 self.assertEqual(
2400 [c, b],
2401 list(e.itersiblings(preceding=True, tag=('c', '*'))))
2402
2404 parseid = self.etree.parseid
2405 XML = self.etree.XML
2406 xml_text = _bytes('''
2407 <!DOCTYPE document [
2408 <!ELEMENT document (h1,p)*>
2409 <!ELEMENT h1 (#PCDATA)>
2410 <!ATTLIST h1 myid ID #REQUIRED>
2411 <!ELEMENT p (#PCDATA)>
2412 <!ATTLIST p someid ID #REQUIRED>
2413 ]>
2414 <document>
2415 <h1 myid="chapter1">...</h1>
2416 <p id="note1" class="note">...</p>
2417 <p>Regular paragraph.</p>
2418 <p xml:id="xmlid">XML:ID paragraph.</p>
2419 <p someid="warn1" class="warning">...</p>
2420 </document>
2421 ''')
2422
2423 tree, dic = parseid(BytesIO(xml_text))
2424 root = tree.getroot()
2425 root2 = XML(xml_text)
2426 self.assertEqual(self._writeElement(root),
2427 self._writeElement(root2))
2428 expected = {
2429 "chapter1" : root[0],
2430 "xmlid" : root[3],
2431 "warn1" : root[4]
2432 }
2433 self.assertTrue("chapter1" in dic)
2434 self.assertTrue("warn1" in dic)
2435 self.assertTrue("xmlid" in dic)
2436 self._checkIDDict(dic, expected)
2437
2439 XMLDTDID = self.etree.XMLDTDID
2440 XML = self.etree.XML
2441 xml_text = _bytes('''
2442 <!DOCTYPE document [
2443 <!ELEMENT document (h1,p)*>
2444 <!ELEMENT h1 (#PCDATA)>
2445 <!ATTLIST h1 myid ID #REQUIRED>
2446 <!ELEMENT p (#PCDATA)>
2447 <!ATTLIST p someid ID #REQUIRED>
2448 ]>
2449 <document>
2450 <h1 myid="chapter1">...</h1>
2451 <p id="note1" class="note">...</p>
2452 <p>Regular paragraph.</p>
2453 <p xml:id="xmlid">XML:ID paragraph.</p>
2454 <p someid="warn1" class="warning">...</p>
2455 </document>
2456 ''')
2457
2458 root, dic = XMLDTDID(xml_text)
2459 root2 = XML(xml_text)
2460 self.assertEqual(self._writeElement(root),
2461 self._writeElement(root2))
2462 expected = {
2463 "chapter1" : root[0],
2464 "xmlid" : root[3],
2465 "warn1" : root[4]
2466 }
2467 self.assertTrue("chapter1" in dic)
2468 self.assertTrue("warn1" in dic)
2469 self.assertTrue("xmlid" in dic)
2470 self._checkIDDict(dic, expected)
2471
2473 XMLDTDID = self.etree.XMLDTDID
2474 XML = self.etree.XML
2475 xml_text = _bytes('''
2476 <document>
2477 <h1 myid="chapter1">...</h1>
2478 <p id="note1" class="note">...</p>
2479 <p>Regular paragraph.</p>
2480 <p someid="warn1" class="warning">...</p>
2481 </document>
2482 ''')
2483
2484 root, dic = XMLDTDID(xml_text)
2485 root2 = XML(xml_text)
2486 self.assertEqual(self._writeElement(root),
2487 self._writeElement(root2))
2488 expected = {}
2489 self._checkIDDict(dic, expected)
2490
2492 XMLDTDID = self.etree.XMLDTDID
2493 XML = self.etree.XML
2494 xml_text = _bytes('''
2495 <!DOCTYPE document [
2496 <!ELEMENT document (h1,p)*>
2497 <!ELEMENT h1 (#PCDATA)>
2498 <!ATTLIST h1 myid ID #REQUIRED>
2499 <!ELEMENT p (#PCDATA)>
2500 <!ATTLIST p someid ID #REQUIRED>
2501 ]>
2502 <document>
2503 <h1 myid="chapter1">...</h1>
2504 <p id="note1" class="note">...</p>
2505 <p>Regular paragraph.</p>
2506 <p xml:id="xmlid">XML:ID paragraph.</p>
2507 <p someid="warn1" class="warning">...</p>
2508 </document>
2509 ''')
2510
2511 parser = etree.XMLParser(collect_ids=False)
2512 root, dic = XMLDTDID(xml_text, parser=parser)
2513 root2 = XML(xml_text)
2514 self.assertEqual(self._writeElement(root),
2515 self._writeElement(root2))
2516 self.assertFalse(dic)
2517 self._checkIDDict(dic, {})
2518
2520 self.assertEqual(len(dic),
2521 len(expected))
2522 self.assertEqual(sorted(dic.items()),
2523 sorted(expected.items()))
2524 if sys.version_info < (3,):
2525 self.assertEqual(sorted(dic.iteritems()),
2526 sorted(expected.iteritems()))
2527 self.assertEqual(sorted(dic.keys()),
2528 sorted(expected.keys()))
2529 if sys.version_info < (3,):
2530 self.assertEqual(sorted(dic.iterkeys()),
2531 sorted(expected.iterkeys()))
2532 if sys.version_info < (3,):
2533 self.assertEqual(sorted(dic.values()),
2534 sorted(expected.values()))
2535 self.assertEqual(sorted(dic.itervalues()),
2536 sorted(expected.itervalues()))
2537
2539 etree = self.etree
2540
2541 r = {'foo': 'http://ns.infrae.com/foo'}
2542 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2543 self.assertEqual(
2544 'foo',
2545 e.prefix)
2546 self.assertEqual(
2547 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
2548 self._writeElement(e))
2549
2551 etree = self.etree
2552
2553 r = {None: 'http://ns.infrae.com/foo'}
2554 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2555 self.assertEqual(
2556 None,
2557 e.prefix)
2558 self.assertEqual(
2559 '{http://ns.infrae.com/foo}bar',
2560 e.tag)
2561 self.assertEqual(
2562 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
2563 self._writeElement(e))
2564
2566 etree = self.etree
2567
2568 r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'}
2569 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2570 self.assertEqual(None, e.prefix)
2571 self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag)
2572 self.assertEqual(
2573 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'),
2574 self._writeElement(e))
2575
2577 etree = self.etree
2578
2579 r = {None: 'http://ns.infrae.com/foo',
2580 'hoi': 'http://ns.infrae.com/hoi'}
2581 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2582 e.set('{http://ns.infrae.com/hoi}test', 'value')
2583 self.assertEqual(
2584 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
2585 self._writeElement(e))
2586
2588 etree = self.etree
2589
2590 root = etree.Element('{http://test/ns}root',
2591 nsmap={None: 'http://test/ns'})
2592 sub = etree.Element('{http://test/ns}sub',
2593 nsmap={'test': 'http://test/ns'})
2594
2595 sub.attrib['{http://test/ns}attr'] = 'value'
2596 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2597 self.assertEqual(
2598 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2599 etree.tostring(sub))
2600
2601 root.append(sub)
2602 self.assertEqual(
2603 _bytes('<root xmlns="http://test/ns">'
2604 '<sub xmlns:test="http://test/ns" test:attr="value"/>'
2605 '</root>'),
2606 etree.tostring(root))
2607
2609 etree = self.etree
2610
2611 root = etree.Element('root')
2612 sub = etree.Element('{http://test/ns}sub',
2613 nsmap={'test': 'http://test/ns'})
2614
2615 sub.attrib['{http://test/ns}attr'] = 'value'
2616 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2617 self.assertEqual(
2618 _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
2619 etree.tostring(sub))
2620
2621 root.append(sub)
2622 self.assertEqual(
2623 _bytes('<root>'
2624 '<test:sub xmlns:test="http://test/ns" test:attr="value"/>'
2625 '</root>'),
2626 etree.tostring(root))
2627
2629 etree = self.etree
2630
2631 root = etree.Element('root')
2632 sub = etree.Element('{http://test/ns}sub',
2633 nsmap={None: 'http://test/ns'})
2634
2635 sub.attrib['{http://test/ns}attr'] = 'value'
2636 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2637 self.assertEqual(
2638 _bytes('<sub xmlns="http://test/ns" '
2639 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2640 etree.tostring(sub))
2641
2642 root.append(sub)
2643 self.assertEqual(
2644 _bytes('<root>'
2645 '<sub xmlns="http://test/ns"'
2646 ' xmlns:ns0="http://test/ns" ns0:attr="value"/>'
2647 '</root>'),
2648 etree.tostring(root))
2649
2651 etree = self.etree
2652
2653 root = etree.Element('{http://test/ns}root',
2654 nsmap={'test': 'http://test/ns',
2655 None: 'http://test/ns'})
2656 sub = etree.Element('{http://test/ns}sub',
2657 nsmap={None: 'http://test/ns'})
2658
2659 sub.attrib['{http://test/ns}attr'] = 'value'
2660 self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
2661 self.assertEqual(
2662 _bytes('<sub xmlns="http://test/ns" '
2663 'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
2664 etree.tostring(sub))
2665
2666 root.append(sub)
2667 self.assertEqual(
2668 _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">'
2669 '<test:sub test:attr="value"/>'
2670 '</test:root>'),
2671 etree.tostring(root))
2672
2674 etree = self.etree
2675 r = {None: 'http://ns.infrae.com/foo',
2676 'hoi': 'http://ns.infrae.com/hoi'}
2677 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
2678 tree = etree.ElementTree(element=e)
2679 etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
2680 self.assertEqual(
2681 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
2682 self._writeElement(e))
2683
2685 etree = self.etree
2686
2687 r = {None: 'http://ns.infrae.com/foo'}
2688 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2689 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2690
2691 e1.append(e2)
2692
2693 self.assertEqual(
2694 None,
2695 e1.prefix)
2696 self.assertEqual(
2697 None,
2698 e1[0].prefix)
2699 self.assertEqual(
2700 '{http://ns.infrae.com/foo}bar',
2701 e1.tag)
2702 self.assertEqual(
2703 '{http://ns.infrae.com/foo}bar',
2704 e1[0].tag)
2705
2707 etree = self.etree
2708
2709 r = {None: 'http://ns.infrae.com/BAR'}
2710 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
2711 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2712
2713 e1.append(e2)
2714
2715 self.assertEqual(
2716 None,
2717 e1.prefix)
2718 self.assertNotEqual(
2719 None,
2720 e2.prefix)
2721 self.assertEqual(
2722 '{http://ns.infrae.com/BAR}bar',
2723 e1.tag)
2724 self.assertEqual(
2725 '{http://ns.infrae.com/foo}bar',
2726 e2.tag)
2727
2729 ns_href = "http://a.b.c"
2730 one = self.etree.fromstring(
2731 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2732 baz = one[0][0]
2733
2734 two = self.etree.fromstring(
2735 _bytes('<root xmlns:ns="%s"/>' % ns_href))
2736 two.append(baz)
2737 del one # make sure the source document is deallocated
2738
2739 self.assertEqual('{%s}baz' % ns_href, baz.tag)
2740 self.assertEqual(
2741 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
2742 self.etree.tostring(two))
2743
2745 xml = _bytes(
2746 '<foo xmlns="F" xmlns:x="x">'
2747 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">'
2748 '<ns:baz/>'
2749 '</bar></foo>'
2750 )
2751 root = self.etree.fromstring(xml)
2752 self.assertEqual(xml, self.etree.tostring(root))
2753 self.etree.cleanup_namespaces(root)
2754 self.assertEqual(
2755 _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
2756 self.etree.tostring(root))
2757
2759 xml = _bytes(
2760 '<foo xmlns="F" xmlns:x="X" xmlns:a="A">'
2761 '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">'
2762 '<ns:baz a:test="attr"/>'
2763 '</bar></foo>'
2764 )
2765 root = self.etree.fromstring(xml)
2766 self.assertEqual(xml, self.etree.tostring(root))
2767 self.etree.cleanup_namespaces(root)
2768 self.assertEqual(
2769 _bytes('<foo xmlns="F" xmlns:a="A">'
2770 '<bar xmlns:ns="NS" xmlns="B">'
2771 '<ns:baz a:test="attr"/>'
2772 '</bar></foo>'),
2773 self.etree.tostring(root))
2774
2776 xml = ('<n12:foo ' +
2777 ' '.join('xmlns:n{n}="NS{n}"'.format(n=i) for i in range(100)) +
2778 '><n68:a/></n12:foo>').encode('utf8')
2779 root = self.etree.fromstring(xml)
2780 self.assertEqual(xml, self.etree.tostring(root))
2781 self.etree.cleanup_namespaces(root)
2782 self.assertEqual(
2783 b'<n12:foo xmlns:n12="NS12" xmlns:n68="NS68"><n68:a/></n12:foo>',
2784 self.etree.tostring(root))
2785
2787 xml = ('<root>' +
2788 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2789 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8')
2790 root = self.etree.fromstring(xml)
2791 self.assertEqual(xml, self.etree.tostring(root))
2792 self.etree.cleanup_namespaces(root)
2793 self.assertEqual(
2794 b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 +
2795 b'<n64:x/>' + b'</a>'*100 + b'</root>',
2796 self.etree.tostring(root))
2797
2799 xml = ('<root>' +
2800 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
2801 '<n64:x xmlns:a="A" a:attr="X"/>' +
2802 '</a>'*100 +
2803 '</root>').encode('utf8')
2804 root = self.etree.fromstring(xml)
2805 self.assertEqual(xml, self.etree.tostring(root))
2806 self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'})
2807 self.assertEqual(
2808 b'<root xmlns:n64="NS64">' + b'<a>'*100 +
2809 b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>',
2810 self.etree.tostring(root))
2811
2813 xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">'
2814 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2815 '<foo>foo:bar</foo>'
2816 '</root>').encode('utf8')
2817 root = self.etree.fromstring(xml)
2818 self.assertEqual(xml, self.etree.tostring(root))
2819 self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo'])
2820 self.assertEqual(
2821 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2822 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2823 b'<foo>foo:bar</foo>'
2824 b'</root>',
2825 self.etree.tostring(root))
2826
2828 xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">'
2829 '<sub xmlns:foo="FOO">'
2830 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
2831 '<foo>foo:bar</foo>'
2832 '</sub>'
2833 '</root>').encode('utf8')
2834 root = self.etree.fromstring(xml)
2835 self.assertEqual(xml, self.etree.tostring(root))
2836 self.etree.cleanup_namespaces(
2837 root,
2838 top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'},
2839 keep_ns_prefixes=['foo'])
2840 self.assertEqual(
2841 b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
2842 b'<sub>'
2843 b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
2844 b'<foo>foo:bar</foo>'
2845 b'</sub>'
2846 b'</root>',
2847 self.etree.tostring(root))
2848
2850 etree = self.etree
2851
2852 r = {None: 'http://ns.infrae.com/foo',
2853 'hoi': 'http://ns.infrae.com/hoi'}
2854 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2855 self.assertEqual(
2856 r,
2857 e.nsmap)
2858
2860 etree = self.etree
2861
2862 re = {None: 'http://ns.infrae.com/foo',
2863 'hoi': 'http://ns.infrae.com/hoi'}
2864 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
2865
2866 rs = {None: 'http://ns.infrae.com/honk',
2867 'top': 'http://ns.infrae.com/top'}
2868 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
2869
2870 r = re.copy()
2871 r.update(rs)
2872 self.assertEqual(re, e.nsmap)
2873 self.assertEqual(r, s.nsmap)
2874
2876 etree = self.etree
2877 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
2878 self.assertEqual({'hha': None}, el.nsmap)
2879
2881 Element = self.etree.Element
2882 SubElement = self.etree.SubElement
2883
2884 a = Element('a')
2885 b = SubElement(a, 'b')
2886 c = SubElement(a, 'c')
2887 d = SubElement(b, 'd')
2888 e = SubElement(c, 'e')
2889 f = SubElement(c, 'f')
2890
2891 self.assertEqual(
2892 [a, b],
2893 list(a.getiterator('a', 'b')))
2894 self.assertEqual(
2895 [],
2896 list(a.getiterator('x', 'y')))
2897 self.assertEqual(
2898 [a, f],
2899 list(a.getiterator('f', 'a')))
2900 self.assertEqual(
2901 [c, e, f],
2902 list(c.getiterator('c', '*', 'a')))
2903 self.assertEqual(
2904 [],
2905 list(a.getiterator( (), () )))
2906
2908 Element = self.etree.Element
2909 SubElement = self.etree.SubElement
2910
2911 a = Element('a')
2912 b = SubElement(a, 'b')
2913 c = SubElement(a, 'c')
2914 d = SubElement(b, 'd')
2915 e = SubElement(c, 'e')
2916 f = SubElement(c, 'f')
2917
2918 self.assertEqual(
2919 [a, b],
2920 list(a.getiterator( ('a', 'b') )))
2921 self.assertEqual(
2922 [],
2923 list(a.getiterator( ('x', 'y') )))
2924 self.assertEqual(
2925 [a, f],
2926 list(a.getiterator( ('f', 'a') )))
2927 self.assertEqual(
2928 [c, e, f],
2929 list(c.getiterator( ('c', '*', 'a') )))
2930 self.assertEqual(
2931 [],
2932 list(a.getiterator( () )))
2933
2935 Element = self.etree.Element
2936 SubElement = self.etree.SubElement
2937
2938 a = Element('{a}a')
2939 b = SubElement(a, '{a}b')
2940 c = SubElement(a, '{a}c')
2941 d = SubElement(b, '{b}d')
2942 e = SubElement(c, '{a}e')
2943 f = SubElement(c, '{b}f')
2944 g = SubElement(c, 'g')
2945
2946 self.assertEqual(
2947 [a],
2948 list(a.getiterator('{a}a')))
2949 self.assertEqual(
2950 [],
2951 list(a.getiterator('{b}a')))
2952 self.assertEqual(
2953 [],
2954 list(a.getiterator('a')))
2955 self.assertEqual(
2956 [a,b,d,c,e,f,g],
2957 list(a.getiterator('*')))
2958 self.assertEqual(
2959 [f],
2960 list(c.getiterator('{b}*')))
2961 self.assertEqual(
2962 [d, f],
2963 list(a.getiterator('{b}*')))
2964 self.assertEqual(
2965 [g],
2966 list(a.getiterator('g')))
2967 self.assertEqual(
2968 [g],
2969 list(a.getiterator('{}g')))
2970 self.assertEqual(
2971 [g],
2972 list(a.getiterator('{}*')))
2973
2975 Element = self.etree.Element
2976 SubElement = self.etree.SubElement
2977
2978 a = Element('{a}a')
2979 b = SubElement(a, '{nsA}b')
2980 c = SubElement(b, '{nsB}b')
2981 d = SubElement(a, 'b')
2982 e = SubElement(a, '{nsA}e')
2983 f = SubElement(e, '{nsB}e')
2984 g = SubElement(e, 'e')
2985
2986 self.assertEqual(
2987 [b, c, d],
2988 list(a.getiterator('{*}b')))
2989 self.assertEqual(
2990 [e, f, g],
2991 list(a.getiterator('{*}e')))
2992 self.assertEqual(
2993 [a, b, c, d, e, f, g],
2994 list(a.getiterator('{*}*')))
2995
2997 Element = self.etree.Element
2998 Entity = self.etree.Entity
2999 SubElement = self.etree.SubElement
3000
3001 a = Element('a')
3002 b = SubElement(a, 'b')
3003 entity_b = Entity("TEST-b")
3004 b.append(entity_b)
3005
3006 self.assertEqual(
3007 [entity_b],
3008 list(a.getiterator(Entity)))
3009
3010 entity_a = Entity("TEST-a")
3011 a.append(entity_a)
3012
3013 self.assertEqual(
3014 [entity_b, entity_a],
3015 list(a.getiterator(Entity)))
3016
3017 self.assertEqual(
3018 [entity_b],
3019 list(b.getiterator(Entity)))
3020
3022 Element = self.etree.Element
3023 Comment = self.etree.Comment
3024 PI = self.etree.PI
3025 SubElement = self.etree.SubElement
3026
3027 a = Element('a')
3028 b = SubElement(a, 'b')
3029 a.append(Comment("test"))
3030 a.append(PI("pi", "content"))
3031 c = SubElement(a, 'c')
3032
3033 self.assertEqual(
3034 [a, b, c],
3035 list(a.getiterator(Element)))
3036
3038 # ElementTree iterates over everything here
3039 Element = self.etree.Element
3040 Comment = self.etree.Comment
3041 PI = self.etree.PI
3042 SubElement = self.etree.SubElement
3043
3044 a = Element('a')
3045 b = SubElement(a, 'b')
3046 a.append(Comment("test"))
3047 a.append(PI("pi", "content"))
3048 c = SubElement(a, 'c')
3049
3050 self.assertEqual(
3051 [a, b, c],
3052 list(a.getiterator('*')))
3053
3055 a = etree.Element("a")
3056 b = etree.SubElement(a, "b")
3057 c = etree.SubElement(a, "c")
3058 d1 = etree.SubElement(c, "d")
3059 d2 = etree.SubElement(c, "d")
3060 c.text = d1.text = 'TEXT'
3061
3062 tree = etree.ElementTree(a)
3063 self.assertEqual('.', tree.getelementpath(a))
3064 self.assertEqual('c/d[1]', tree.getelementpath(d1))
3065 self.assertEqual('c/d[2]', tree.getelementpath(d2))
3066
3067 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3068 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3069
3070 tree = etree.ElementTree(c)
3071 self.assertEqual('.', tree.getelementpath(c))
3072 self.assertEqual('d[2]', tree.getelementpath(d2))
3073 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3074
3075 tree = etree.ElementTree(b) # not a parent of a/c/d1/d2
3076 self.assertEqual('.', tree.getelementpath(b))
3077 self.assertRaises(ValueError, tree.getelementpath, a)
3078 self.assertRaises(ValueError, tree.getelementpath, c)
3079 self.assertRaises(ValueError, tree.getelementpath, d2)
3080
3082 a = etree.Element("{http://ns1/}a")
3083 b = etree.SubElement(a, "{http://ns1/}b")
3084 c = etree.SubElement(a, "{http://ns1/}c")
3085 d1 = etree.SubElement(c, "{http://ns1/}d")
3086 d2 = etree.SubElement(c, "{http://ns2/}d")
3087 d3 = etree.SubElement(c, "{http://ns1/}d")
3088
3089 tree = etree.ElementTree(a)
3090 self.assertEqual('.', tree.getelementpath(a))
3091 self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]',
3092 tree.getelementpath(d1))
3093 self.assertEqual('{http://ns1/}c/{http://ns2/}d',
3094 tree.getelementpath(d2))
3095 self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]',
3096 tree.getelementpath(d3))
3097
3098 self.assertEqual(a, tree.find(tree.getelementpath(a)))
3099 self.assertEqual(b, tree.find(tree.getelementpath(b)))
3100 self.assertEqual(c, tree.find(tree.getelementpath(c)))
3101 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3102 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3103 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
3104
3105 tree = etree.ElementTree(c)
3106 self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1))
3107 self.assertEqual('{http://ns2/}d', tree.getelementpath(d2))
3108 self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3))
3109 self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
3110 self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
3111 self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
3112
3113 tree = etree.ElementTree(b) # not a parent of d1/d2
3114 self.assertRaises(ValueError, tree.getelementpath, d1)
3115 self.assertRaises(ValueError, tree.getelementpath, d2)
3116
3118 XML = self.etree.XML
3119 ElementTree = self.etree.ElementTree
3120 QName = self.etree.QName
3121 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
3122 self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
3123
3125 XML = self.etree.XML
3126 ElementTree = self.etree.ElementTree
3127 QName = self.etree.QName
3128 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
3129 self.assertEqual(len(list(tree.findall(QName("c")))), 1)
3130
3132 XML = self.etree.XML
3133 ElementTree = self.etree.ElementTree
3134 QName = self.etree.QName
3135 tree = ElementTree(XML(
3136 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
3137 self.assertEqual(len(list(tree.findall(QName("b")))), 2)
3138 self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
3139
3141 XML = self.etree.XML
3142 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
3143 self.assertEqual(len(root.findall(".//{X}b")), 2)
3144 self.assertEqual(len(root.findall(".//{X}*")), 2)
3145 self.assertEqual(len(root.findall(".//b")), 3)
3146
3148 XML = self.etree.XML
3149 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3150 nsmap = {'xx': 'X'}
3151 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3152 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
3153 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3154 nsmap = {'xx': 'Y'}
3155 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
3156 self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
3157 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
3158
3160 XML = self.etree.XML
3161 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
3162 nsmap = {'xx': 'X'}
3163 self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
3164 nsmap = {'xx': 'X', None: 'Y'}
3165 self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1)
3166 nsmap = {'xx': 'X', '': 'Y'}
3167 self.assertRaises(ValueError, root.findall, ".//xx:b", namespaces=nsmap)
3168
3170 XML = self.etree.XML
3171 root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>'))
3172 self.assertRaises(SyntaxError, root.findall, '')
3173 self.assertRaises(SyntaxError, root.findall, '//') # absolute path on Element
3174 self.assertRaises(SyntaxError, root.findall, './//')
3175
3177 etree = self.etree
3178 e = etree.Element('foo')
3179 for i in range(10):
3180 etree.SubElement(e, 'a%s' % i)
3181 for i in range(10):
3182 self.assertEqual(
3183 i,
3184 e.index(e[i]))
3185 self.assertEqual(
3186 3, e.index(e[3], 3))
3187 self.assertRaises(
3188 ValueError, e.index, e[3], 4)
3189 self.assertRaises(
3190 ValueError, e.index, e[3], 0, 2)
3191 self.assertRaises(
3192 ValueError, e.index, e[8], 0, -3)
3193 self.assertRaises(
3194 ValueError, e.index, e[8], -5, -3)
3195 self.assertEqual(
3196 8, e.index(e[8], 0, -1))
3197 self.assertEqual(
3198 8, e.index(e[8], -12, -1))
3199 self.assertEqual(
3200 0, e.index(e[0], -12, -1))
3201
3203 etree = self.etree
3204 e = etree.Element('foo')
3205 for i in range(10):
3206 el = etree.SubElement(e, 'a%s' % i)
3207 el.text = "text%d" % i
3208 el.tail = "tail%d" % i
3209
3210 child0 = e[0]
3211 child1 = e[1]
3212 child2 = e[2]
3213
3214 e.replace(e[0], e[1])
3215 self.assertEqual(
3216 9, len(e))
3217 self.assertEqual(
3218 child1, e[0])
3219 self.assertEqual(
3220 child1.text, "text1")
3221 self.assertEqual(
3222 child1.tail, "tail1")
3223 self.assertEqual(
3224 child0.tail, "tail0")
3225 self.assertEqual(
3226 child2, e[1])
3227
3228 e.replace(e[-1], e[0])
3229 self.assertEqual(
3230 child1, e[-1])
3231 self.assertEqual(
3232 child1.text, "text1")
3233 self.assertEqual(
3234 child1.tail, "tail1")
3235 self.assertEqual(
3236 child2, e[0])
3237
3239 etree = self.etree
3240 e = etree.Element('foo')
3241 for i in range(10):
3242 etree.SubElement(e, 'a%s' % i)
3243
3244 new_element = etree.Element("test")
3245 new_element.text = "TESTTEXT"
3246 new_element.tail = "TESTTAIL"
3247 child1 = e[1]
3248 e.replace(e[0], new_element)
3249 self.assertEqual(
3250 new_element, e[0])
3251 self.assertEqual(
3252 "TESTTEXT",
3253 e[0].text)
3254 self.assertEqual(
3255 "TESTTAIL",
3256 e[0].tail)
3257 self.assertEqual(
3258 child1, e[1])
3259
3261 Element = self.etree.Element
3262 SubElement = self.etree.SubElement
3263
3264 a = Element('a')
3265
3266 e = Element('e')
3267 f = Element('f')
3268 g = Element('g')
3269
3270 s = [e, f, g]
3271 a[::-1] = s
3272 self.assertEqual(
3273 [g, f, e],
3274 list(a))
3275
3277 Element = self.etree.Element
3278 SubElement = self.etree.SubElement
3279
3280 a = Element('a')
3281 b = SubElement(a, 'b')
3282 c = SubElement(a, 'c')
3283 d = SubElement(a, 'd')
3284 e = SubElement(a, 'e')
3285
3286 x = Element('x')
3287 y = Element('y')
3288
3289 a[1::2] = [x, y]
3290 self.assertEqual(
3291 [b, x, d, y],
3292 list(a))
3293
3295 Element = self.etree.Element
3296 SubElement = self.etree.SubElement
3297
3298 a = Element('a')
3299 b = SubElement(a, 'b')
3300 c = SubElement(a, 'c')
3301 d = SubElement(a, 'd')
3302 e = SubElement(a, 'e')
3303
3304 x = Element('x')
3305 y = Element('y')
3306
3307 a[1::-1] = [x, y]
3308 self.assertEqual(
3309 [y, x, d, e],
3310 list(a))
3311
3313 Element = self.etree.Element
3314 SubElement = self.etree.SubElement
3315
3316 a = Element('a')
3317 b = SubElement(a, 'b')
3318 c = SubElement(a, 'c')
3319 d = SubElement(a, 'd')
3320 e = SubElement(a, 'e')
3321
3322 x = Element('x')
3323 y = Element('y')
3324
3325 a[::-2] = [x, y]
3326 self.assertEqual(
3327 [b, y, d, x],
3328 list(a))
3329
3331 Element = self.etree.Element
3332 SubElement = self.etree.SubElement
3333 try:
3334 slice
3335 except NameError:
3336 print("slice() not found")
3337 return
3338
3339 a = Element('a')
3340 b = SubElement(a, 'b')
3341 c = SubElement(a, 'c')
3342 d = SubElement(a, 'd')
3343 e = SubElement(a, 'e')
3344
3345 x = Element('x')
3346 y = Element('y')
3347 z = Element('z')
3348
3349 self.assertRaises(
3350 ValueError,
3351 operator.setitem, a, slice(1,None,2), [x, y, z])
3352
3353 self.assertEqual(
3354 [b, c, d, e],
3355 list(a))
3356
3358 XML = self.etree.XML
3359 root = XML(_bytes('''<?xml version="1.0"?>
3360 <root><test>
3361
3362 <bla/></test>
3363 </root>
3364 '''))
3365
3366 self.assertEqual(
3367 [2, 2, 4],
3368 [ el.sourceline for el in root.getiterator() ])
3369
3371 XML = self.etree.XML
3372 root = XML(_bytes(
3373 '<?xml version="1.0"?>\n'
3374 '<root>' + '\n' * 65536 +
3375 '<p>' + '\n' * 65536 + '</p>\n' +
3376 '<br/>\n'
3377 '</root>'))
3378
3379 if self.etree.LIBXML_VERSION >= (2, 9):
3380 expected = [2, 131074, 131076]
3381 else:
3382 expected = [2, 65535, 65535]
3383
3384 self.assertEqual(expected, [el.sourceline for el in root.iter()])
3385
3387 parse = self.etree.parse
3388 tree = parse(fileInTestDir('include/test_xinclude.xml'))
3389
3390 self.assertEqual(
3391 [1, 2, 3],
3392 [ el.sourceline for el in tree.getiterator() ])
3393
3395 iterparse = self.etree.iterparse
3396 lines = [ el.sourceline for (event, el) in
3397 iterparse(fileInTestDir('include/test_xinclude.xml')) ]
3398
3399 self.assertEqual(
3400 [2, 3, 1],
3401 lines)
3402
3404 iterparse = self.etree.iterparse
3405 lines = [ el.sourceline for (event, el) in
3406 iterparse(fileInTestDir('include/test_xinclude.xml'),
3407 events=("start",)) ]
3408
3409 self.assertEqual(
3410 [1, 2, 3],
3411 lines)
3412
3414 Element = self.etree.Element
3415 SubElement = self.etree.SubElement
3416 el = Element("test")
3417 self.assertEqual(None, el.sourceline)
3418
3419 child = SubElement(el, "test")
3420 self.assertEqual(None, el.sourceline)
3421 self.assertEqual(None, child.sourceline)
3422
3424 etree = self.etree
3425 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3426 docinfo = root.getroottree().docinfo
3427 self.assertEqual(docinfo.URL, "http://no/such/url")
3428
3430 etree = self.etree
3431 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3432 docinfo = root.getroottree().docinfo
3433 self.assertEqual(docinfo.URL, "http://no/such/url")
3434 docinfo.URL = "https://secret/url"
3435 self.assertEqual(docinfo.URL, "https://secret/url")
3436
3438 etree = self.etree
3439 tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
3440 docinfo = tree.docinfo
3441 self.assertEqual(docinfo.URL, "http://no/such/url")
3442
3444 etree = self.etree
3445 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
3446 base_url="http://no/such/url")
3447 docinfo = tree.docinfo
3448 self.assertEqual(docinfo.URL, "http://no/such/url")
3449
3451 etree = self.etree
3452 root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
3453 docinfo = root.getroottree().docinfo
3454 self.assertEqual(docinfo.URL, "http://no/such/url")
3455
3457 etree = self.etree
3458 xml_header = '<?xml version="1.0" encoding="ascii"?>'
3459 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3460 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3461 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
3462
3463 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
3464
3465 tree = etree.parse(BytesIO(xml))
3466 docinfo = tree.docinfo
3467 self.assertEqual(docinfo.encoding, "ascii")
3468 self.assertEqual(docinfo.xml_version, "1.0")
3469 self.assertEqual(docinfo.public_id, pub_id)
3470 self.assertEqual(docinfo.system_url, sys_id)
3471 self.assertEqual(docinfo.root_name, 'html')
3472 self.assertEqual(docinfo.doctype, doctype_string)
3473
3475 etree = self.etree
3476 xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
3477 sys_id = "some.dtd"
3478 doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
3479 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
3480
3481 tree = etree.parse(BytesIO(xml))
3482 docinfo = tree.docinfo
3483 self.assertEqual(docinfo.encoding, "UTF-8")
3484 self.assertEqual(docinfo.xml_version, "1.0")
3485 self.assertEqual(docinfo.public_id, None)
3486 self.assertEqual(docinfo.system_url, sys_id)
3487 self.assertEqual(docinfo.root_name, 'html')
3488 self.assertEqual(docinfo.doctype, doctype_string)
3489
3491 etree = self.etree
3492 xml = _bytes('<html><body></body></html>')
3493 tree = etree.parse(BytesIO(xml))
3494 docinfo = tree.docinfo
3495 self.assertEqual(docinfo.encoding, "UTF-8")
3496 self.assertEqual(docinfo.xml_version, "1.0")
3497 self.assertEqual(docinfo.public_id, None)
3498 self.assertEqual(docinfo.system_url, None)
3499 self.assertEqual(docinfo.root_name, 'html')
3500 self.assertEqual(docinfo.doctype, '')
3501
3503 etree = self.etree
3504 xml = _bytes('<!DOCTYPE root><root></root>')
3505 tree = etree.parse(BytesIO(xml))
3506 docinfo = tree.docinfo
3507 self.assertEqual(docinfo.encoding, "UTF-8")
3508 self.assertEqual(docinfo.xml_version, "1.0")
3509 self.assertEqual(docinfo.public_id, None)
3510 self.assertEqual(docinfo.system_url, None)
3511 self.assertEqual(docinfo.root_name, 'root')
3512 self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
3513
3515 etree = self.etree
3516 xml = _bytes('<!DOCTYPE root>\n<root/>')
3517 tree = etree.parse(BytesIO(xml))
3518 self.assertEqual(xml, etree.tostring(tree))
3519
3521 etree = self.etree
3522 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
3523 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
3524 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
3525
3526 xml = _bytes('<!DOCTYPE root>\n<root/>')
3527 tree = etree.parse(BytesIO(xml))
3528 self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
3529 etree.tostring(tree, doctype=doctype_string))
3530
3532 etree = self.etree
3533 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3534 self.assertEqual(root.base, "http://no/such/url")
3535 self.assertEqual(
3536 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3537 root.base = "https://secret/url"
3538 self.assertEqual(root.base, "https://secret/url")
3539 self.assertEqual(
3540 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3541 "https://secret/url")
3542
3544 etree = self.etree
3545 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
3546 self.assertEqual(root.base, "http://no/such/url")
3547 self.assertEqual(
3548 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
3549 root.set('{http://www.w3.org/XML/1998/namespace}base',
3550 "https://secret/url")
3551 self.assertEqual(root.base, "https://secret/url")
3552 self.assertEqual(
3553 root.get('{http://www.w3.org/XML/1998/namespace}base'),
3554 "https://secret/url")
3555
3557 etree = self.etree
3558 root = etree.HTML(_bytes("<html><body></body></html>"),
3559 base_url="http://no/such/url")
3560 self.assertEqual(root.base, "http://no/such/url")
3561
3563 etree = self.etree
3564 root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
3565 self.assertEqual(root.base, "http://no/such/url")
3566
3568 # parse from a file object that returns unicode strings
3569 f = LargeFileLikeUnicode()
3570 tree = self.etree.parse(f)
3571 root = tree.getroot()
3572 self.assertTrue(root.tag.endswith('root'))
3573
3575 # check that DTDs that go in also go back out
3576 xml = _bytes('''\
3577 <!DOCTYPE test SYSTEM "test.dtd" [
3578 <!ENTITY entity "tasty">
3579 <!ELEMENT test (a)>
3580 <!ELEMENT a (#PCDATA)>
3581 ]>
3582 <test><a>test-test</a></test>\
3583 ''')
3584 tree = self.etree.parse(BytesIO(xml))
3585 self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
3586 xml.replace(_bytes(" "), _bytes("")))
3587
3589 Element = self.etree.Element
3590
3591 a = Element('a')
3592 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
3593 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
3594
3595 self.assertRaises(ValueError, Element, 'ha\0ho')
3596
3598 Element = self.etree.Element
3599
3600 a = Element('a')
3601 self.assertRaises(ValueError, setattr, a, "text",
3602 _str('ha\0ho'))
3603 self.assertRaises(ValueError, setattr, a, "tail",
3604 _str('ha\0ho'))
3605
3606 self.assertRaises(ValueError, Element,
3607 _str('ha\0ho'))
3608
3610 Element = self.etree.Element
3611
3612 a = Element('a')
3613 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
3614 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
3615
3616 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
3617 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
3618
3619 self.assertRaises(ValueError, Element, 'ha\x07ho')
3620 self.assertRaises(ValueError, Element, 'ha\x02ho')
3621
3623 Element = self.etree.Element
3624
3625 a = Element('a')
3626 self.assertRaises(ValueError, setattr, a, "text",
3627 _str('ha\x07ho'))
3628 self.assertRaises(ValueError, setattr, a, "text",
3629 _str('ha\x02ho'))
3630
3631 self.assertRaises(ValueError, setattr, a, "tail",
3632 _str('ha\x07ho'))
3633 self.assertRaises(ValueError, setattr, a, "tail",
3634 _str('ha\x02ho'))
3635
3636 self.assertRaises(ValueError, Element,
3637 _str('ha\x07ho'))
3638 self.assertRaises(ValueError, Element,
3639 _str('ha\x02ho'))
3640
3642 Element = self.etree.Element
3643
3644 a = Element('a')
3645 self.assertRaises(ValueError, setattr, a, "text",
3646 _str('ha\u1234\x07ho'))
3647 self.assertRaises(ValueError, setattr, a, "text",
3648 _str('ha\u1234\x02ho'))
3649
3650 self.assertRaises(ValueError, setattr, a, "tail",
3651 _str('ha\u1234\x07ho'))
3652 self.assertRaises(ValueError, setattr, a, "tail",
3653 _str('ha\u1234\x02ho'))
3654
3655 self.assertRaises(ValueError, Element,
3656 _str('ha\u1234\x07ho'))
3657 self.assertRaises(ValueError, Element,
3658 _str('ha\u1234\x02ho'))
3659
3661 # ElementTree fails to serialize this
3662 tostring = self.etree.tostring
3663 Element = self.etree.Element
3664 SubElement = self.etree.SubElement
3665
3666 a = Element('a')
3667 b = SubElement(a, 'b')
3668 c = SubElement(a, 'c')
3669
3670 result = tostring(a, encoding='UTF-16')
3671 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
3672 canonicalize(result))
3673
3675 # ElementTree raises an AssertionError here
3676 tostring = self.etree.tostring
3677 self.assertRaises(TypeError, self.etree.tostring, None)
3678
3680 tostring = self.etree.tostring
3681 Element = self.etree.Element
3682 SubElement = self.etree.SubElement
3683
3684 a = Element('a')
3685 b = SubElement(a, 'b')
3686 c = SubElement(a, 'c')
3687
3688 result = tostring(a)
3689 self.assertEqual(result, _bytes("<a><b/><c/></a>"))
3690
3691 result = tostring(a, pretty_print=False)
3692 self.assertEqual(result, _bytes("<a><b/><c/></a>"))
3693
3694 result = tostring(a, pretty_print=True)
3695 self.assertEqual(result, _bytes("<a>\n <b/>\n <c/>\n</a>\n"))
3696
3698 tostring = self.etree.tostring
3699 Element = self.etree.Element
3700 SubElement = self.etree.SubElement
3701
3702 a = Element('a')
3703 a.tail = "aTAIL"
3704 b = SubElement(a, 'b')
3705 b.tail = "bTAIL"
3706 c = SubElement(a, 'c')
3707
3708 result = tostring(a)
3709 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
3710
3711 result = tostring(a, with_tail=False)
3712 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>"))
3713
3714 result = tostring(a, with_tail=True)
3715 self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
3716
3718 tostring = self.etree.tostring
3719 html = self.etree.fromstring(
3720 '<html><body>'
3721 '<div><p>Some text<i>\r\n</i></p></div>\r\n'
3722 '</body></html>',
3723 parser=self.etree.HTMLParser())
3724 self.assertEqual(html.tag, 'html')
3725 div = html.find('.//div')
3726 self.assertEqual(div.tail, '\r\n')
3727 result = tostring(div, method='html')
3728 self.assertEqual(
3729 result,
3730 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3731 result = tostring(div, method='html', with_tail=True)
3732 self.assertEqual(
3733 result,
3734 _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
3735 result = tostring(div, method='html', with_tail=False)
3736 self.assertEqual(
3737 result,
3738 _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
3739
3741 tostring = self.etree.tostring
3742 XML = self.etree.XML
3743 ElementTree = self.etree.ElementTree
3744 Element = self.etree.Element
3745
3746 tree = Element("root").getroottree()
3747 self.assertEqual(None, tree.docinfo.standalone)
3748
3749 tree = XML(_bytes("<root/>")).getroottree()
3750 self.assertEqual(None, tree.docinfo.standalone)
3751
3752 tree = XML(_bytes(
3753 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
3754 )).getroottree()
3755 self.assertEqual(True, tree.docinfo.standalone)
3756
3757 tree = XML(_bytes(
3758 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
3759 )).getroottree()
3760 self.assertEqual(False, tree.docinfo.standalone)
3761
3763 tostring = self.etree.tostring
3764 XML = self.etree.XML
3765 ElementTree = self.etree.ElementTree
3766
3767 root = XML(_bytes("<root/>"))
3768
3769 tree = ElementTree(root)
3770 self.assertEqual(None, tree.docinfo.standalone)
3771
3772 result = tostring(root, xml_declaration=True, encoding="ASCII")
3773 self.assertEqual(result, _bytes(
3774 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3775
3776 result = tostring(root, xml_declaration=True, encoding="ASCII",
3777 standalone=True)
3778 self.assertEqual(result, _bytes(
3779 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3780
3781 tree = ElementTree(XML(result))
3782 self.assertEqual(True, tree.docinfo.standalone)
3783
3784 result = tostring(root, xml_declaration=True, encoding="ASCII",
3785 standalone=False)
3786 self.assertEqual(result, _bytes(
3787 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
3788
3789 tree = ElementTree(XML(result))
3790 self.assertEqual(False, tree.docinfo.standalone)
3791
3793 tostring = self.etree.tostring
3794 XML = self.etree.XML
3795 ElementTree = self.etree.ElementTree
3796
3797 root = XML(_bytes(
3798 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
3799
3800 tree = ElementTree(root)
3801 self.assertEqual(True, tree.docinfo.standalone)
3802
3803 result = tostring(root, xml_declaration=True, encoding="ASCII")
3804 self.assertEqual(result, _bytes(
3805 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3806
3807 result = tostring(root, xml_declaration=True, encoding="ASCII",
3808 standalone=True)
3809 self.assertEqual(result, _bytes(
3810 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3811
3813 tostring = self.etree.tostring
3814 Element = self.etree.Element
3815 SubElement = self.etree.SubElement
3816
3817 a = Element('a')
3818 a.text = "A"
3819 a.tail = "tail"
3820 b = SubElement(a, 'b')
3821 b.text = "B"
3822 b.tail = _str("Søk på nettet")
3823 c = SubElement(a, 'c')
3824 c.text = "C"
3825
3826 result = tostring(a, method="text", encoding="UTF-16")
3827
3828 self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
3829 result)
3830
3832 tostring = self.etree.tostring
3833 Element = self.etree.Element
3834 SubElement = self.etree.SubElement
3835
3836 a = Element('a')
3837 a.text = _str('Søk på nettetA')
3838 a.tail = "tail"
3839 b = SubElement(a, 'b')
3840 b.text = "B"
3841 b.tail = _str('Søk på nettetB')
3842 c = SubElement(a, 'c')
3843 c.text = "C"
3844
3845 self.assertRaises(UnicodeEncodeError,
3846 tostring, a, method="text")
3847
3848 self.assertEqual(
3849 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
3850 tostring(a, encoding="UTF-8", method="text"))
3851
3853 tounicode = self.etree.tounicode
3854 Element = self.etree.Element
3855 SubElement = self.etree.SubElement
3856
3857 a = Element('a')
3858 b = SubElement(a, 'b')
3859 c = SubElement(a, 'c')
3860
3861 self.assertTrue(isinstance(tounicode(a), _unicode))
3862 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
3863 canonicalize(tounicode(a)))
3864
3866 tounicode = self.etree.tounicode
3867 Element = self.etree.Element
3868 SubElement = self.etree.SubElement
3869
3870 a = Element('a')
3871 b = SubElement(a, 'b')
3872 c = SubElement(a, 'c')
3873 d = SubElement(c, 'd')
3874 self.assertTrue(isinstance(tounicode(b), _unicode))
3875 self.assertTrue(isinstance(tounicode(c), _unicode))
3876 self.assertEqual(_bytes('<b></b>'),
3877 canonicalize(tounicode(b)))
3878 self.assertEqual(_bytes('<c><d></d></c>'),
3879 canonicalize(tounicode(c)))
3880
3884
3886 tounicode = self.etree.tounicode
3887 Element = self.etree.Element
3888 SubElement = self.etree.SubElement
3889
3890 a = Element('a')
3891 b = SubElement(a, 'b')
3892 c = SubElement(a, 'c')
3893 d = SubElement(c, 'd')
3894 b.tail = 'Foo'
3895
3896 self.assertTrue(isinstance(tounicode(b), _unicode))
3897 self.assertTrue(tounicode(b) == '<b/>Foo' or
3898 tounicode(b) == '<b />Foo')
3899
3901 tounicode = self.etree.tounicode
3902 Element = self.etree.Element
3903 SubElement = self.etree.SubElement
3904
3905 a = Element('a')
3906 b = SubElement(a, 'b')
3907 c = SubElement(a, 'c')
3908
3909 result = tounicode(a)
3910 self.assertEqual(result, "<a><b/><c/></a>")
3911
3912 result = tounicode(a, pretty_print=False)
3913 self.assertEqual(result, "<a><b/><c/></a>")
3914
3915 result = tounicode(a, pretty_print=True)
3916 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
3917
3919 tostring = self.etree.tostring
3920 Element = self.etree.Element
3921 SubElement = self.etree.SubElement
3922
3923 a = Element('a')
3924 b = SubElement(a, 'b')
3925 c = SubElement(a, 'c')
3926
3927 self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode))
3928 self.assertEqual(_bytes('<a><b></b><c></c></a>'),
3929 canonicalize(tostring(a, encoding=_unicode)))
3930
3932 tostring = self.etree.tostring
3933 Element = self.etree.Element
3934 SubElement = self.etree.SubElement
3935
3936 a = Element('a')
3937 b = SubElement(a, 'b')
3938 c = SubElement(a, 'c')
3939 d = SubElement(c, 'd')
3940 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
3941 self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
3942 self.assertEqual(_bytes('<b></b>'),
3943 canonicalize(tostring(b, encoding=_unicode)))
3944 self.assertEqual(_bytes('<c><d></d></c>'),
3945 canonicalize(tostring(c, encoding=_unicode)))
3946
3948 tostring = self.etree.tostring
3949 self.assertRaises(TypeError, self.etree.tostring,
3950 None, encoding=_unicode)
3951
3953 tostring = self.etree.tostring
3954 Element = self.etree.Element
3955 SubElement = self.etree.SubElement
3956
3957 a = Element('a')
3958 b = SubElement(a, 'b')
3959 c = SubElement(a, 'c')
3960 d = SubElement(c, 'd')
3961 b.tail = 'Foo'
3962
3963 self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
3964 self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or
3965 tostring(b, encoding=_unicode) == '<b />Foo')
3966
3968 tostring = self.etree.tostring
3969 Element = self.etree.Element
3970 SubElement = self.etree.SubElement
3971
3972 a = Element('a')
3973 b = SubElement(a, 'b')
3974 c = SubElement(a, 'c')
3975
3976 result = tostring(a, encoding=_unicode)
3977 self.assertEqual(result, "<a><b/><c/></a>")
3978
3979 result = tostring(a, encoding=_unicode, pretty_print=False)
3980 self.assertEqual(result, "<a><b/><c/></a>")
3981
3982 result = tostring(a, encoding=_unicode, pretty_print=True)
3983 self.assertEqual(result, "<a>\n <b/>\n <c/>\n</a>\n")
3984
3986 root = etree.Element('parent')
3987 etree.SubElement(root, 'child')
3988
3989 self.assertEqual(len(root), 1)
3990 self.assertEqual(root[0].tag, 'child')
3991
3992 # in PyPy, GC used to kill the Python proxy instance without cleanup
3993 gc.collect()
3994 self.assertEqual(len(root), 1)
3995 self.assertEqual(root[0].tag, 'child')
3996
4000
4001 el1 = SubEl()
4002 el2 = SubEl()
4003 self.assertEqual('SubEl', el1.tag)
4004 self.assertEqual('SubEl', el2.tag)
4005 el1.other = el2
4006 el2.other = el1
4007
4008 del el1, el2
4009 gc.collect()
4010 # not really testing anything here, but it shouldn't crash
4011
4013 root = etree.Element('parent')
4014 c1 = etree.SubElement(root, 'child1')
4015 c2 = etree.SubElement(root, 'child2')
4016
4017 root.remove(c1)
4018 root.remove(c2)
4019 c1.addnext(c2)
4020 del c1
4021 # trigger deallocation attempt of c1
4022 c2.getprevious()
4023 # make sure it wasn't deallocated
4024 self.assertEqual('child1', c2.getprevious().tag)
4025
4027 root = etree.Element('parent')
4028 c1 = etree.SubElement(root, 'child1')
4029 c2 = etree.SubElement(root, 'child2')
4030
4031 root.remove(c1)
4032 root.remove(c2)
4033 c1.addnext(c2)
4034 c1.tail = 'abc'
4035 c2.tail = 'xyz'
4036 del c1
4037 # trigger deallocation attempt of c1
4038 c2.getprevious()
4039 # make sure it wasn't deallocated
4040 self.assertEqual('child1', c2.getprevious().tag)
4041 self.assertEqual('abc', c2.getprevious().tail)
4042
4043 # helper methods
4044
4046 """Write out element for comparison.
4047 """
4048 ElementTree = self.etree.ElementTree
4049 f = BytesIO()
4050 tree = ElementTree(element=element)
4051 tree.write(f, encoding=encoding, compression=compression)
4052 data = f.getvalue()
4053 if compression:
4054 data = zlib.decompress(data)
4055 return canonicalize(data)
4056
4060 filename = fileInTestDir('test_broken.xml')
4061 root = etree.XML(_bytes('''\
4062 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
4063 <xi:include href="%s" parse="text"/>
4064 </doc>
4065 ''' % path2url(filename)))
4066 old_text = root.text
4067 content = read_file(filename)
4068 old_tail = root[0].tail
4069
4070 self.include( etree.ElementTree(root) )
4071 self.assertEqual(old_text + content + old_tail,
4072 root.text)
4073
4075 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
4076 self.assertNotEqual(
4077 'a',
4078 tree.getroot()[1].tag)
4079 # process xincludes
4080 self.include( tree )
4081 # check whether we find it replaced with included data
4082 self.assertEqual(
4083 'a',
4084 tree.getroot()[1].tag)
4085
4087 class res(etree.Resolver):
4088 include_text = read_file(fileInTestDir('test.xml'))
4089 called = {}
4090 def resolve(self, url, id, context):
4091 if url.endswith(".dtd"):
4092 self.called["dtd"] = True
4093 return self.resolve_filename(
4094 fileInTestDir('test.dtd'), context)
4095 elif url.endswith("test_xinclude.xml"):
4096 self.called["input"] = True
4097 return None # delegate to default resolver
4098 else:
4099 self.called["include"] = True
4100 return self.resolve_string(self.include_text, context)
4101
4102 res_instance = res()
4103 parser = etree.XMLParser(load_dtd = True)
4104 parser.resolvers.add(res_instance)
4105
4106 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4107 parser = parser)
4108
4109 self.include(tree)
4110
4111 called = list(res_instance.called.items())
4112 called.sort()
4113 self.assertEqual(
4114 [("dtd", True), ("include", True), ("input", True)],
4115 called)
4116
4118 data = textwrap.dedent('''
4119 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
4120 <foo/>
4121 <xi:include href="./test.xml" />
4122 </doc>
4123 ''')
4124
4125 class Resolver(etree.Resolver):
4126 called = {}
4127
4128 def resolve(self, url, id, context):
4129 if url.endswith("test_xinclude.xml"):
4130 assert not self.called.get("input")
4131 self.called["input"] = True
4132 return None # delegate to default resolver
4133 elif url.endswith('/test5.xml'):
4134 assert not self.called.get("DONE")
4135 self.called["DONE"] = True
4136 return self.resolve_string('<DONE/>', context)
4137 else:
4138 _, filename = url.rsplit('/', 1)
4139 assert not self.called.get(filename)
4140 self.called[filename] = True
4141 next_data = data.replace(
4142 'test.xml', 'test%d.xml' % len(self.called))
4143 return self.resolve_string(next_data, context)
4144
4145 res_instance = Resolver()
4146 parser = etree.XMLParser(load_dtd=True)
4147 parser.resolvers.add(res_instance)
4148
4149 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
4150 parser=parser)
4151
4152 self.include(tree)
4153
4154 called = list(res_instance.called.items())
4155 called.sort()
4156 self.assertEqual(
4157 [("DONE", True), ("input", True), ("test.xml", True),
4158 ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)],
4159 called)
4160
4165
4171
4175 tree = self.parse(_bytes('<a><b/></a>'))
4176 f = BytesIO()
4177 tree.write_c14n(f)
4178 s = f.getvalue()
4179 self.assertEqual(_bytes('<a><b></b></a>'),
4180 s)
4181
4183 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4184 f = BytesIO()
4185 tree.write_c14n(f, compression=9)
4186 with closing(gzip.GzipFile(fileobj=BytesIO(f.getvalue()))) as gzfile:
4187 s = gzfile.read()
4188 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4189 s)
4190
4192 tree = self.parse(_bytes('<a><b/></a>'))
4193 with tmpfile() as filename:
4194 tree.write_c14n(filename)
4195 data = read_file(filename, 'rb')
4196 self.assertEqual(_bytes('<a><b></b></a>'),
4197 data)
4198
4200 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4201 with tmpfile() as filename:
4202 tree.write_c14n(filename, compression=9)
4203 with closing(gzip.open(filename, 'rb')) as f:
4204 data = f.read()
4205 self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
4206 data)
4207
4209 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4210 f = BytesIO()
4211 tree.write_c14n(f)
4212 s = f.getvalue()
4213 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4214 s)
4215 f = BytesIO()
4216 tree.write_c14n(f, with_comments=True)
4217 s = f.getvalue()
4218 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4219 s)
4220 f = BytesIO()
4221 tree.write_c14n(f, with_comments=False)
4222 s = f.getvalue()
4223 self.assertEqual(_bytes('<a><b></b></a>'),
4224 s)
4225
4227 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4228 s = etree.tostring(tree, method='c14n')
4229 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4230 s)
4231 s = etree.tostring(tree, method='c14n', with_comments=True)
4232 self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
4233 s)
4234 s = etree.tostring(tree, method='c14n', with_comments=False)
4235 self.assertEqual(_bytes('<a><b></b></a>'),
4236 s)
4237
4239 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
4240 s = etree.tostring(tree.getroot(), method='c14n')
4241 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
4242 s)
4243 s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
4244 self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
4245 s)
4246 s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
4247 self.assertEqual(_bytes('<a><b></b></a>'),
4248 s)
4249
4251 tree = self.parse(_bytes(
4252 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4253 f = BytesIO()
4254 tree.write_c14n(f)
4255 s = f.getvalue()
4256 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4257 s)
4258 f = BytesIO()
4259 tree.write_c14n(f, exclusive=False)
4260 s = f.getvalue()
4261 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4262 s)
4263 f = BytesIO()
4264 tree.write_c14n(f, exclusive=True)
4265 s = f.getvalue()
4266 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4267 s)
4268
4269 f = BytesIO()
4270 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
4271 s = f.getvalue()
4272 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
4273 s)
4274
4276 tree = self.parse(_bytes(
4277 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4278 s = etree.tostring(tree, method='c14n')
4279 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4280 s)
4281 s = etree.tostring(tree, method='c14n', exclusive=False)
4282 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4283 s)
4284 s = etree.tostring(tree, method='c14n', exclusive=True)
4285 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4286 s)
4287
4288 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4289 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
4290 s)
4291
4293 tree = self.parse(_bytes(
4294 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4295 s = etree.tostring(tree.getroot(), method='c14n')
4296 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4297 s)
4298 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
4299 self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4300 s)
4301 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
4302 self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
4303 s)
4304
4305 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
4306 self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4307 s)
4308 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
4309 self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
4310 s)
4311
4312 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
4313 self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
4314 s)
4315
4317 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
4318 tree = self.parse(_bytes(
4319 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
4320
4321 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
4322 self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
4323 s)
4324
4328 tree = self.parse(_bytes('<a><b/></a>'))
4329 f = BytesIO()
4330 tree.write(f)
4331 s = f.getvalue()
4332 self.assertEqual(_bytes('<a><b/></a>'),
4333 s)
4334
4336 tree = self.parse(_bytes('<a><b/></a>'))
4337 f = BytesIO()
4338 tree.write(f, doctype='HUHU')
4339 s = f.getvalue()
4340 self.assertEqual(_bytes('HUHU\n<a><b/></a>'),
4341 s)
4342
4344 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4345 f = BytesIO()
4346 tree.write(f, compression=9)
4347 with closing(gzip.GzipFile(fileobj=BytesIO(f.getvalue()))) as gzfile:
4348 s = gzfile.read()
4349 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4350 s)
4351
4353 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4354 f = BytesIO()
4355 tree.write(f, compression=9, doctype='<!DOCTYPE a>')
4356 with closing(gzip.GzipFile(fileobj=BytesIO(f.getvalue()))) as gzfile:
4357 s = gzfile.read()
4358 self.assertEqual(_bytes('<!DOCTYPE a>\n<a>'+'<b/>'*200+'</a>'),
4359 s)
4360
4362 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4363 f = BytesIO()
4364 tree.write(f, compression=0)
4365 s0 = f.getvalue()
4366
4367 f = BytesIO()
4368 tree.write(f)
4369 self.assertEqual(f.getvalue(), s0)
4370
4371 f = BytesIO()
4372 tree.write(f, compression=1)
4373 s = f.getvalue()
4374 self.assertTrue(len(s) <= len(s0))
4375 with closing(gzip.GzipFile(fileobj=BytesIO(s))) as gzfile:
4376 s1 = gzfile.read()
4377
4378 f = BytesIO()
4379 tree.write(f, compression=9)
4380 s = f.getvalue()
4381 self.assertTrue(len(s) <= len(s0))
4382 with closing(gzip.GzipFile(fileobj=BytesIO(s))) as gzfile:
4383 s9 = gzfile.read()
4384
4385 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4386 s0)
4387 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4388 s1)
4389 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4390 s9)
4391
4393 tree = self.parse(_bytes('<a><b/></a>'))
4394 with tmpfile() as filename:
4395 tree.write(filename)
4396 data = read_file(filename, 'rb')
4397 self.assertEqual(_bytes('<a><b/></a>'),
4398 data)
4399
4401 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4402 with tmpfile() as filename:
4403 tree.write(filename, compression=9)
4404 with closing(gzip.open(filename, 'rb')) as f:
4405 data = f.read()
4406 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4407 data)
4408
4410 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
4411 with tmpfile() as filename:
4412 tree.write(filename, compression=9)
4413 data = etree.tostring(etree.parse(filename))
4414 self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
4415 data)
4416
4425
4428 etree = etree
4429
4431 parse = self.etree.parse
4432 f = BytesIO('<a><b></c></b></a>')
4433 self.etree.clear_error_log()
4434 try:
4435 parse(f)
4436 logs = None
4437 except SyntaxError:
4438 e = sys.exc_info()[1]
4439 logs = e.error_log
4440 f.close()
4441 self.assertTrue([ log for log in logs
4442 if 'mismatch' in log.message ])
4443 self.assertTrue([ log for log in logs
4444 if 'PARSER' in log.domain_name])
4445 self.assertTrue([ log for log in logs
4446 if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
4447 self.assertTrue([ log for log in logs
4448 if 1 == log.line ])
4449 self.assertTrue([ log for log in logs
4450 if 15 == log.column ])
4451
4462
4463 self.etree.use_global_python_log(Logger())
4464 f = BytesIO('<a><b></c></b></a>')
4465 try:
4466 parse(f)
4467 except SyntaxError:
4468 pass
4469 f.close()
4470
4471 self.assertTrue([ message for message in messages
4472 if 'mismatch' in message ])
4473 self.assertTrue([ message for message in messages
4474 if ':PARSER:' in message])
4475 self.assertTrue([ message for message in messages
4476 if ':ERR_TAG_NAME_MISMATCH:' in message ])
4477 self.assertTrue([ message for message in messages
4478 if ':1:15:' in message ])
4479
4494 def close(self):
4495 return 'close()'
4496
4497 parser = self.etree.XMLPullParser(target=Target())
4498 events = parser.read_events()
4499
4500 parser.feed('<root><element>')
4501 self.assertFalse(list(events))
4502 self.assertFalse(list(events))
4503 parser.feed('</element><child>')
4504 self.assertEqual([('end', 'end(element)')], list(events))
4505 parser.feed('</child>')
4506 self.assertEqual([('end', 'end(child)')], list(events))
4507 parser.feed('</root>')
4508 self.assertEqual([('end', 'end(root)')], list(events))
4509 self.assertFalse(list(events))
4510 self.assertEqual('close()', parser.close())
4511
4516 def end(self, tag):
4517 return 'end(%s)' % tag
4518 def close(self):
4519 return 'close()'
4520
4521 parser = self.etree.XMLPullParser(
4522 ['start', 'end'], target=Target())
4523 events = parser.read_events()
4524
4525 parser.feed('<root><element>')
4526 self.assertEqual(
4527 [('start', 'start(root)'), ('start', 'start(element)')],
4528 list(events))
4529 self.assertFalse(list(events))
4530 parser.feed('</element><child>')
4531 self.assertEqual(
4532 [('end', 'end(element)'), ('start', 'start(child)')],
4533 list(events))
4534 parser.feed('</child>')
4535 self.assertEqual(
4536 [('end', 'end(child)')],
4537 list(events))
4538 parser.feed('</root>')
4539 self.assertEqual(
4540 [('end', 'end(root)')],
4541 list(events))
4542 self.assertFalse(list(events))
4543 self.assertEqual('close()', parser.close())
4544
4546 parser = self.etree.XMLPullParser(
4547 ['start', 'end'], target=etree.TreeBuilder())
4548 events = parser.read_events()
4549
4550 parser.feed('<root><element>')
4551 self.assert_event_tags(
4552 events, [('start', 'root'), ('start', 'element')])
4553 self.assertFalse(list(events))
4554 parser.feed('</element><child>')
4555 self.assert_event_tags(
4556 events, [('end', 'element'), ('start', 'child')])
4557 parser.feed('</child>')
4558 self.assert_event_tags(
4559 events, [('end', 'child')])
4560 parser.feed('</root>')
4561 self.assert_event_tags(
4562 events, [('end', 'root')])
4563 self.assertFalse(list(events))
4564 root = parser.close()
4565 self.assertEqual('root', root.tag)
4566
4568 class Target(etree.TreeBuilder):
4569 def end(self, tag):
4570 el = super(Target, self).end(tag)
4571 el.tag += '-huhu'
4572 return el
4573
4574 parser = self.etree.XMLPullParser(
4575 ['start', 'end'], target=Target())
4576 events = parser.read_events()
4577
4578 parser.feed('<root><element>')
4579 self.assert_event_tags(
4580 events, [('start', 'root'), ('start', 'element')])
4581 self.assertFalse(list(events))
4582 parser.feed('</element><child>')
4583 self.assert_event_tags(
4584 events, [('end', 'element-huhu'), ('start', 'child')])
4585 parser.feed('</child>')
4586 self.assert_event_tags(
4587 events, [('end', 'child-huhu')])
4588 parser.feed('</root>')
4589 self.assert_event_tags(
4590 events, [('end', 'root-huhu')])
4591 self.assertFalse(list(events))
4592 root = parser.close()
4593 self.assertEqual('root-huhu', root.tag)
4594
4597 suite = unittest.TestSuite()
4598 suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
4599 suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
4600 suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
4601 suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
4602 suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
4603 suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
4604 suite.addTests([unittest.makeSuite(XMLPullParserTest)])
4605
4606 # add original doctests from ElementTree selftest modules
4607 from . import selftest, selftest2
4608 suite.addTests(doctest.DocTestSuite(selftest))
4609 suite.addTests(doctest.DocTestSuite(selftest2))
4610
4611 # add doctests
4612 suite.addTests(doctest.DocTestSuite(etree))
4613 suite.addTests(
4614 [make_doctest('../../../doc/tutorial.txt')])
4615 suite.addTests(
4616 [make_doctest('../../../doc/api.txt')])
4617 suite.addTests(
4618 [make_doctest('../../../doc/FAQ.txt')])
4619 suite.addTests(
4620 [make_doctest('../../../doc/parsing.txt')])
4621 suite.addTests(
4622 [make_doctest('../../../doc/resolvers.txt')])
4623 return suite
4624
4625
4626 if __name__ == '__main__':
4627 print('to test use test.py %s' % __file__)
4628
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Jan 11 11:29:00 2019 | http://epydoc.sourceforge.net |