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