1 # -*- coding: utf-8 -*-
4 Tests specific to the extended etree API
6 Tests that apply to the general ElementTree API should go into
19 this_dir = os.path.dirname(__file__)
20 if this_dir not in sys.path:
21 sys.path.insert(0, this_dir) # needed for Py3
23 from common_imports import etree, StringIO, BytesIO, HelperTestCase, fileInTestDir, read_file
24 from common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
25 from common_imports import canonicalize, sorted, _str, _bytes
28 print("TESTED VERSION: %s" % etree.__version__)
29 print(" Python: " + repr(sys.version_info))
30 print(" lxml.etree: " + repr(etree.LXML_VERSION))
31 print(" libxml used: " + repr(etree.LIBXML_VERSION))
32 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION))
33 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION))
34 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
43 class ETreeOnlyTestCase(HelperTestCase):
44 """Tests only for etree, not ElementTree"""
47 def test_version(self):
48 self.assert_(isinstance(etree.__version__, _unicode))
49 self.assert_(isinstance(etree.LXML_VERSION, tuple))
50 self.assertEqual(len(etree.LXML_VERSION), 4)
51 self.assert_(isinstance(etree.LXML_VERSION[0], int))
52 self.assert_(isinstance(etree.LXML_VERSION[1], int))
53 self.assert_(isinstance(etree.LXML_VERSION[2], int))
54 self.assert_(isinstance(etree.LXML_VERSION[3], int))
55 self.assert_(etree.__version__.startswith(
56 str(etree.LXML_VERSION[0])))
59 if hasattr(self.etree, '__pyx_capi__'):
60 # newer Pyrex compatible C-API
61 self.assert_(isinstance(self.etree.__pyx_capi__, dict))
62 self.assert_(len(self.etree.__pyx_capi__) > 0)
64 # older C-API mechanism
65 self.assert_(hasattr(self.etree, '_import_c_api'))
67 def test_element_names(self):
68 Element = self.etree.Element
70 self.assertEquals(el.tag, 'name')
71 el = Element('{}name')
72 self.assertEquals(el.tag, 'name')
74 def test_element_name_empty(self):
75 Element = self.etree.Element
77 self.assertRaises(ValueError, Element, '{}')
78 self.assertRaises(ValueError, setattr, el, 'tag', '{}')
80 self.assertRaises(ValueError, Element, '{test}')
81 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
83 def test_element_name_colon(self):
84 Element = self.etree.Element
85 self.assertRaises(ValueError, Element, 'p:name')
86 self.assertRaises(ValueError, Element, '{test}p:name')
89 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
91 def test_element_name_quote(self):
92 Element = self.etree.Element
93 self.assertRaises(ValueError, Element, "p'name")
94 self.assertRaises(ValueError, Element, 'p"name')
96 self.assertRaises(ValueError, Element, "{test}p'name")
97 self.assertRaises(ValueError, Element, '{test}p"name')
100 self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
101 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
103 def test_element_name_space(self):
104 Element = self.etree.Element
105 self.assertRaises(ValueError, Element, ' name ')
106 self.assertRaises(ValueError, Element, 'na me')
107 self.assertRaises(ValueError, Element, '{test} name')
110 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
112 def test_subelement_name_empty(self):
113 Element = self.etree.Element
114 SubElement = self.etree.SubElement
117 self.assertRaises(ValueError, SubElement, el, '{}')
118 self.assertRaises(ValueError, SubElement, el, '{test}')
120 def test_subelement_name_colon(self):
121 Element = self.etree.Element
122 SubElement = self.etree.SubElement
125 self.assertRaises(ValueError, SubElement, el, 'p:name')
126 self.assertRaises(ValueError, SubElement, el, '{test}p:name')
128 def test_subelement_name_quote(self):
129 Element = self.etree.Element
130 SubElement = self.etree.SubElement
133 self.assertRaises(ValueError, SubElement, el, "p'name")
134 self.assertRaises(ValueError, SubElement, el, "{test}p'name")
136 self.assertRaises(ValueError, SubElement, el, 'p"name')
137 self.assertRaises(ValueError, SubElement, el, '{test}p"name')
139 def test_subelement_name_space(self):
140 Element = self.etree.Element
141 SubElement = self.etree.SubElement
144 self.assertRaises(ValueError, SubElement, el, ' name ')
145 self.assertRaises(ValueError, SubElement, el, 'na me')
146 self.assertRaises(ValueError, SubElement, el, '{test} name')
148 def test_subelement_attribute_invalid(self):
149 Element = self.etree.Element
150 SubElement = self.etree.SubElement
153 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'})
154 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'})
155 self.assertEquals(0, len(el))
157 def test_qname_empty(self):
158 QName = self.etree.QName
159 self.assertRaises(ValueError, QName, '')
160 self.assertRaises(ValueError, QName, 'test', '')
162 def test_qname_colon(self):
163 QName = self.etree.QName
164 self.assertRaises(ValueError, QName, 'p:name')
165 self.assertRaises(ValueError, QName, 'test', 'p:name')
167 def test_qname_space(self):
168 QName = self.etree.QName
169 self.assertRaises(ValueError, QName, ' name ')
170 self.assertRaises(ValueError, QName, 'na me')
171 self.assertRaises(ValueError, QName, 'test', ' name')
173 def test_qname_namespace_localname(self):
174 # ET doesn't have namespace/localname properties on QNames
175 QName = self.etree.QName
176 namespace, localname = 'http://myns', 'a'
177 qname = QName(namespace, localname)
178 self.assertEquals(namespace, qname.namespace)
179 self.assertEquals(localname, qname.localname)
181 def test_qname_element(self):
182 # ET doesn't have namespace/localname properties on QNames
183 QName = self.etree.QName
184 qname1 = QName('http://myns', 'a')
185 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
188 self.assertEquals(a.tag, qname1.text)
189 self.assertEquals(qname1.text, qname2.text)
190 self.assertEquals(qname1, qname2)
192 def test_qname_text_resolve(self):
193 # ET doesn't resove QNames as text values
195 qname = etree.QName('http://myns', 'a')
196 a = etree.Element(qname, nsmap={'p' : 'http://myns'})
199 self.assertEquals("p:a", a.text)
201 def test_nsmap_prefix_invalid(self):
203 self.assertRaises(ValueError,
204 etree.Element, "root", nsmap={'"' : 'testns'})
205 self.assertRaises(ValueError,
206 etree.Element, "root", nsmap={'&' : 'testns'})
207 self.assertRaises(ValueError,
208 etree.Element, "root", nsmap={'a:b' : 'testns'})
210 def test_attribute_has_key(self):
211 # ET in Py 3.x has no "attrib.has_key()" method
214 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
216 True, root.attrib.has_key('bar'))
218 False, root.attrib.has_key('baz'))
220 False, root.attrib.has_key('hah'))
223 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
225 def test_attribute_set(self):
226 Element = self.etree.Element
227 root = Element("root")
228 root.set("attr", "TEST")
229 self.assertEquals("TEST", root.get("attr"))
231 def test_attribute_set_invalid(self):
232 # ElementTree accepts arbitrary attribute values
233 # lxml.etree allows only strings
234 Element = self.etree.Element
235 root = Element("root")
236 self.assertRaises(TypeError, root.set, "newattr", 5)
237 self.assertRaises(TypeError, root.set, "newattr", None)
239 def test_strip_attributes(self):
241 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>')
244 self.etree.strip_attributes(root, 'a')
245 self.assertEquals(_bytes('<test b="10" c="20"><x b="2"></x></test>'),
246 self._writeElement(root))
249 self.etree.strip_attributes(root, 'b', 'c')
250 self.assertEquals(_bytes('<test a="5"><x a="4"></x></test>'),
251 self._writeElement(root))
253 def test_strip_attributes_ns(self):
255 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>')
258 self.etree.strip_attributes(root, 'a')
260 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'),
261 self._writeElement(root))
264 self.etree.strip_attributes(root, '{http://test/ns}a', 'c')
266 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'),
267 self._writeElement(root))
270 self.etree.strip_attributes(root, '{http://test/ns}*')
272 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'),
273 self._writeElement(root))
275 def test_strip_elements(self):
277 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
280 self.etree.strip_elements(root, 'a')
281 self.assertEquals(_bytes('<test><x></x></test>'),
282 self._writeElement(root))
285 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
286 self.assertEquals(_bytes('<test><a></a><x><a></a></x></test>'),
287 self._writeElement(root))
290 self.etree.strip_elements(root, 'c')
291 self.assertEquals(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
292 self._writeElement(root))
294 def test_strip_elements_ns(self):
296 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>')
299 self.etree.strip_elements(root, 'a')
300 self.assertEquals(_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>'),
301 self._writeElement(root))
304 self.etree.strip_elements(root, '{urn:a}b', 'c')
305 self.assertEquals(_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>'),
306 self._writeElement(root))
309 self.etree.strip_elements(root, '{urn:a}*', 'c')
310 self.assertEquals(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
311 self._writeElement(root))
314 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
315 self.assertEquals(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
316 self._writeElement(root))
318 def test_strip_tags(self):
320 xml = _bytes('<test>TEST<a>A<b>B<c/>CT</b>BT</a>AT<x>X<a>A<b/>BT<c/>CT</a>AT</x>XT</test>')
323 self.etree.strip_tags(root, 'a')
324 self.assertEquals(_bytes('<test>TESTA<b>B<c></c>CT</b>BTAT<x>XA<b></b>BT<c></c>CTAT</x>XT</test>'),
325 self._writeElement(root))
328 self.etree.strip_tags(root, 'b', 'c', 'X', 'Y', 'Z')
329 self.assertEquals(_bytes('<test>TEST<a>ABCTBT</a>AT<x>X<a>ABTCT</a>AT</x>XT</test>'),
330 self._writeElement(root))
333 self.etree.strip_tags(root, 'c')
334 self.assertEquals(_bytes('<test>TEST<a>A<b>BCT</b>BT</a>AT<x>X<a>A<b></b>BTCT</a>AT</x>XT</test>'),
335 self._writeElement(root))
337 def test_strip_tags_pi_comment(self):
339 PI = self.etree.ProcessingInstruction
340 Comment = self.etree.Comment
341 xml = _bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT<?PI2?></test>\n<!--comment3-->\n<?PI1?>')
344 self.etree.strip_tags(root, PI)
345 self.assertEquals(_bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT</test>\n<!--comment3-->\n<?PI1?>'),
346 self._writeElement(root))
349 self.etree.strip_tags(root, Comment)
350 self.assertEquals(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT<?PI2?></test>\n<!--comment3-->\n<?PI1?>'),
351 self._writeElement(root))
354 self.etree.strip_tags(root, PI, Comment)
355 self.assertEquals(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT</test>\n<!--comment3-->\n<?PI1?>'),
356 self._writeElement(root))
359 self.etree.strip_tags(root, Comment, PI)
360 self.assertEquals(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT</test>\n<!--comment3-->\n<?PI1?>'),
361 self._writeElement(root))
363 def test_strip_tags_pi_comment_all(self):
365 ElementTree = self.etree.ElementTree
366 PI = self.etree.ProcessingInstruction
367 Comment = self.etree.Comment
368 xml = _bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT<?PI2?></test>\n<!--comment3-->\n<?PI1?>')
371 self.etree.strip_tags(ElementTree(root), PI)
372 self.assertEquals(_bytes('<!--comment1-->\n<test>TEST<!--comment2-->XT</test>\n<!--comment3-->'),
373 self._writeElement(root))
376 self.etree.strip_tags(ElementTree(root), Comment)
377 self.assertEquals(_bytes('<?PI1?>\n<test>TESTXT<?PI2?></test>\n<?PI1?>'),
378 self._writeElement(root))
381 self.etree.strip_tags(ElementTree(root), PI, Comment)
382 self.assertEquals(_bytes('<test>TESTXT</test>'),
383 self._writeElement(root))
386 self.etree.strip_tags(ElementTree(root), Comment, PI)
387 self.assertEquals(_bytes('<test>TESTXT</test>'),
388 self._writeElement(root))
390 def test_strip_tags_doc_style(self):
395 I like <strong>sheep</strong>.
397 I like lots of <strong>sheep</strong>.
399 Click <a href="http://www.sheep.com">here</a> for <a href="http://www.sheep.com">those</a> sheep.
406 self.etree.strip_tags(root, 'a')
407 self.assertEquals(re.sub(_bytes('</?a[^>]*>'), _bytes(''), xml).replace(_bytes('<br/>'), _bytes('<br></br>')),
408 self._writeElement(root))
411 self.etree.strip_tags(root, 'a', 'br')
412 self.assertEquals(re.sub(_bytes('</?a[^>]*>'), _bytes(''),
413 re.sub(_bytes('<br[^>]*>'), _bytes(''), xml)),
414 self._writeElement(root))
416 def test_strip_tags_ns(self):
418 xml = _bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"/>CT</b>BT</n:a>AT<x>X<a>A<b xmlns="urn:a"/>BT<c xmlns="urn:x"/>CT</a>AT</x>XT</test>')
421 self.etree.strip_tags(root, 'a')
422 self.assertEquals(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>CT</b>BT</n:a>AT<x>XA<b xmlns="urn:a"></b>BT<c xmlns="urn:x"></c>CTAT</x>XT</test>'),
423 self._writeElement(root))
426 self.etree.strip_tags(root, '{urn:a}b', 'c')
427 self.assertEquals(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>CT</b>BT</n:a>AT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
428 self._writeElement(root))
431 self.etree.strip_tags(root, '{urn:a}*', 'c')
432 self.assertEquals(_bytes('<test>TESTA<b>B<c xmlns="urn:c"></c>CT</b>BTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
433 self._writeElement(root))
435 def test_strip_tags_and_remove(self):
437 HTML = self.etree.HTML
438 root = HTML(_bytes('<div><h1>title</h1> <b>foo</b> <p>boo</p></div>'))[0][0]
439 self.assertEquals(_bytes('<div><h1>title</h1> <b>foo</b> <p>boo</p></div>'),
440 self.etree.tostring(root))
441 self.etree.strip_tags(root, 'b')
442 self.assertEquals(_bytes('<div><h1>title</h1> foo <p>boo</p></div>'),
443 self.etree.tostring(root))
445 self.assertEquals(_bytes('<div><p>boo</p></div>'),
446 self.etree.tostring(root))
449 # lxml.etree separates target and text
450 Element = self.etree.Element
451 SubElement = self.etree.SubElement
452 ProcessingInstruction = self.etree.ProcessingInstruction
455 a.append(ProcessingInstruction('foo', 'some more text'))
456 self.assertEquals(a[0].target, 'foo')
457 self.assertEquals(a[0].text, 'some more text')
459 def test_pi_parse(self):
461 root = XML(_bytes("<test><?mypi my test ?></test>"))
462 self.assertEquals(root[0].target, "mypi")
463 self.assertEquals(root[0].text, "my test ")
465 def test_pi_pseudo_attributes_get(self):
467 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
468 self.assertEquals(root[0].target, "mypi")
469 self.assertEquals(root[0].get('my'), "1")
470 self.assertEquals(root[0].get('test'), " abc ")
471 self.assertEquals(root[0].get('quotes'), "' '")
472 self.assertEquals(root[0].get('only'), None)
473 self.assertEquals(root[0].get('names'), None)
474 self.assertEquals(root[0].get('nope'), None)
476 def test_pi_pseudo_attributes_attrib(self):
478 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
479 self.assertEquals(root[0].target, "mypi")
480 self.assertEquals(root[0].attrib['my'], "1")
481 self.assertEquals(root[0].attrib['test'], " abc ")
482 self.assertEquals(root[0].attrib['quotes'], "' '")
483 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
484 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
485 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
487 def test_deepcopy_pi(self):
488 # previously caused a crash
489 ProcessingInstruction = self.etree.ProcessingInstruction
491 a = ProcessingInstruction("PI", "ONE")
495 self.assertEquals('ONE', a.text)
496 self.assertEquals('ANOTHER', b.text)
498 def test_deepcopy_elementtree_pi(self):
500 tostring = self.etree.tostring
501 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->"))
502 tree1 = self.etree.ElementTree(root)
503 self.assertEquals(_bytes("<?mypi my test ?><test/><!--comment -->"),
506 tree2 = copy.deepcopy(tree1)
507 self.assertEquals(_bytes("<?mypi my test ?><test/><!--comment -->"),
510 root2 = copy.deepcopy(tree1.getroot())
511 self.assertEquals(_bytes("<test/>"),
514 def test_deepcopy_elementtree_dtd(self):
516 tostring = self.etree.tostring
517 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
519 tree1 = self.etree.ElementTree(root)
520 self.assertEquals(xml, tostring(tree1))
522 tree2 = copy.deepcopy(tree1)
523 self.assertEquals(xml, tostring(tree2))
525 root2 = copy.deepcopy(tree1.getroot())
526 self.assertEquals(_bytes("<test/>"),
529 def test_attribute_set(self):
530 # ElementTree accepts arbitrary attribute values
531 # lxml.etree allows only strings
532 Element = self.etree.Element
534 root = Element("root")
535 root.set("attr", "TEST")
536 self.assertEquals("TEST", root.get("attr"))
537 self.assertRaises(TypeError, root.set, "newattr", 5)
539 def test_parse_remove_comments(self):
540 fromstring = self.etree.fromstring
541 tostring = self.etree.tostring
542 XMLParser = self.etree.XMLParser
544 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
545 parser = XMLParser(remove_comments=True)
546 root = fromstring(xml, parser)
548 _bytes('<a><b><c/></b></a>'),
551 def test_parse_remove_pis(self):
552 parse = self.etree.parse
553 tostring = self.etree.tostring
554 XMLParser = self.etree.XMLParser
556 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
564 parser = XMLParser(remove_pis=True)
565 tree = parse(f, parser)
567 _bytes('<a><b><c/></b></a>'),
570 def test_parse_parser_type_error(self):
571 # ET raises IOError only
572 parse = self.etree.parse
573 self.assertRaises(TypeError, parse, 'notthere.xml', object())
575 def test_iterparse_tree_comments(self):
576 # ET removes comments
577 iterparse = self.etree.iterparse
578 tostring = self.etree.tostring
580 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
581 events = list(iterparse(f))
583 self.assertEquals(3, len(events))
585 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
588 def test_iterparse_comments(self):
589 # ET removes comments
590 iterparse = self.etree.iterparse
591 tostring = self.etree.tostring
594 if event == 'comment':
599 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
600 events = list(iterparse(f, events=('end', 'comment')))
602 self.assertEquals(6, len(events))
603 self.assertEquals(['A', ' B ', 'c', 'b', 'C', 'a'],
604 [ name(*item) for item in events ])
606 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
609 def test_iterparse_pis(self):
611 iterparse = self.etree.iterparse
612 tostring = self.etree.tostring
613 ElementTree = self.etree.ElementTree
617 return (el.target, el.text)
621 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
622 events = list(iterparse(f, events=('end', 'pi')))
624 self.assertEquals(8, len(events))
625 self.assertEquals([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
626 ('pid','d'), 'a', ('pie','e')],
627 [ name(*item) for item in events ])
629 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
630 tostring(ElementTree(root)))
632 def test_iterparse_remove_comments(self):
633 iterparse = self.etree.iterparse
634 tostring = self.etree.tostring
636 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
637 events = list(iterparse(f, remove_comments=True,
638 events=('end', 'comment')))
640 self.assertEquals(3, len(events))
641 self.assertEquals(['c', 'b', 'a'],
642 [ el.tag for (event, el) in events ])
644 _bytes('<a><b><c/></b></a>'),
647 def test_iterparse_broken(self):
648 iterparse = self.etree.iterparse
649 f = BytesIO('<a><b><c/></a>')
650 # ET raises ExpatError, lxml raises XMLSyntaxError
651 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
653 def test_iterparse_strip(self):
654 iterparse = self.etree.iterparse
656 <a> \n \n <b> b test </b> \n
658 \n\t <c> \n </c> </a> \n """)
659 iterator = iterparse(f, remove_blank_text=True)
660 text = [ (element.text, element.tail)
661 for event, element in iterator ]
663 [(" b test ", None), (" \n ", None), (None, None)],
666 def test_iterparse_tag(self):
667 iterparse = self.etree.iterparse
668 f = BytesIO('<a><b><d/></b><c/></a>')
670 iterator = iterparse(f, tag="b", events=('start', 'end'))
671 events = list(iterator)
674 [('start', root[0]), ('end', root[0])],
677 def test_iterparse_tag_all(self):
678 iterparse = self.etree.iterparse
679 f = BytesIO('<a><b><d/></b><c/></a>')
681 iterator = iterparse(f, tag="*", events=('start', 'end'))
682 events = list(iterator)
687 def test_iterparse_tag_ns(self):
688 iterparse = self.etree.iterparse
689 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
691 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
692 events = list(iterator)
695 [('start', root[0]), ('end', root[0])],
698 def test_iterparse_tag_ns_all(self):
699 iterparse = self.etree.iterparse
700 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
702 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
703 events = list(iterator)
708 def test_iterparse_encoding_error(self):
709 text = _str('Søk på nettet')
710 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
711 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
712 ).encode('iso-8859-1')
714 self.assertRaises(self.etree.ParseError,
715 list, self.etree.iterparse(BytesIO(xml_latin1)))
717 def test_iterparse_encoding_8bit_override(self):
718 text = _str('Søk på nettet', encoding="UTF-8")
719 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
720 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
721 ).encode('iso-8859-1')
723 iterator = self.etree.iterparse(BytesIO(xml_latin1),
724 encoding="iso-8859-1")
725 self.assertEquals(1, len(list(iterator)))
728 self.assertEquals(a.text, text)
730 def test_iterparse_keep_cdata(self):
731 tostring = self.etree.tostring
732 f = BytesIO('<root><![CDATA[test]]></root>')
733 context = self.etree.iterparse(f, strip_cdata=False)
734 content = [ el.text for event,el in context ]
736 self.assertEquals(['test'], content)
737 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
738 tostring(context.root))
740 def test_parser_encoding_unknown(self):
742 LookupError, self.etree.XMLParser, encoding="hopefully unknown")
744 def test_parser_encoding(self):
745 self.etree.XMLParser(encoding="ascii")
746 self.etree.XMLParser(encoding="utf-8")
747 self.etree.XMLParser(encoding="iso-8859-1")
749 def test_feed_parser_recover(self):
750 parser = self.etree.XMLParser(recover=True)
752 parser.feed('<?xml version=')
753 parser.feed('"1.0"?><ro')
755 parser.feed('a test="works"')
756 parser.feed('><othertag/></root') # <a> not closed!
759 root = parser.close()
761 self.assertEquals(root.tag, "root")
762 self.assertEquals(len(root), 1)
763 self.assertEquals(root[0].tag, "a")
764 self.assertEquals(root[0].get("test"), "works")
765 self.assertEquals(len(root[0]), 1)
766 self.assertEquals(root[0][0].tag, "othertag")
767 # FIXME: would be nice to get some errors logged ...
768 #self.assert_(len(parser.error_log) > 0, "error log is empty")
770 def test_elementtree_parser_target_type_error(self):
771 assertEquals = self.assertEquals
772 assertFalse = self.assertFalse
775 class Target(object):
776 def start(self, tag, attrib):
777 events.append("start")
779 assertEquals("TAG", tag)
782 assertEquals("TAG", tag)
784 return "DONE" # no Element!
786 parser = self.etree.XMLParser(target=Target())
787 tree = self.etree.ElementTree()
789 self.assertRaises(TypeError,
790 tree.parse, BytesIO("<TAG/>"), parser=parser)
791 self.assertEquals(["start", "end"], events)
793 def test_parser_target_feed_exception(self):
794 # ET doesn't call .close() on errors
796 class Target(object):
797 def start(self, tag, attrib):
798 events.append("start-" + tag)
800 events.append("end-" + tag)
802 raise ValueError("dead and gone")
803 def data(self, data):
804 events.append("data-" + data)
806 events.append("close")
809 parser = self.etree.XMLParser(target=Target())
812 parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
813 done = parser.close()
814 self.fail("error expected, but parsing succeeded")
816 done = 'value error received as expected'
818 self.assertEquals(["start-root", "data-A", "start-a",
819 "data-ca", "end-a", "close"],
822 def test_parser_target_fromstring_exception(self):
823 # ET doesn't call .close() on errors
825 class Target(object):
826 def start(self, tag, attrib):
827 events.append("start-" + tag)
829 events.append("end-" + tag)
831 raise ValueError("dead and gone")
832 def data(self, data):
833 events.append("data-" + data)
835 events.append("close")
838 parser = self.etree.XMLParser(target=Target())
841 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
843 self.fail("error expected, but parsing succeeded")
845 done = 'value error received as expected'
847 self.assertEquals(["start-root", "data-A", "start-a",
848 "data-ca", "end-a", "close"],
851 def test_parser_target_comment(self):
853 class Target(object):
854 def start(self, tag, attrib):
855 events.append("start-" + tag)
857 events.append("end-" + tag)
858 def data(self, data):
859 events.append("data-" + data)
860 def comment(self, text):
861 events.append("comment-" + text)
865 parser = self.etree.XMLParser(target=Target())
867 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
868 done = parser.close()
870 self.assertEquals("DONE", done)
871 self.assertEquals(["comment-a", "start-root", "data-A", "comment-b",
872 "start-sub", "end-sub", "comment-c", "data-B",
873 "end-root", "comment-d"],
876 def test_parser_target_pi(self):
878 class Target(object):
879 def start(self, tag, attrib):
880 events.append("start-" + tag)
882 events.append("end-" + tag)
883 def data(self, data):
884 events.append("data-" + data)
885 def pi(self, target, data):
886 events.append("pi-" + target + "-" + data)
890 parser = self.etree.XMLParser(target=Target())
892 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
893 done = parser.close()
895 self.assertEquals("DONE", done)
896 self.assertEquals(["pi-test-a", "start-root", "data-A", "pi-test-b",
897 "data-B", "end-root", "pi-test-c"],
900 def test_parser_target_cdata(self):
902 class Target(object):
903 def start(self, tag, attrib):
904 events.append("start-" + tag)
906 events.append("end-" + tag)
907 def data(self, data):
908 events.append("data-" + data)
912 parser = self.etree.XMLParser(target=Target(),
915 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
916 done = parser.close()
918 self.assertEquals("DONE", done)
919 self.assertEquals(["start-root", "data-A", "start-a",
920 "data-ca", "end-a", "data-B", "end-root"],
923 def test_parser_target_recover(self):
925 class Target(object):
926 def start(self, tag, attrib):
927 events.append("start-" + tag)
929 events.append("end-" + tag)
930 def data(self, data):
931 events.append("data-" + data)
933 events.append("close")
936 parser = self.etree.XMLParser(target=Target(),
939 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
940 done = parser.close()
942 self.assertEquals("DONE", done)
943 self.assertEquals(["start-root", "data-A", "start-a",
944 "data-ca", "end-a", "data-B",
945 "end-root", "close"],
948 def test_iterwalk_tag(self):
949 iterwalk = self.etree.iterwalk
950 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
952 iterator = iterwalk(root, tag="b", events=('start', 'end'))
953 events = list(iterator)
955 [('start', root[0]), ('end', root[0])],
958 def test_iterwalk_tag_all(self):
959 iterwalk = self.etree.iterwalk
960 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
962 iterator = iterwalk(root, tag="*", events=('start', 'end'))
963 events = list(iterator)
968 def test_iterwalk(self):
969 iterwalk = self.etree.iterwalk
970 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
972 events = list(iterwalk(root))
974 [('end', root[0]), ('end', root[1]), ('end', root)],
977 def test_iterwalk_start(self):
978 iterwalk = self.etree.iterwalk
979 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
981 iterator = iterwalk(root, events=('start',))
982 events = list(iterator)
984 [('start', root), ('start', root[0]), ('start', root[1])],
987 def test_iterwalk_start_end(self):
988 iterwalk = self.etree.iterwalk
989 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
991 iterator = iterwalk(root, events=('start','end'))
992 events = list(iterator)
994 [('start', root), ('start', root[0]), ('end', root[0]),
995 ('start', root[1]), ('end', root[1]), ('end', root)],
998 def test_iterwalk_clear(self):
999 iterwalk = self.etree.iterwalk
1000 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1002 iterator = iterwalk(root)
1003 for event, elem in iterator:
1006 self.assertEquals(0,
1009 def test_iterwalk_attrib_ns(self):
1010 iterwalk = self.etree.iterwalk
1011 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
1013 attr_name = '{testns}bla'
1015 iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
1016 for event, elem in iterator:
1017 events.append(event)
1018 if event == 'start':
1019 if elem.tag != '{ns1}a':
1020 elem.set(attr_name, 'value')
1023 ['start-ns', 'start', 'start', 'start-ns', 'start',
1024 'end', 'end-ns', 'end', 'end', 'end-ns'],
1029 root.get(attr_name))
1032 root[0].get(attr_name))
1034 def test_iterwalk_getiterator(self):
1035 iterwalk = self.etree.iterwalk
1036 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1039 for event, elem in iterwalk(root):
1040 counts.append(len(list(elem.getiterator())))
1045 def test_resolve_string_dtd(self):
1046 parse = self.etree.parse
1047 parser = self.etree.XMLParser(dtd_validation=True)
1048 assertEqual = self.assertEqual
1049 test_url = _str("__nosuch.dtd")
1051 class MyResolver(self.etree.Resolver):
1052 def resolve(self, url, id, context):
1053 assertEqual(url, test_url)
1054 return self.resolve_string(
1055 _str('''<!ENTITY myentity "%s">
1056 <!ELEMENT doc ANY>''') % url, context)
1058 parser.resolvers.add(MyResolver())
1060 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1061 tree = parse(StringIO(xml), parser)
1062 root = tree.getroot()
1063 self.assertEquals(root.text, test_url)
1065 def test_resolve_bytes_dtd(self):
1066 parse = self.etree.parse
1067 parser = self.etree.XMLParser(dtd_validation=True)
1068 assertEqual = self.assertEqual
1069 test_url = _str("__nosuch.dtd")
1071 class MyResolver(self.etree.Resolver):
1072 def resolve(self, url, id, context):
1073 assertEqual(url, test_url)
1074 return self.resolve_string(
1075 (_str('''<!ENTITY myentity "%s">
1076 <!ELEMENT doc ANY>''') % url).encode('utf-8'),
1079 parser.resolvers.add(MyResolver())
1081 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1082 tree = parse(StringIO(xml), parser)
1083 root = tree.getroot()
1084 self.assertEquals(root.text, test_url)
1086 def test_resolve_filelike_dtd(self):
1087 parse = self.etree.parse
1088 parser = self.etree.XMLParser(dtd_validation=True)
1089 assertEqual = self.assertEqual
1090 test_url = _str("__nosuch.dtd")
1092 class MyResolver(self.etree.Resolver):
1093 def resolve(self, url, id, context):
1094 assertEqual(url, test_url)
1095 return self.resolve_file(
1097 _str('''<!ENTITY myentity "%s">
1098 <!ELEMENT doc ANY>''') % url), context)
1100 parser.resolvers.add(MyResolver())
1102 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1103 tree = parse(StringIO(xml), parser)
1104 root = tree.getroot()
1105 self.assertEquals(root.text, test_url)
1107 def test_resolve_filename_dtd(self):
1108 parse = self.etree.parse
1109 parser = self.etree.XMLParser(attribute_defaults=True)
1110 assertEqual = self.assertEqual
1111 test_url = _str("__nosuch.dtd")
1113 class MyResolver(self.etree.Resolver):
1114 def resolve(self, url, id, context):
1115 assertEqual(url, test_url)
1116 return self.resolve_filename(
1117 fileInTestDir('test.dtd'), context)
1119 parser.resolvers.add(MyResolver())
1121 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1122 tree = parse(StringIO(xml), parser)
1123 root = tree.getroot()
1125 root.attrib, {'default': 'valueA'})
1127 root[0].attrib, {'default': 'valueB'})
1129 def test_resolve_filename_dtd_relative(self):
1130 parse = self.etree.parse
1131 parser = self.etree.XMLParser(attribute_defaults=True)
1132 assertEqual = self.assertEqual
1133 test_url = _str("__nosuch.dtd")
1135 class MyResolver(self.etree.Resolver):
1136 def resolve(self, url, id, context):
1137 assertEqual(url, fileInTestDir(test_url))
1138 return self.resolve_filename(
1139 fileInTestDir('test.dtd'), context)
1141 parser.resolvers.add(MyResolver())
1143 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1144 tree = parse(StringIO(xml), parser,
1145 base_url=fileInTestDir('__test.xml'))
1146 root = tree.getroot()
1148 root.attrib, {'default': 'valueA'})
1150 root[0].attrib, {'default': 'valueB'})
1152 def test_resolve_file_dtd(self):
1153 parse = self.etree.parse
1154 parser = self.etree.XMLParser(attribute_defaults=True)
1155 assertEqual = self.assertEqual
1156 test_url = _str("__nosuch.dtd")
1158 class MyResolver(self.etree.Resolver):
1159 def resolve(self, url, id, context):
1160 assertEqual(url, test_url)
1161 return self.resolve_file(
1162 open(fileInTestDir('test.dtd'), 'rb'), context)
1164 parser.resolvers.add(MyResolver())
1166 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1167 tree = parse(StringIO(xml), parser)
1168 root = tree.getroot()
1170 root.attrib, {'default': 'valueA'})
1172 root[0].attrib, {'default': 'valueB'})
1174 def test_resolve_empty(self):
1175 parse = self.etree.parse
1176 parser = self.etree.XMLParser(load_dtd=True)
1177 assertEqual = self.assertEqual
1178 test_url = _str("__nosuch.dtd")
1180 class check(object):
1183 class MyResolver(self.etree.Resolver):
1184 def resolve(self, url, id, context):
1185 assertEqual(url, test_url)
1186 check.resolved = True
1187 return self.resolve_empty(context)
1189 parser.resolvers.add(MyResolver())
1191 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1192 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
1193 self.assert_(check.resolved)
1195 def test_resolve_error(self):
1196 parse = self.etree.parse
1197 parser = self.etree.XMLParser(dtd_validation=True)
1199 class _LocalException(Exception):
1202 class MyResolver(self.etree.Resolver):
1203 def resolve(self, url, id, context):
1204 raise _LocalException
1206 parser.resolvers.add(MyResolver())
1208 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
1209 self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
1211 if etree.LIBXML_VERSION > (2,6,20):
1212 def test_entity_parse(self):
1213 parse = self.etree.parse
1214 tostring = self.etree.tostring
1215 parser = self.etree.XMLParser(resolve_entities=False)
1216 Entity = self.etree.Entity
1218 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>')
1219 tree = parse(BytesIO(xml), parser)
1220 root = tree.getroot()
1221 self.assertEquals(root[0].tag, Entity)
1222 self.assertEquals(root[0].text, "&myentity;")
1223 self.assertEquals(root[0].tail, None)
1224 self.assertEquals(root[0].name, "myentity")
1226 self.assertEquals(_bytes('<doc>&myentity;</doc>'),
1229 def test_entity_restructure(self):
1230 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]>
1234 <child3> </child3>
1237 parser = self.etree.XMLParser(resolve_entities=False)
1238 root = etree.fromstring(xml, parser)
1239 self.assertEquals([ el.tag for el in root ],
1240 ['child1', 'child2', 'child3'])
1243 self.assertEquals([ el.tag for el in root ],
1244 ['child3', 'child2'])
1245 self.assertEquals(root[0][0].text, ' ')
1246 self.assertEquals(root[0][0].name, 'nbsp')
1248 def test_entity_append(self):
1249 Entity = self.etree.Entity
1250 Element = self.etree.Element
1251 tostring = self.etree.tostring
1253 root = Element("root")
1254 root.append( Entity("test") )
1256 self.assertEquals(root[0].tag, Entity)
1257 self.assertEquals(root[0].text, "&test;")
1258 self.assertEquals(root[0].tail, None)
1259 self.assertEquals(root[0].name, "test")
1261 self.assertEquals(_bytes('<root>&test;</root>'),
1264 def test_entity_values(self):
1265 Entity = self.etree.Entity
1266 self.assertEquals(Entity("test").text, '&test;')
1267 self.assertEquals(Entity("#17683").text, '䔓')
1268 self.assertEquals(Entity("#x1768").text, 'ᝨ')
1269 self.assertEquals(Entity("#x98AF").text, '颯')
1271 def test_entity_error(self):
1272 Entity = self.etree.Entity
1273 self.assertRaises(ValueError, Entity, 'a b c')
1274 self.assertRaises(ValueError, Entity, 'a,b')
1275 self.assertRaises(ValueError, Entity, 'a\0b')
1276 self.assertRaises(ValueError, Entity, '#abc')
1277 self.assertRaises(ValueError, Entity, '#xxyz')
1279 def test_cdata(self):
1280 CDATA = self.etree.CDATA
1281 Element = self.etree.Element
1282 tostring = self.etree.tostring
1284 root = Element("root")
1285 root.text = CDATA('test')
1287 self.assertEquals('test',
1289 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
1292 def test_cdata_type(self):
1293 CDATA = self.etree.CDATA
1294 Element = self.etree.Element
1295 root = Element("root")
1297 root.text = CDATA("test")
1298 self.assertEquals('test', root.text)
1300 root.text = CDATA(_str("test"))
1301 self.assertEquals('test', root.text)
1303 self.assertRaises(TypeError, CDATA, 1)
1305 def test_cdata_errors(self):
1306 CDATA = self.etree.CDATA
1307 Element = self.etree.Element
1309 root = Element("root")
1310 cdata = CDATA('test')
1312 self.assertRaises(TypeError,
1313 setattr, root, 'tail', cdata)
1314 self.assertRaises(TypeError,
1315 root.set, 'attr', cdata)
1316 self.assertRaises(TypeError,
1317 operator.setitem, root.attrib, 'attr', cdata)
1319 def test_cdata_parser(self):
1320 tostring = self.etree.tostring
1321 parser = self.etree.XMLParser(strip_cdata=False)
1322 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1324 self.assertEquals('test', root.text)
1325 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
1328 def test_cdata_xpath(self):
1329 tostring = self.etree.tostring
1330 parser = self.etree.XMLParser(strip_cdata=False)
1331 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1332 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
1335 self.assertEquals(['test'], root.xpath('//text()'))
1337 # TypeError in etree, AssertionError in ElementTree;
1338 def test_setitem_assert(self):
1339 Element = self.etree.Element
1340 SubElement = self.etree.SubElement
1343 b = SubElement(a, 'b')
1345 self.assertRaises(TypeError,
1346 a.__setitem__, 0, 'foo')
1348 def test_append_error(self):
1349 Element = self.etree.Element
1350 root = Element('root')
1351 # raises AssertionError in ElementTree
1352 self.assertRaises(TypeError, root.append, None)
1353 self.assertRaises(TypeError, root.extend, [None])
1354 self.assertRaises(TypeError, root.extend, [Element('one'), None])
1355 self.assertEquals('one', root[0].tag)
1357 def test_addnext(self):
1358 Element = self.etree.Element
1359 SubElement = self.etree.SubElement
1360 root = Element('root')
1361 SubElement(root, 'a')
1362 SubElement(root, 'b')
1364 self.assertEquals(['a', 'b'],
1365 [c.tag for c in root])
1366 root[1].addnext(root[0])
1367 self.assertEquals(['b', 'a'],
1368 [c.tag for c in root])
1370 def test_addprevious(self):
1371 Element = self.etree.Element
1372 SubElement = self.etree.SubElement
1373 root = Element('root')
1374 SubElement(root, 'a')
1375 SubElement(root, 'b')
1377 self.assertEquals(['a', 'b'],
1378 [c.tag for c in root])
1379 root[0].addprevious(root[1])
1380 self.assertEquals(['b', 'a'],
1381 [c.tag for c in root])
1383 def test_addnext_root(self):
1384 Element = self.etree.Element
1387 self.assertRaises(TypeError, a.addnext, b)
1389 def test_addnext_root(self):
1390 Element = self.etree.Element
1393 self.assertRaises(TypeError, a.addnext, b)
1395 def test_addprevious_pi(self):
1396 Element = self.etree.Element
1397 SubElement = self.etree.SubElement
1399 root = Element('root')
1400 SubElement(root, 'a')
1401 pi = PI('TARGET', 'TEXT')
1404 self.assertEquals(_bytes('<root><a></a></root>'),
1405 self._writeElement(root))
1406 root[0].addprevious(pi)
1407 self.assertEquals(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
1408 self._writeElement(root))
1410 def test_addprevious_root_pi(self):
1411 Element = self.etree.Element
1413 root = Element('root')
1414 pi = PI('TARGET', 'TEXT')
1417 self.assertEquals(_bytes('<root></root>'),
1418 self._writeElement(root))
1419 root.addprevious(pi)
1420 self.assertEquals(_bytes('<?TARGET TEXT?>\n<root></root>'),
1421 self._writeElement(root))
1423 def test_addnext_pi(self):
1424 Element = self.etree.Element
1425 SubElement = self.etree.SubElement
1427 root = Element('root')
1428 SubElement(root, 'a')
1429 pi = PI('TARGET', 'TEXT')
1432 self.assertEquals(_bytes('<root><a></a></root>'),
1433 self._writeElement(root))
1435 self.assertEquals(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
1436 self._writeElement(root))
1438 def test_addnext_root_pi(self):
1439 Element = self.etree.Element
1441 root = Element('root')
1442 pi = PI('TARGET', 'TEXT')
1445 self.assertEquals(_bytes('<root></root>'),
1446 self._writeElement(root))
1448 self.assertEquals(_bytes('<root></root>\n<?TARGET TEXT?>'),
1449 self._writeElement(root))
1451 def test_addnext_comment(self):
1452 Element = self.etree.Element
1453 SubElement = self.etree.SubElement
1454 Comment = self.etree.Comment
1455 root = Element('root')
1456 SubElement(root, 'a')
1457 comment = Comment('TEXT ')
1458 comment.tail = "TAIL"
1460 self.assertEquals(_bytes('<root><a></a></root>'),
1461 self._writeElement(root))
1462 root[0].addnext(comment)
1463 self.assertEquals(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
1464 self._writeElement(root))
1466 def test_addnext_root_comment(self):
1467 Element = self.etree.Element
1468 Comment = self.etree.Comment
1469 root = Element('root')
1470 comment = Comment('TEXT ')
1471 comment.tail = "TAIL"
1473 self.assertEquals(_bytes('<root></root>'),
1474 self._writeElement(root))
1475 root.addnext(comment)
1476 self.assertEquals(_bytes('<root></root>\n<!--TEXT -->'),
1477 self._writeElement(root))
1479 def test_addprevious_comment(self):
1480 Element = self.etree.Element
1481 SubElement = self.etree.SubElement
1482 Comment = self.etree.Comment
1483 root = Element('root')
1484 SubElement(root, 'a')
1485 comment = Comment('TEXT ')
1486 comment.tail = "TAIL"
1488 self.assertEquals(_bytes('<root><a></a></root>'),
1489 self._writeElement(root))
1490 root[0].addprevious(comment)
1491 self.assertEquals(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
1492 self._writeElement(root))
1494 def test_addprevious_root_comment(self):
1495 Element = self.etree.Element
1496 Comment = self.etree.Comment
1497 root = Element('root')
1498 comment = Comment('TEXT ')
1499 comment.tail = "TAIL"
1501 self.assertEquals(_bytes('<root></root>'),
1502 self._writeElement(root))
1503 root.addprevious(comment)
1504 self.assertEquals(_bytes('<!--TEXT -->\n<root></root>'),
1505 self._writeElement(root))
1507 # ET's Elements have items() and key(), but not values()
1508 def test_attribute_values(self):
1509 XML = self.etree.XML
1511 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
1512 values = root.values()
1514 self.assertEquals(['Alpha', 'Beta', 'Gamma'], values)
1516 # gives error in ElementTree
1517 def test_comment_empty(self):
1518 Element = self.etree.Element
1519 Comment = self.etree.Comment
1524 _bytes('<a><!----></a>'),
1525 self._writeElement(a))
1527 # ElementTree ignores comments
1528 def test_comment_parse_empty(self):
1529 ElementTree = self.etree.ElementTree
1530 tostring = self.etree.tostring
1532 xml = _bytes('<a><b/><!----><c/></a>')
1534 doc = ElementTree(file=f)
1543 # ElementTree ignores comments
1544 def test_comment_no_proxy_yet(self):
1545 ElementTree = self.etree.ElementTree
1547 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
1548 doc = ElementTree(file=f)
1554 # does not raise an exception in ElementTree
1555 def test_comment_immutable(self):
1556 Element = self.etree.Element
1557 Comment = self.etree.Comment
1560 el = Element('myel')
1562 self.assertRaises(TypeError, c.append, el)
1563 self.assertRaises(TypeError, c.insert, 0, el)
1564 self.assertRaises(TypeError, c.set, "myattr", "test")
1566 # test passing 'None' to dump
1567 def test_dump_none(self):
1568 self.assertRaises(TypeError, self.etree.dump, None)
1570 def test_prefix(self):
1571 ElementTree = self.etree.ElementTree
1573 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
1574 doc = ElementTree(file=f)
1583 def test_prefix_default_ns(self):
1584 ElementTree = self.etree.ElementTree
1586 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
1587 doc = ElementTree(file=f)
1596 def test_getparent(self):
1597 Element = self.etree.Element
1598 SubElement = self.etree.SubElement
1601 b = SubElement(a, 'b')
1602 c = SubElement(a, 'c')
1603 d = SubElement(b, 'd')
1617 def test_iterchildren(self):
1618 XML = self.etree.XML
1620 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
1622 for el in root.iterchildren():
1623 result.append(el.tag)
1624 self.assertEquals(['one', 'two', 'three'], result)
1626 def test_iterchildren_reversed(self):
1627 XML = self.etree.XML
1629 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
1631 for el in root.iterchildren(reversed=True):
1632 result.append(el.tag)
1633 self.assertEquals(['three', 'two', 'one'], result)
1635 def test_iterchildren_tag(self):
1636 XML = self.etree.XML
1638 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
1640 for el in root.iterchildren(tag='two'):
1641 result.append(el.text)
1642 self.assertEquals(['Two', 'Bla'], result)
1644 def test_iterchildren_tag_reversed(self):
1645 XML = self.etree.XML
1647 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
1649 for el in root.iterchildren(reversed=True, tag='two'):
1650 result.append(el.text)
1651 self.assertEquals(['Bla', 'Two'], result)
1653 def test_iterancestors(self):
1654 Element = self.etree.Element
1655 SubElement = self.etree.SubElement
1658 b = SubElement(a, 'b')
1659 c = SubElement(a, 'c')
1660 d = SubElement(b, 'd')
1663 list(a.iterancestors()))
1666 list(b.iterancestors()))
1669 list(c.iterancestors()))
1672 list(d.iterancestors()))
1674 def test_iterancestors_tag(self):
1675 Element = self.etree.Element
1676 SubElement = self.etree.SubElement
1679 b = SubElement(a, 'b')
1680 c = SubElement(a, 'c')
1681 d = SubElement(b, 'd')
1684 list(d.iterancestors(tag='a')))
1686 def test_iterdescendants(self):
1687 Element = self.etree.Element
1688 SubElement = self.etree.SubElement
1691 b = SubElement(a, 'b')
1692 c = SubElement(a, 'c')
1693 d = SubElement(b, 'd')
1694 e = SubElement(c, 'e')
1698 list(a.iterdescendants()))
1701 list(d.iterdescendants()))
1703 def test_iterdescendants_tag(self):
1704 Element = self.etree.Element
1705 SubElement = self.etree.SubElement
1708 b = SubElement(a, 'b')
1709 c = SubElement(a, 'c')
1710 d = SubElement(b, 'd')
1711 e = SubElement(c, 'e')
1715 list(a.iterdescendants('a')))
1716 a2 = SubElement(e, 'a')
1719 list(a.iterdescendants('a')))
1722 list(c.iterdescendants('a')))
1724 def test_getroottree(self):
1725 Element = self.etree.Element
1726 SubElement = self.etree.SubElement
1729 b = SubElement(a, 'b')
1730 c = SubElement(a, 'c')
1731 d = SubElement(b, 'd')
1734 a.getroottree().getroot())
1737 b.getroottree().getroot())
1740 d.getroottree().getroot())
1742 def test_getnext(self):
1743 Element = self.etree.Element
1744 SubElement = self.etree.SubElement
1747 b = SubElement(a, 'b')
1748 c = SubElement(a, 'c')
1759 def test_getprevious(self):
1760 Element = self.etree.Element
1761 SubElement = self.etree.SubElement
1764 b = SubElement(a, 'b')
1765 c = SubElement(a, 'c')
1766 d = SubElement(b, 'd')
1777 def test_itersiblings(self):
1778 Element = self.etree.Element
1779 SubElement = self.etree.SubElement
1782 b = SubElement(a, 'b')
1783 c = SubElement(a, 'c')
1784 d = SubElement(b, 'd')
1787 list(a.itersiblings()))
1790 list(b.itersiblings()))
1793 list(c.itersiblings()))
1796 list(c.itersiblings(preceding=True)))
1799 list(b.itersiblings(preceding=True)))
1801 def test_itersiblings_tag(self):
1802 Element = self.etree.Element
1803 SubElement = self.etree.SubElement
1806 b = SubElement(a, 'b')
1807 c = SubElement(a, 'c')
1808 d = SubElement(b, 'd')
1811 list(a.itersiblings(tag='XXX')))
1814 list(b.itersiblings(tag='c')))
1817 list(c.itersiblings(preceding=True, tag='b')))
1820 list(c.itersiblings(preceding=True, tag='c')))
1822 def test_parseid(self):
1823 parseid = self.etree.parseid
1824 XML = self.etree.XML
1825 xml_text = _bytes('''
1826 <!DOCTYPE document [
1827 <!ELEMENT document (h1,p)*>
1828 <!ELEMENT h1 (#PCDATA)>
1829 <!ATTLIST h1 myid ID #REQUIRED>
1830 <!ELEMENT p (#PCDATA)>
1831 <!ATTLIST p someid ID #REQUIRED>
1834 <h1 myid="chapter1">...</h1>
1835 <p id="note1" class="note">...</p>
1836 <p>Regular paragraph.</p>
1837 <p xml:id="xmlid">XML:ID paragraph.</p>
1838 <p someid="warn1" class="warning">...</p>
1842 tree, dic = parseid(BytesIO(xml_text))
1843 root = tree.getroot()
1844 root2 = XML(xml_text)
1845 self.assertEquals(self._writeElement(root),
1846 self._writeElement(root2))
1848 "chapter1" : root[0],
1852 self.assert_("chapter1" in dic)
1853 self.assert_("warn1" in dic)
1854 self.assert_("xmlid" in dic)
1855 self._checkIDDict(dic, expected)
1857 def test_XMLDTDID(self):
1858 XMLDTDID = self.etree.XMLDTDID
1859 XML = self.etree.XML
1860 xml_text = _bytes('''
1861 <!DOCTYPE document [
1862 <!ELEMENT document (h1,p)*>
1863 <!ELEMENT h1 (#PCDATA)>
1864 <!ATTLIST h1 myid ID #REQUIRED>
1865 <!ELEMENT p (#PCDATA)>
1866 <!ATTLIST p someid ID #REQUIRED>
1869 <h1 myid="chapter1">...</h1>
1870 <p id="note1" class="note">...</p>
1871 <p>Regular paragraph.</p>
1872 <p xml:id="xmlid">XML:ID paragraph.</p>
1873 <p someid="warn1" class="warning">...</p>
1877 root, dic = XMLDTDID(xml_text)
1878 root2 = XML(xml_text)
1879 self.assertEquals(self._writeElement(root),
1880 self._writeElement(root2))
1882 "chapter1" : root[0],
1886 self.assert_("chapter1" in dic)
1887 self.assert_("warn1" in dic)
1888 self.assert_("xmlid" in dic)
1889 self._checkIDDict(dic, expected)
1891 def test_XMLDTDID_empty(self):
1892 XMLDTDID = self.etree.XMLDTDID
1893 XML = self.etree.XML
1894 xml_text = _bytes('''
1896 <h1 myid="chapter1">...</h1>
1897 <p id="note1" class="note">...</p>
1898 <p>Regular paragraph.</p>
1899 <p someid="warn1" class="warning">...</p>
1903 root, dic = XMLDTDID(xml_text)
1904 root2 = XML(xml_text)
1905 self.assertEquals(self._writeElement(root),
1906 self._writeElement(root2))
1908 self._checkIDDict(dic, expected)
1910 def _checkIDDict(self, dic, expected):
1911 self.assertEquals(len(dic),
1913 self.assertEquals(sorted(dic.items()),
1914 sorted(expected.items()))
1915 if sys.version_info < (3,):
1916 self.assertEquals(sorted(dic.iteritems()),
1917 sorted(expected.iteritems()))
1918 self.assertEquals(sorted(dic.keys()),
1919 sorted(expected.keys()))
1920 if sys.version_info < (3,):
1921 self.assertEquals(sorted(dic.iterkeys()),
1922 sorted(expected.iterkeys()))
1923 if sys.version_info < (3,):
1924 self.assertEquals(sorted(dic.values()),
1925 sorted(expected.values()))
1926 self.assertEquals(sorted(dic.itervalues()),
1927 sorted(expected.itervalues()))
1929 def test_namespaces(self):
1932 r = {'foo': 'http://ns.infrae.com/foo'}
1933 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
1938 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
1939 self._writeElement(e))
1941 def test_namespaces_default(self):
1944 r = {None: 'http://ns.infrae.com/foo'}
1945 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
1950 '{http://ns.infrae.com/foo}bar',
1953 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
1954 self._writeElement(e))
1956 def test_namespaces_default_and_attr(self):
1959 r = {None: 'http://ns.infrae.com/foo',
1960 'hoi': 'http://ns.infrae.com/hoi'}
1961 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
1962 e.set('{http://ns.infrae.com/hoi}test', 'value')
1964 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
1965 self._writeElement(e))
1967 def test_namespaces_elementtree(self):
1969 r = {None: 'http://ns.infrae.com/foo',
1970 'hoi': 'http://ns.infrae.com/hoi'}
1971 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
1972 tree = etree.ElementTree(element=e)
1973 etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
1975 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
1976 self._writeElement(e))
1978 def test_namespaces_default_copy_element(self):
1981 r = {None: 'http://ns.infrae.com/foo'}
1982 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
1983 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
1994 '{http://ns.infrae.com/foo}bar',
1997 '{http://ns.infrae.com/foo}bar',
2000 def test_namespaces_copy_element(self):
2003 r = {None: 'http://ns.infrae.com/BAR'}
2004 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
2005 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2012 self.assertNotEquals(
2016 '{http://ns.infrae.com/BAR}bar',
2019 '{http://ns.infrae.com/foo}bar',
2022 def test_namespaces_reuse_after_move(self):
2023 ns_href = "http://a.b.c"
2024 one = self.etree.fromstring(
2025 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2028 two = self.etree.fromstring(
2029 _bytes('<root xmlns:ns="%s"/>' % ns_href))
2031 del one # make sure the source document is deallocated
2033 self.assertEquals('{%s}baz' % ns_href, baz.tag)
2035 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
2036 self.etree.tostring(two))
2038 def test_namespace_cleanup(self):
2039 xml = _bytes('<foo xmlns="F" xmlns:x="x"><bar xmlns:ns="NS" xmlns:b="b" xmlns="B"><ns:baz/></bar></foo>')
2040 root = self.etree.fromstring(xml)
2041 self.assertEquals(xml,
2042 self.etree.tostring(root))
2043 self.etree.cleanup_namespaces(root)
2045 _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
2046 self.etree.tostring(root))
2048 def test_element_nsmap(self):
2051 r = {None: 'http://ns.infrae.com/foo',
2052 'hoi': 'http://ns.infrae.com/hoi'}
2053 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2058 def test_subelement_nsmap(self):
2061 re = {None: 'http://ns.infrae.com/foo',
2062 'hoi': 'http://ns.infrae.com/hoi'}
2063 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
2065 rs = {None: 'http://ns.infrae.com/honk',
2066 'top': 'http://ns.infrae.com/top'}
2067 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
2071 self.assertEquals(re, e.nsmap)
2072 self.assertEquals(r, s.nsmap)
2074 def test_html_prefix_nsmap(self):
2076 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
2077 self.assertEquals({'hha': None}, el.nsmap)
2079 def test_getiterator_filter_namespace(self):
2080 Element = self.etree.Element
2081 SubElement = self.etree.SubElement
2084 b = SubElement(a, '{a}b')
2085 c = SubElement(a, '{a}c')
2086 d = SubElement(b, '{b}d')
2087 e = SubElement(c, '{a}e')
2088 f = SubElement(c, '{b}f')
2092 list(a.getiterator('{a}a')))
2095 list(a.getiterator('{b}a')))
2098 list(a.getiterator('a')))
2101 list(c.getiterator('{b}*')))
2104 list(a.getiterator('{b}*')))
2106 def test_getiterator_filter_entities(self):
2107 Element = self.etree.Element
2108 Entity = self.etree.Entity
2109 SubElement = self.etree.SubElement
2112 b = SubElement(a, 'b')
2113 entity_b = Entity("TEST-b")
2118 list(a.getiterator(Entity)))
2120 entity_a = Entity("TEST-a")
2124 [entity_b, entity_a],
2125 list(a.getiterator(Entity)))
2129 list(b.getiterator(Entity)))
2131 def test_getiterator_filter_element(self):
2132 Element = self.etree.Element
2133 Comment = self.etree.Comment
2135 SubElement = self.etree.SubElement
2138 b = SubElement(a, 'b')
2139 a.append(Comment("test"))
2140 a.append(PI("pi", "content"))
2141 c = SubElement(a, 'c')
2145 list(a.getiterator(Element)))
2147 def test_getiterator_filter_all_comment_pi(self):
2148 # ElementTree iterates over everything here
2149 Element = self.etree.Element
2150 Comment = self.etree.Comment
2152 SubElement = self.etree.SubElement
2155 b = SubElement(a, 'b')
2156 a.append(Comment("test"))
2157 a.append(PI("pi", "content"))
2158 c = SubElement(a, 'c')
2162 list(a.getiterator('*')))
2164 def test_elementtree_find_qname(self):
2165 XML = self.etree.XML
2166 ElementTree = self.etree.ElementTree
2167 QName = self.etree.QName
2168 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
2169 self.assertEquals(tree.find(QName("c")), tree.getroot()[2])
2171 def test_elementtree_findall_qname(self):
2172 XML = self.etree.XML
2173 ElementTree = self.etree.ElementTree
2174 QName = self.etree.QName
2175 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
2176 self.assertEquals(len(list(tree.findall(QName("c")))), 1)
2178 def test_elementtree_findall_ns_qname(self):
2179 XML = self.etree.XML
2180 ElementTree = self.etree.ElementTree
2181 QName = self.etree.QName
2182 tree = ElementTree(XML(
2183 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
2184 self.assertEquals(len(list(tree.findall(QName("b")))), 2)
2185 self.assertEquals(len(list(tree.findall(QName("X", "b")))), 1)
2187 def test_findall_ns(self):
2188 XML = self.etree.XML
2189 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
2190 self.assertEquals(len(root.findall(".//{X}b")), 2)
2191 self.assertEquals(len(root.findall(".//{X}*")), 2)
2192 self.assertEquals(len(root.findall(".//b")), 3)
2194 def test_index(self):
2196 e = etree.Element('foo')
2198 etree.SubElement(e, 'a%s' % i)
2204 3, e.index(e[3], 3))
2206 ValueError, e.index, e[3], 4)
2208 ValueError, e.index, e[3], 0, 2)
2210 ValueError, e.index, e[8], 0, -3)
2212 ValueError, e.index, e[8], -5, -3)
2214 8, e.index(e[8], 0, -1))
2216 8, e.index(e[8], -12, -1))
2218 0, e.index(e[0], -12, -1))
2220 def test_replace(self):
2222 e = etree.Element('foo')
2224 el = etree.SubElement(e, 'a%s' % i)
2225 el.text = "text%d" % i
2226 el.tail = "tail%d" % i
2232 e.replace(e[0], e[1])
2238 child1.text, "text1")
2240 child1.tail, "tail1")
2242 child0.tail, "tail0")
2246 e.replace(e[-1], e[0])
2250 child1.text, "text1")
2252 child1.tail, "tail1")
2256 def test_replace_new(self):
2258 e = etree.Element('foo')
2260 etree.SubElement(e, 'a%s' % i)
2262 new_element = etree.Element("test")
2263 new_element.text = "TESTTEXT"
2264 new_element.tail = "TESTTAIL"
2266 e.replace(e[0], new_element)
2278 def test_setslice_all_empty_reversed(self):
2279 Element = self.etree.Element
2280 SubElement = self.etree.SubElement
2294 def test_setslice_step(self):
2295 Element = self.etree.Element
2296 SubElement = self.etree.SubElement
2299 b = SubElement(a, 'b')
2300 c = SubElement(a, 'c')
2301 d = SubElement(a, 'd')
2302 e = SubElement(a, 'e')
2312 def test_setslice_step_negative(self):
2313 Element = self.etree.Element
2314 SubElement = self.etree.SubElement
2317 b = SubElement(a, 'b')
2318 c = SubElement(a, 'c')
2319 d = SubElement(a, 'd')
2320 e = SubElement(a, 'e')
2330 def test_setslice_step_negative2(self):
2331 Element = self.etree.Element
2332 SubElement = self.etree.SubElement
2335 b = SubElement(a, 'b')
2336 c = SubElement(a, 'c')
2337 d = SubElement(a, 'd')
2338 e = SubElement(a, 'e')
2348 def test_setslice_step_overrun(self):
2349 Element = self.etree.Element
2350 SubElement = self.etree.SubElement
2354 print("slice() not found")
2358 b = SubElement(a, 'b')
2359 c = SubElement(a, 'c')
2360 d = SubElement(a, 'd')
2361 e = SubElement(a, 'e')
2369 operator.setitem, a, slice(1,None,2), [x, y, z])
2375 def test_sourceline_XML(self):
2376 XML = self.etree.XML
2377 root = XML(_bytes('''<?xml version="1.0"?>
2386 [ el.sourceline for el in root.getiterator() ])
2388 def test_sourceline_parse(self):
2389 parse = self.etree.parse
2390 tree = parse(fileInTestDir('include/test_xinclude.xml'))
2394 [ el.sourceline for el in tree.getiterator() ])
2396 def test_sourceline_iterparse_end(self):
2397 iterparse = self.etree.iterparse
2398 lines = [ el.sourceline for (event, el) in
2399 iterparse(fileInTestDir('include/test_xinclude.xml')) ]
2405 def test_sourceline_iterparse_start(self):
2406 iterparse = self.etree.iterparse
2407 lines = [ el.sourceline for (event, el) in
2408 iterparse(fileInTestDir('include/test_xinclude.xml'),
2409 events=("start",)) ]
2415 def test_sourceline_element(self):
2416 Element = self.etree.Element
2417 SubElement = self.etree.SubElement
2418 el = Element("test")
2419 self.assertEquals(None, el.sourceline)
2421 child = SubElement(el, "test")
2422 self.assertEquals(None, el.sourceline)
2423 self.assertEquals(None, child.sourceline)
2425 def test_XML_base_url_docinfo(self):
2427 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2428 docinfo = root.getroottree().docinfo
2429 self.assertEquals(docinfo.URL, "http://no/such/url")
2431 def test_XML_set_base_url_docinfo(self):
2433 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2434 docinfo = root.getroottree().docinfo
2435 self.assertEquals(docinfo.URL, "http://no/such/url")
2436 docinfo.URL = "https://secret/url"
2437 self.assertEquals(docinfo.URL, "https://secret/url")
2439 def test_parse_stringio_base_url(self):
2441 tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
2442 docinfo = tree.docinfo
2443 self.assertEquals(docinfo.URL, "http://no/such/url")
2445 def test_parse_base_url_docinfo(self):
2447 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
2448 base_url="http://no/such/url")
2449 docinfo = tree.docinfo
2450 self.assertEquals(docinfo.URL, "http://no/such/url")
2452 def test_HTML_base_url_docinfo(self):
2454 root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
2455 docinfo = root.getroottree().docinfo
2456 self.assertEquals(docinfo.URL, "http://no/such/url")
2458 def test_docinfo_public(self):
2460 xml_header = '<?xml version="1.0" encoding="ascii"?>'
2461 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
2462 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
2463 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
2465 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
2467 tree = etree.parse(BytesIO(xml))
2468 docinfo = tree.docinfo
2469 self.assertEquals(docinfo.encoding, "ascii")
2470 self.assertEquals(docinfo.xml_version, "1.0")
2471 self.assertEquals(docinfo.public_id, pub_id)
2472 self.assertEquals(docinfo.system_url, sys_id)
2473 self.assertEquals(docinfo.root_name, 'html')
2474 self.assertEquals(docinfo.doctype, doctype_string)
2476 def test_docinfo_system(self):
2478 xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
2480 doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
2481 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
2483 tree = etree.parse(BytesIO(xml))
2484 docinfo = tree.docinfo
2485 self.assertEquals(docinfo.encoding, "UTF-8")
2486 self.assertEquals(docinfo.xml_version, "1.0")
2487 self.assertEquals(docinfo.public_id, None)
2488 self.assertEquals(docinfo.system_url, sys_id)
2489 self.assertEquals(docinfo.root_name, 'html')
2490 self.assertEquals(docinfo.doctype, doctype_string)
2492 def test_docinfo_empty(self):
2494 xml = _bytes('<html><body></body></html>')
2495 tree = etree.parse(BytesIO(xml))
2496 docinfo = tree.docinfo
2497 self.assertEquals(docinfo.encoding, "UTF-8")
2498 self.assertEquals(docinfo.xml_version, "1.0")
2499 self.assertEquals(docinfo.public_id, None)
2500 self.assertEquals(docinfo.system_url, None)
2501 self.assertEquals(docinfo.root_name, 'html')
2502 self.assertEquals(docinfo.doctype, '')
2504 def test_docinfo_name_only(self):
2506 xml = _bytes('<!DOCTYPE root><root></root>')
2507 tree = etree.parse(BytesIO(xml))
2508 docinfo = tree.docinfo
2509 self.assertEquals(docinfo.encoding, "UTF-8")
2510 self.assertEquals(docinfo.xml_version, "1.0")
2511 self.assertEquals(docinfo.public_id, None)
2512 self.assertEquals(docinfo.system_url, None)
2513 self.assertEquals(docinfo.root_name, 'root')
2514 self.assertEquals(docinfo.doctype, '<!DOCTYPE root>')
2516 def test_doctype_name_only_roundtrip(self):
2518 xml = _bytes('<!DOCTYPE root>\n<root/>')
2519 tree = etree.parse(BytesIO(xml))
2520 self.assertEquals(xml, etree.tostring(tree))
2522 def test_doctype_output_override(self):
2524 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
2525 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
2526 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
2528 xml = _bytes('<!DOCTYPE root>\n<root/>')
2529 tree = etree.parse(BytesIO(xml))
2530 self.assertEquals(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
2531 etree.tostring(tree, doctype=doctype_string))
2533 def test_xml_base(self):
2535 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2536 self.assertEquals(root.base, "http://no/such/url")
2538 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
2539 root.base = "https://secret/url"
2540 self.assertEquals(root.base, "https://secret/url")
2542 root.get('{http://www.w3.org/XML/1998/namespace}base'),
2543 "https://secret/url")
2545 def test_xml_base_attribute(self):
2547 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2548 self.assertEquals(root.base, "http://no/such/url")
2550 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
2551 root.set('{http://www.w3.org/XML/1998/namespace}base',
2552 "https://secret/url")
2553 self.assertEquals(root.base, "https://secret/url")
2555 root.get('{http://www.w3.org/XML/1998/namespace}base'),
2556 "https://secret/url")
2558 def test_html_base(self):
2560 root = etree.HTML(_bytes("<html><body></body></html>"),
2561 base_url="http://no/such/url")
2562 self.assertEquals(root.base, "http://no/such/url")
2564 def test_html_base_tag(self):
2566 root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
2567 self.assertEquals(root.base, "http://no/such/url")
2569 def test_parse_fileobject_unicode(self):
2570 # parse from a file object that returns unicode strings
2571 f = LargeFileLikeUnicode()
2572 tree = self.etree.parse(f)
2573 root = tree.getroot()
2574 self.assert_(root.tag.endswith('root'))
2576 def test_dtd_io(self):
2577 # check that DTDs that go in also go back out
2579 <!DOCTYPE test SYSTEM "test.dtd" [
2580 <!ENTITY entity "tasty">
2582 <!ELEMENT a (#PCDATA)>
2584 <test><a>test-test</a></test>\
2586 tree = self.etree.parse(BytesIO(xml))
2587 self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
2588 xml.replace(_bytes(" "), _bytes("")))
2590 def test_byte_zero(self):
2591 Element = self.etree.Element
2594 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
2595 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
2597 self.assertRaises(ValueError, Element, 'ha\0ho')
2599 def test_unicode_byte_zero(self):
2600 Element = self.etree.Element
2603 self.assertRaises(ValueError, setattr, a, "text",
2605 self.assertRaises(ValueError, setattr, a, "tail",
2608 self.assertRaises(ValueError, Element,
2611 def test_byte_invalid(self):
2612 Element = self.etree.Element
2615 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
2616 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
2618 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
2619 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
2621 self.assertRaises(ValueError, Element, 'ha\x07ho')
2622 self.assertRaises(ValueError, Element, 'ha\x02ho')
2624 def test_unicode_byte_invalid(self):
2625 Element = self.etree.Element
2628 self.assertRaises(ValueError, setattr, a, "text",
2630 self.assertRaises(ValueError, setattr, a, "text",
2633 self.assertRaises(ValueError, setattr, a, "tail",
2635 self.assertRaises(ValueError, setattr, a, "tail",
2638 self.assertRaises(ValueError, Element,
2640 self.assertRaises(ValueError, Element,
2643 def test_unicode_byte_invalid_sequence(self):
2644 Element = self.etree.Element
2647 self.assertRaises(ValueError, setattr, a, "text",
2648 _str('ha\u1234\x07ho'))
2649 self.assertRaises(ValueError, setattr, a, "text",
2650 _str('ha\u1234\x02ho'))
2652 self.assertRaises(ValueError, setattr, a, "tail",
2653 _str('ha\u1234\x07ho'))
2654 self.assertRaises(ValueError, setattr, a, "tail",
2655 _str('ha\u1234\x02ho'))
2657 self.assertRaises(ValueError, Element,
2658 _str('ha\u1234\x07ho'))
2659 self.assertRaises(ValueError, Element,
2660 _str('ha\u1234\x02ho'))
2662 def test_encoding_tostring_utf16(self):
2663 # ElementTree fails to serialize this
2664 tostring = self.etree.tostring
2665 Element = self.etree.Element
2666 SubElement = self.etree.SubElement
2669 b = SubElement(a, 'b')
2670 c = SubElement(a, 'c')
2672 result = tostring(a, encoding='UTF-16')
2673 self.assertEquals(_bytes('<a><b></b><c></c></a>'),
2674 canonicalize(result))
2676 def test_tostring_none(self):
2677 # ElementTree raises an AssertionError here
2678 tostring = self.etree.tostring
2679 self.assertRaises(TypeError, self.etree.tostring, None)
2681 def test_tostring_pretty(self):
2682 tostring = self.etree.tostring
2683 Element = self.etree.Element
2684 SubElement = self.etree.SubElement
2687 b = SubElement(a, 'b')
2688 c = SubElement(a, 'c')
2690 result = tostring(a)
2691 self.assertEquals(result, _bytes("<a><b/><c/></a>"))
2693 result = tostring(a, pretty_print=False)
2694 self.assertEquals(result, _bytes("<a><b/><c/></a>"))
2696 result = tostring(a, pretty_print=True)
2697 self.assertEquals(result, _bytes("<a>\n <b/>\n <c/>\n</a>\n"))
2699 def test_tostring_with_tail(self):
2700 tostring = self.etree.tostring
2701 Element = self.etree.Element
2702 SubElement = self.etree.SubElement
2706 b = SubElement(a, 'b')
2708 c = SubElement(a, 'c')
2710 result = tostring(a)
2711 self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
2713 result = tostring(a, with_tail=False)
2714 self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>"))
2716 result = tostring(a, with_tail=True)
2717 self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
2719 def test_standalone(self):
2720 tostring = self.etree.tostring
2721 XML = self.etree.XML
2722 ElementTree = self.etree.ElementTree
2723 Element = self.etree.Element
2725 tree = Element("root").getroottree()
2726 self.assertEquals(None, tree.docinfo.standalone)
2728 tree = XML(_bytes("<root/>")).getroottree()
2729 self.assertEquals(None, tree.docinfo.standalone)
2732 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
2734 self.assertEquals(True, tree.docinfo.standalone)
2737 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
2739 self.assertEquals(False, tree.docinfo.standalone)
2741 def test_tostring_standalone(self):
2742 tostring = self.etree.tostring
2743 XML = self.etree.XML
2744 ElementTree = self.etree.ElementTree
2746 root = XML(_bytes("<root/>"))
2748 tree = ElementTree(root)
2749 self.assertEquals(None, tree.docinfo.standalone)
2751 result = tostring(root, xml_declaration=True, encoding="ASCII")
2752 self.assertEquals(result, _bytes(
2753 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
2755 result = tostring(root, xml_declaration=True, encoding="ASCII",
2757 self.assertEquals(result, _bytes(
2758 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
2760 tree = ElementTree(XML(result))
2761 self.assertEquals(True, tree.docinfo.standalone)
2763 result = tostring(root, xml_declaration=True, encoding="ASCII",
2765 self.assertEquals(result, _bytes(
2766 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
2768 tree = ElementTree(XML(result))
2769 self.assertEquals(False, tree.docinfo.standalone)
2771 def test_tostring_standalone_in_out(self):
2772 tostring = self.etree.tostring
2773 XML = self.etree.XML
2774 ElementTree = self.etree.ElementTree
2777 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
2779 tree = ElementTree(root)
2780 self.assertEquals(True, tree.docinfo.standalone)
2782 result = tostring(root, xml_declaration=True, encoding="ASCII")
2783 self.assertEquals(result, _bytes(
2784 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
2786 result = tostring(root, xml_declaration=True, encoding="ASCII",
2788 self.assertEquals(result, _bytes(
2789 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
2791 def test_tostring_method_text_encoding(self):
2792 tostring = self.etree.tostring
2793 Element = self.etree.Element
2794 SubElement = self.etree.SubElement
2799 b = SubElement(a, 'b')
2801 b.tail = _str("Søk på nettet")
2802 c = SubElement(a, 'c')
2805 result = tostring(a, method="text", encoding="UTF-16")
2807 self.assertEquals(_str('ABSøk på nettetCtail').encode("UTF-16"),
2810 def test_tostring_method_text_unicode(self):
2811 tostring = self.etree.tostring
2812 Element = self.etree.Element
2813 SubElement = self.etree.SubElement
2816 a.text = _str('Søk på nettetA')
2818 b = SubElement(a, 'b')
2820 b.tail = _str('Søk på nettetB')
2821 c = SubElement(a, 'c')
2824 self.assertRaises(UnicodeEncodeError,
2825 tostring, a, method="text")
2828 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
2829 tostring(a, encoding="UTF-8", method="text"))
2831 def test_tounicode(self):
2832 tounicode = self.etree.tounicode
2833 Element = self.etree.Element
2834 SubElement = self.etree.SubElement
2837 b = SubElement(a, 'b')
2838 c = SubElement(a, 'c')
2840 self.assert_(isinstance(tounicode(a), _unicode))
2841 self.assertEquals(_bytes('<a><b></b><c></c></a>'),
2842 canonicalize(tounicode(a)))
2844 def test_tounicode_element(self):
2845 tounicode = self.etree.tounicode
2846 Element = self.etree.Element
2847 SubElement = self.etree.SubElement
2850 b = SubElement(a, 'b')
2851 c = SubElement(a, 'c')
2852 d = SubElement(c, 'd')
2853 self.assert_(isinstance(tounicode(b), _unicode))
2854 self.assert_(isinstance(tounicode(c), _unicode))
2855 self.assertEquals(_bytes('<b></b>'),
2856 canonicalize(tounicode(b)))
2857 self.assertEquals(_bytes('<c><d></d></c>'),
2858 canonicalize(tounicode(c)))
2860 def test_tounicode_none(self):
2861 tounicode = self.etree.tounicode
2862 self.assertRaises(TypeError, self.etree.tounicode, None)
2864 def test_tounicode_element_tail(self):
2865 tounicode = self.etree.tounicode
2866 Element = self.etree.Element
2867 SubElement = self.etree.SubElement
2870 b = SubElement(a, 'b')
2871 c = SubElement(a, 'c')
2872 d = SubElement(c, 'd')
2875 self.assert_(isinstance(tounicode(b), _unicode))
2876 self.assert_(tounicode(b) == '<b/>Foo' or
2877 tounicode(b) == '<b />Foo')
2879 def test_tounicode_pretty(self):
2880 tounicode = self.etree.tounicode
2881 Element = self.etree.Element
2882 SubElement = self.etree.SubElement
2885 b = SubElement(a, 'b')
2886 c = SubElement(a, 'c')
2888 result = tounicode(a)
2889 self.assertEquals(result, "<a><b/><c/></a>")
2891 result = tounicode(a, pretty_print=False)
2892 self.assertEquals(result, "<a><b/><c/></a>")
2894 result = tounicode(a, pretty_print=True)
2895 self.assertEquals(result, "<a>\n <b/>\n <c/>\n</a>\n")
2897 def test_tostring_unicode(self):
2898 tostring = self.etree.tostring
2899 Element = self.etree.Element
2900 SubElement = self.etree.SubElement
2903 b = SubElement(a, 'b')
2904 c = SubElement(a, 'c')
2906 self.assert_(isinstance(tostring(a, encoding=_unicode), _unicode))
2907 self.assertEquals(_bytes('<a><b></b><c></c></a>'),
2908 canonicalize(tostring(a, encoding=_unicode)))
2910 def test_tostring_unicode_element(self):
2911 tostring = self.etree.tostring
2912 Element = self.etree.Element
2913 SubElement = self.etree.SubElement
2916 b = SubElement(a, 'b')
2917 c = SubElement(a, 'c')
2918 d = SubElement(c, 'd')
2919 self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
2920 self.assert_(isinstance(tostring(c, encoding=_unicode), _unicode))
2921 self.assertEquals(_bytes('<b></b>'),
2922 canonicalize(tostring(b, encoding=_unicode)))
2923 self.assertEquals(_bytes('<c><d></d></c>'),
2924 canonicalize(tostring(c, encoding=_unicode)))
2926 def test_tostring_unicode_none(self):
2927 tostring = self.etree.tostring
2928 self.assertRaises(TypeError, self.etree.tostring,
2929 None, encoding=_unicode)
2931 def test_tostring_unicode_element_tail(self):
2932 tostring = self.etree.tostring
2933 Element = self.etree.Element
2934 SubElement = self.etree.SubElement
2937 b = SubElement(a, 'b')
2938 c = SubElement(a, 'c')
2939 d = SubElement(c, 'd')
2942 self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
2943 self.assert_(tostring(b, encoding=_unicode) == '<b/>Foo' or
2944 tostring(b, encoding=_unicode) == '<b />Foo')
2946 def test_tostring_unicode_pretty(self):
2947 tostring = self.etree.tostring
2948 Element = self.etree.Element
2949 SubElement = self.etree.SubElement
2952 b = SubElement(a, 'b')
2953 c = SubElement(a, 'c')
2955 result = tostring(a, encoding=_unicode)
2956 self.assertEquals(result, "<a><b/><c/></a>")
2958 result = tostring(a, encoding=_unicode, pretty_print=False)
2959 self.assertEquals(result, "<a><b/><c/></a>")
2961 result = tostring(a, encoding=_unicode, pretty_print=True)
2962 self.assertEquals(result, "<a>\n <b/>\n <c/>\n</a>\n")
2966 def _writeElement(self, element, encoding='us-ascii', compression=0):
2967 """Write out element for comparison.
2969 ElementTree = self.etree.ElementTree
2971 tree = ElementTree(element=element)
2972 tree.write(f, encoding=encoding, compression=compression)
2975 data = zlib.decompress(data)
2976 return canonicalize(data)
2979 class XIncludeTestCase(HelperTestCase):
2980 def test_xinclude_text(self):
2981 filename = fileInTestDir('test_broken.xml')
2982 root = etree.XML(_bytes('''\
2983 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
2984 <xi:include href="%s" parse="text"/>
2987 old_text = root.text
2988 content = read_file(filename)
2989 old_tail = root[0].tail
2991 self.include( etree.ElementTree(root) )
2992 self.assertEquals(old_text + content + old_tail,
2995 def test_xinclude(self):
2996 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
2997 self.assertNotEquals(
2999 tree.getroot()[1].tag)
3001 self.include( tree )
3002 # check whether we find it replaced with included data
3005 tree.getroot()[1].tag)
3007 def test_xinclude_resolver(self):
3008 class res(etree.Resolver):
3009 include_text = read_file(fileInTestDir('test.xml'))
3011 def resolve(self, url, id, context):
3012 if url.endswith(".dtd"):
3013 self.called["dtd"] = True
3014 return self.resolve_filename(
3015 fileInTestDir('test.dtd'), context)
3016 elif url.endswith("test_xinclude.xml"):
3017 self.called["input"] = True
3018 return None # delegate to default resolver
3020 self.called["include"] = True
3021 return self.resolve_string(self.include_text, context)
3023 res_instance = res()
3024 parser = etree.XMLParser(load_dtd = True)
3025 parser.resolvers.add(res_instance)
3027 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
3032 called = list(res_instance.called.items())
3035 [("dtd", True), ("include", True), ("input", True)],
3038 class ETreeXIncludeTestCase(XIncludeTestCase):
3039 def include(self, tree):
3043 class ElementIncludeTestCase(XIncludeTestCase):
3044 from lxml import ElementInclude
3045 def include(self, tree):
3046 self.ElementInclude.include(tree.getroot())
3049 class ETreeC14NTestCase(HelperTestCase):
3050 def test_c14n(self):
3051 tree = self.parse(_bytes('<a><b/></a>'))
3055 self.assertEquals(_bytes('<a><b></b></a>'),
3058 def test_c14n_gzip(self):
3059 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3061 tree.write_c14n(f, compression=9)
3062 gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
3067 self.assertEquals(_bytes('<a>'+'<b></b>'*200+'</a>'),
3070 def test_c14n_file(self):
3071 tree = self.parse(_bytes('<a><b/></a>'))
3072 handle, filename = tempfile.mkstemp()
3074 tree.write_c14n(filename)
3075 data = read_file(filename, 'rb')
3079 self.assertEquals(_bytes('<a><b></b></a>'),
3082 def test_c14n_file_gzip(self):
3083 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3084 handle, filename = tempfile.mkstemp()
3086 tree.write_c14n(filename, compression=9)
3087 f = gzip.open(filename, 'rb')
3095 self.assertEquals(_bytes('<a>'+'<b></b>'*200+'</a>'),
3098 def test_c14n_with_comments(self):
3099 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
3103 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3106 tree.write_c14n(f, with_comments=True)
3108 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3111 tree.write_c14n(f, with_comments=False)
3113 self.assertEquals(_bytes('<a><b></b></a>'),
3116 def test_c14n_tostring_with_comments(self):
3117 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
3118 s = etree.tostring(tree, method='c14n')
3119 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3121 s = etree.tostring(tree, method='c14n', with_comments=True)
3122 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3124 s = etree.tostring(tree, method='c14n', with_comments=False)
3125 self.assertEquals(_bytes('<a><b></b></a>'),
3128 def test_c14n_element_tostring_with_comments(self):
3129 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
3130 s = etree.tostring(tree.getroot(), method='c14n')
3131 self.assertEquals(_bytes('<a><!--ho--><b></b></a>'),
3133 s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
3134 self.assertEquals(_bytes('<a><!--ho--><b></b></a>'),
3136 s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
3137 self.assertEquals(_bytes('<a><b></b></a>'),
3140 def test_c14n_exclusive(self):
3141 tree = self.parse(_bytes(
3142 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3146 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3149 tree.write_c14n(f, exclusive=False)
3151 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3154 tree.write_c14n(f, exclusive=True)
3156 self.assertEquals(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
3159 def test_c14n_tostring_exclusive(self):
3160 tree = self.parse(_bytes(
3161 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3162 s = etree.tostring(tree, method='c14n')
3163 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3165 s = etree.tostring(tree, method='c14n', exclusive=False)
3166 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3168 s = etree.tostring(tree, method='c14n', exclusive=True)
3169 self.assertEquals(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
3172 def test_c14n_element_tostring_exclusive(self):
3173 tree = self.parse(_bytes(
3174 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3175 s = etree.tostring(tree.getroot(), method='c14n')
3176 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3178 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
3179 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3181 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
3182 self.assertEquals(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
3185 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
3186 self.assertEquals(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
3188 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
3189 self.assertEquals(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
3193 class ETreeWriteTestCase(HelperTestCase):
3194 def test_write(self):
3195 tree = self.parse(_bytes('<a><b/></a>'))
3199 self.assertEquals(_bytes('<a><b/></a>'),
3202 def test_write_gzip(self):
3203 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3205 tree.write(f, compression=9)
3206 gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
3211 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3214 def test_write_gzip_level(self):
3215 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3217 tree.write(f, compression=0)
3222 self.assertEquals(f.getvalue(), s0)
3225 tree.write(f, compression=1)
3227 self.assert_(len(s) <= len(s0))
3228 gzfile = gzip.GzipFile(fileobj=BytesIO(s))
3235 tree.write(f, compression=9)
3237 self.assert_(len(s) <= len(s0))
3238 gzfile = gzip.GzipFile(fileobj=BytesIO(s))
3244 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3246 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3248 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3251 def test_write_file(self):
3252 tree = self.parse(_bytes('<a><b/></a>'))
3253 handle, filename = tempfile.mkstemp()
3255 tree.write(filename)
3256 data = read_file(filename, 'rb')
3260 self.assertEquals(_bytes('<a><b/></a>'),
3263 def test_write_file_gzip(self):
3264 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3265 handle, filename = tempfile.mkstemp()
3267 tree.write(filename, compression=9)
3268 f = gzip.open(filename, 'rb')
3276 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3279 def test_write_file_gzip_parse(self):
3280 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3281 handle, filename = tempfile.mkstemp()
3283 tree.write(filename, compression=9)
3284 data = etree.tostring(etree.parse(filename))
3288 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3291 def test_write_file_gzipfile_parse(self):
3292 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3293 handle, filename = tempfile.mkstemp()
3295 tree.write(filename, compression=9)
3296 data = etree.tostring(etree.parse(
3297 gzip.GzipFile(filename)))
3301 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3304 class ETreeErrorLogTest(HelperTestCase):
3307 def test_parse_error_logging(self):
3308 parse = self.etree.parse
3309 f = BytesIO('<a><b></c></b></a>')
3310 self.etree.clear_error_log()
3315 e = sys.exc_info()[1]
3318 self.assert_([ log for log in logs
3319 if 'mismatch' in log.message ])
3320 self.assert_([ log for log in logs
3321 if 'PARSER' in log.domain_name])
3322 self.assert_([ log for log in logs
3323 if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
3324 self.assert_([ log for log in logs
3326 self.assert_([ log for log in logs
3327 if 15 == log.column ])
3329 def _test_python_error_logging(self):
3330 """This can't really be tested as long as there isn't a way to
3331 reset the logging setup ...
3333 parse = self.etree.parse
3336 class Logger(self.etree.PyErrorLog):
3337 def log(self, entry, message, *args):
3338 messages.append(message)
3340 self.etree.use_global_python_log(Logger())
3341 f = BytesIO('<a><b></c></b></a>')
3348 self.assert_([ message for message in messages
3349 if 'mismatch' in message ])
3350 self.assert_([ message for message in messages
3351 if ':PARSER:' in message])
3352 self.assert_([ message for message in messages
3353 if ':ERR_TAG_NAME_MISMATCH:' in message ])
3354 self.assert_([ message for message in messages
3355 if ':1:15:' in message ])
3358 suite = unittest.TestSuite()
3359 suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
3360 suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
3361 suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
3362 suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
3363 suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
3364 suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
3366 [make_doctest('../../../doc/tutorial.txt')])
3368 [make_doctest('../../../doc/api.txt')])
3370 [make_doctest('../../../doc/FAQ.txt')])
3372 [make_doctest('../../../doc/parsing.txt')])
3374 [make_doctest('../../../doc/resolvers.txt')])
3377 if __name__ == '__main__':
3378 print('to test use test.py %s' % __file__)