1 # xml.etree test. This file contains enough tests to make sure that
2 # all included components work as they should.
3 # Large parts are extracted from the upstream test suite.
5 # IMPORTANT: the same doctests are run from "test_xml_etree_c" in
6 # order to ensure consistency between the C implementation and the
7 # Python implementation.
9 # For this purpose, the module-level "ET" symbol is temporarily
10 # monkey-patched when running the "test_xml_etree_c" test suite.
11 # Don't re-import "xml.etree.ElementTree" module in the docstring,
12 # except if the test is specific to the Python implementation.
17 from test
import test_support
18 from test
.test_support
import findfile
20 from xml
.etree
import ElementTree
as ET
22 SIMPLE_XMLFILE
= findfile("simple.xml", subdir
="xmltestdata")
23 SIMPLE_NS_XMLFILE
= findfile("simple-ns.xml", subdir
="xmltestdata")
27 <tag class='a'>text</tag>
30 <tag class='b' id='inner'>subtext</tag>
37 <tag class='b' id='inner'>subtext</tag>
46 <body xmlns="http://effbot.org/ns">
60 >>> from xml.etree import ElementTree
61 >>> from xml.etree import ElementInclude
62 >>> from xml.etree import ElementPath
65 def check_method(method
):
66 if not hasattr(method
, '__call__'):
67 print method
, "not callable"
69 def serialize(elem
, to_string
=True, **options
):
71 file = StringIO
.StringIO()
72 tree
= ET
.ElementTree(elem
)
73 tree
.write(file, **options
)
75 return file.getvalue()
81 if elem
.tag
== ET
.Comment
:
85 def summarize_list(seq
):
86 return [summarize(elem
) for elem
in seq
]
88 def normalize_crlf(tree
):
89 for elem
in tree
.iter():
91 elem
.text
= elem
.text
.replace("\r\n", "\n")
93 elem
.tail
= elem
.tail
.replace("\r\n", "\n")
95 def check_string(string
):
99 print "expected one-character string, got %r" % char
100 new_string
= string
+ ""
101 new_string
= string
+ " "
104 def check_mapping(mapping
):
106 keys
= mapping
.keys()
107 items
= mapping
.items()
110 mapping
["key"] = "value"
111 if mapping
["key"] != "value":
112 print "expected value string, got %r" % mapping
["key"]
114 def check_element(element
):
115 if not ET
.iselement(element
):
116 print "not an element"
117 if not hasattr(element
, "tag"):
118 print "no tag member"
119 if not hasattr(element
, "attrib"):
120 print "no attrib member"
121 if not hasattr(element
, "text"):
122 print "no text member"
123 if not hasattr(element
, "tail"):
124 print "no tail member"
126 check_string(element
.tag
)
127 check_mapping(element
.attrib
)
128 if element
.text
is not None:
129 check_string(element
.text
)
130 if element
.tail
is not None:
131 check_string(element
.tail
)
135 # --------------------------------------------------------------------
140 Test element tree interface.
142 >>> element = ET.Element("tag")
143 >>> check_element(element)
144 >>> tree = ET.ElementTree(element)
145 >>> check_element(tree.getroot())
147 >>> element = ET.Element("t\xe4g", key="value")
148 >>> tree = ET.ElementTree(element)
149 >>> repr(element) # doctest: +ELLIPSIS
150 "<Element 't\\xe4g' at 0x...>"
151 >>> element = ET.Element("tag", key="value")
153 Make sure all standard element methods exist.
155 >>> check_method(element.append)
156 >>> check_method(element.extend)
157 >>> check_method(element.insert)
158 >>> check_method(element.remove)
159 >>> check_method(element.getchildren)
160 >>> check_method(element.find)
161 >>> check_method(element.iterfind)
162 >>> check_method(element.findall)
163 >>> check_method(element.findtext)
164 >>> check_method(element.clear)
165 >>> check_method(element.get)
166 >>> check_method(element.set)
167 >>> check_method(element.keys)
168 >>> check_method(element.items)
169 >>> check_method(element.iter)
170 >>> check_method(element.itertext)
171 >>> check_method(element.getiterator)
173 These methods return an iterable. See bug 6472.
175 >>> check_method(element.iter("tag").next)
176 >>> check_method(element.iterfind("tag").next)
177 >>> check_method(element.iterfind("*").next)
178 >>> check_method(tree.iter("tag").next)
179 >>> check_method(tree.iterfind("tag").next)
180 >>> check_method(tree.iterfind("*").next)
182 These aliases are provided:
184 >>> assert ET.XML == ET.fromstring
185 >>> assert ET.PI == ET.ProcessingInstruction
186 >>> assert ET.XMLParser == ET.XMLTreeBuilder
191 Basic method sanity checks.
193 >>> elem = ET.XML("<body><tag/></body>")
195 '<body><tag /></body>'
196 >>> e = ET.Element("tag2")
199 '<body><tag /><tag2 /></body>'
202 '<body><tag /></body>'
203 >>> elem.insert(0, e)
205 '<body><tag2 /><tag /></body>'
209 '<body><tag /><tag2 /></body>'
212 >>> element = ET.Element("tag", key="value")
213 >>> serialize(element) # 1
214 '<tag key="value" />'
215 >>> subelement = ET.Element("subtag")
216 >>> element.append(subelement)
217 >>> serialize(element) # 2
218 '<tag key="value"><subtag /></tag>'
219 >>> element.insert(0, subelement)
220 >>> serialize(element) # 3
221 '<tag key="value"><subtag /><subtag /></tag>'
222 >>> element.remove(subelement)
223 >>> serialize(element) # 4
224 '<tag key="value"><subtag /></tag>'
225 >>> element.remove(subelement)
226 >>> serialize(element) # 5
227 '<tag key="value" />'
228 >>> element.remove(subelement)
229 Traceback (most recent call last):
230 ValueError: list.remove(x): x not in list
231 >>> serialize(element) # 6
232 '<tag key="value" />'
233 >>> element[0:0] = [subelement, subelement, subelement]
234 >>> serialize(element[1])
236 >>> element[1:9] == [element[1], element[2]]
238 >>> element[:9:2] == [element[0], element[2]]
241 >>> serialize(element)
242 '<tag key="value"><subtag /><subtag /></tag>'
247 Test CDATA handling (etc).
249 >>> serialize(ET.XML("<tag>hello</tag>"))
251 >>> serialize(ET.XML("<tag>hello</tag>"))
253 >>> serialize(ET.XML("<tag><![CDATA[hello]]></tag>"))
257 # Only with Python implementation
260 Test find methods using the elementpath fallback.
262 >>> from xml.etree import ElementTree
264 >>> CurrentElementPath = ElementTree.ElementPath
265 >>> ElementTree.ElementPath = ElementTree._SimpleElementPath()
266 >>> elem = ElementTree.XML(SAMPLE_XML)
267 >>> elem.find("tag").tag
269 >>> ElementTree.ElementTree(elem).find("tag").tag
271 >>> elem.findtext("tag")
273 >>> elem.findtext("tog")
274 >>> elem.findtext("tog", "default")
276 >>> ElementTree.ElementTree(elem).findtext("tag")
278 >>> summarize_list(elem.findall("tag"))
280 >>> summarize_list(elem.findall(".//tag"))
281 ['tag', 'tag', 'tag']
283 Path syntax doesn't work in this case.
285 >>> elem.find("section/tag")
286 >>> elem.findtext("section/tag")
287 >>> summarize_list(elem.findall("section/tag"))
290 >>> ElementTree.ElementPath = CurrentElementPath
295 Test find methods (including xpath syntax).
297 >>> elem = ET.XML(SAMPLE_XML)
298 >>> elem.find("tag").tag
300 >>> ET.ElementTree(elem).find("tag").tag
302 >>> elem.find("section/tag").tag
304 >>> elem.find("./tag").tag
306 >>> ET.ElementTree(elem).find("./tag").tag
308 >>> ET.ElementTree(elem).find("/tag").tag
310 >>> elem[2] = ET.XML(SAMPLE_SECTION)
311 >>> elem.find("section/nexttag").tag
313 >>> ET.ElementTree(elem).find("section/tag").tag
315 >>> ET.ElementTree(elem).find("tog")
316 >>> ET.ElementTree(elem).find("tog/foo")
317 >>> elem.findtext("tag")
319 >>> elem.findtext("section/nexttag")
321 >>> elem.findtext("section/nexttag", "default")
323 >>> elem.findtext("tog")
324 >>> elem.findtext("tog", "default")
326 >>> ET.ElementTree(elem).findtext("tag")
328 >>> ET.ElementTree(elem).findtext("tog/foo")
329 >>> ET.ElementTree(elem).findtext("tog/foo", "default")
331 >>> ET.ElementTree(elem).findtext("./tag")
333 >>> ET.ElementTree(elem).findtext("/tag")
335 >>> elem.findtext("section/tag")
337 >>> ET.ElementTree(elem).findtext("section/tag")
339 >>> summarize_list(elem.findall("."))
341 >>> summarize_list(elem.findall("tag"))
343 >>> summarize_list(elem.findall("tog"))
345 >>> summarize_list(elem.findall("tog/foo"))
347 >>> summarize_list(elem.findall("*"))
348 ['tag', 'tag', 'section']
349 >>> summarize_list(elem.findall(".//tag"))
350 ['tag', 'tag', 'tag', 'tag']
351 >>> summarize_list(elem.findall("section/tag"))
353 >>> summarize_list(elem.findall("section//tag"))
355 >>> summarize_list(elem.findall("section/*"))
356 ['tag', 'nexttag', 'nextsection']
357 >>> summarize_list(elem.findall("section//*"))
358 ['tag', 'nexttag', 'nextsection', 'tag']
359 >>> summarize_list(elem.findall("section/.//*"))
360 ['tag', 'nexttag', 'nextsection', 'tag']
361 >>> summarize_list(elem.findall("*/*"))
362 ['tag', 'nexttag', 'nextsection']
363 >>> summarize_list(elem.findall("*//*"))
364 ['tag', 'nexttag', 'nextsection', 'tag']
365 >>> summarize_list(elem.findall("*/tag"))
367 >>> summarize_list(elem.findall("*/./tag"))
369 >>> summarize_list(elem.findall("./tag"))
371 >>> summarize_list(elem.findall(".//tag"))
372 ['tag', 'tag', 'tag', 'tag']
373 >>> summarize_list(elem.findall("././tag"))
375 >>> summarize_list(elem.findall(".//tag[@class]"))
376 ['tag', 'tag', 'tag']
377 >>> summarize_list(elem.findall(".//tag[@class='a']"))
379 >>> summarize_list(elem.findall(".//tag[@class='b']"))
381 >>> summarize_list(elem.findall(".//tag[@id]"))
383 >>> summarize_list(elem.findall(".//section[tag]"))
385 >>> summarize_list(elem.findall(".//section[element]"))
387 >>> summarize_list(elem.findall("../tag"))
389 >>> summarize_list(elem.findall("section/../tag"))
391 >>> summarize_list(ET.ElementTree(elem).findall("./tag"))
394 Following example is invalid in 1.2.
395 A leading '*' is assumed in 1.3.
397 >>> elem.findall("section//") == elem.findall("section//*")
400 ET's Path module handles this case incorrectly; this gives
401 a warning in 1.3, and the behaviour will be modified in 1.4.
403 >>> summarize_list(ET.ElementTree(elem).findall("/tag"))
406 >>> elem = ET.XML(SAMPLE_XML_NS)
407 >>> summarize_list(elem.findall("tag"))
409 >>> summarize_list(elem.findall("{http://effbot.org/ns}tag"))
410 ['{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag']
411 >>> summarize_list(elem.findall(".//{http://effbot.org/ns}tag"))
412 ['{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag']
419 >>> stringfile = StringIO.StringIO(SAMPLE_XML)
420 >>> tree = ET.ElementTree(file=stringfile)
421 >>> tree.find("tag").tag
423 >>> tree.find("section/tag").tag
426 >>> tree = ET.ElementTree(file=SIMPLE_XMLFILE)
427 >>> tree.find("element").tag
429 >>> tree.find("element/../empty-element").tag
435 Check bad or unsupported path expressions.
437 >>> elem = ET.XML(SAMPLE_XML)
438 >>> elem.findall("/tag")
439 Traceback (most recent call last):
440 SyntaxError: cannot use absolute path on element
445 Check that the path cache behaves sanely.
447 >>> elem = ET.XML(SAMPLE_XML)
448 >>> for i in range(10): ET.ElementTree(elem).find('./'+str(i))
449 >>> cache_len_10 = len(ET.ElementPath._cache)
450 >>> for i in range(10): ET.ElementTree(elem).find('./'+str(i))
451 >>> len(ET.ElementPath._cache) == cache_len_10
453 >>> for i in range(20): ET.ElementTree(elem).find('./'+str(i))
454 >>> len(ET.ElementPath._cache) > cache_len_10
456 >>> for i in range(600): ET.ElementTree(elem).find('./'+str(i))
457 >>> len(ET.ElementPath._cache) < 500
463 Test copy handling (etc).
466 >>> e1 = ET.XML("<tag>hello<foo/></tag>")
467 >>> e2 = copy.copy(e1)
468 >>> e3 = copy.deepcopy(e1)
469 >>> e1.find("foo").tag = "bar"
471 '<tag>hello<bar /></tag>'
473 '<tag>hello<bar /></tag>'
475 '<tag>hello<foo /></tag>'
481 Test attribute handling.
483 >>> elem = ET.Element("tag")
484 >>> elem.get("key") # 1.1
485 >>> elem.get("key", "default") # 1.2
487 >>> elem.set("key", "value")
488 >>> elem.get("key") # 1.3
491 >>> elem = ET.Element("tag", key="value")
492 >>> elem.get("key") # 2.1
494 >>> elem.attrib # 2.2
497 >>> attrib = {"key": "value"}
498 >>> elem = ET.Element("tag", attrib)
499 >>> attrib.clear() # check for aliasing issues
500 >>> elem.get("key") # 3.1
502 >>> elem.attrib # 3.2
505 >>> attrib = {"key": "value"}
506 >>> elem = ET.Element("tag", **attrib)
507 >>> attrib.clear() # check for aliasing issues
508 >>> elem.get("key") # 4.1
510 >>> elem.attrib # 4.2
513 >>> elem = ET.Element("tag", {"key": "other"}, key="value")
514 >>> elem.get("key") # 5.1
516 >>> elem.attrib # 5.2
519 >>> elem = ET.Element('test')
521 >>> elem.set('testa', 'testval')
522 >>> elem.set('testb', 'test2')
523 >>> ET.tostring(elem)
524 '<test testa="testval" testb="test2">aa</test>'
525 >>> sorted(elem.keys())
527 >>> sorted(elem.items())
528 [('testa', 'testval'), ('testb', 'test2')]
529 >>> elem.attrib['testb']
531 >>> elem.attrib['testb'] = 'test1'
532 >>> elem.attrib['testc'] = 'test2'
533 >>> ET.tostring(elem)
534 '<test testa="testval" testb="test1" testc="test2">aa</test>'
539 Test makeelement handling.
541 >>> elem = ET.Element("tag")
542 >>> attrib = {"key": "value"}
543 >>> subelem = elem.makeelement("subtag", attrib)
544 >>> if subelem.attrib is attrib:
545 ... print "attrib aliasing"
546 >>> elem.append(subelem)
548 '<tag><subtag key="value" /></tag>'
553 >>> elem.append(subelem)
555 '<tag><subtag key="value" /></tag>'
556 >>> elem.extend([subelem, subelem])
558 '<tag><subtag key="value" /><subtag key="value" /><subtag key="value" /></tag>'
559 >>> elem[:] = [subelem]
561 '<tag><subtag key="value" /></tag>'
562 >>> elem[:] = tuple([subelem])
564 '<tag><subtag key="value" /></tag>'
570 Test parsing from file.
572 >>> tree = ET.parse(SIMPLE_XMLFILE)
573 >>> normalize_crlf(tree)
574 >>> tree.write(sys.stdout)
576 <element key="value">text</element>
577 <element>text</element>tail
580 >>> tree = ET.parse(SIMPLE_NS_XMLFILE)
581 >>> normalize_crlf(tree)
582 >>> tree.write(sys.stdout)
583 <ns0:root xmlns:ns0="namespace">
584 <ns0:element key="value">text</ns0:element>
585 <ns0:element>text</ns0:element>tail
586 <ns0:empty-element />
589 >>> with open(SIMPLE_XMLFILE) as f:
592 >>> parser = ET.XMLParser()
593 >>> parser.version # doctest: +ELLIPSIS
595 >>> parser.feed(data)
596 >>> print serialize(parser.close())
598 <element key="value">text</element>
599 <element>text</element>tail
603 >>> parser = ET.XMLTreeBuilder() # 1.2 compatibility
604 >>> parser.feed(data)
605 >>> print serialize(parser.close())
607 <element key="value">text</element>
608 <element>text</element>tail
612 >>> target = ET.TreeBuilder()
613 >>> parser = ET.XMLParser(target=target)
614 >>> parser.feed(data)
615 >>> print serialize(parser.close())
617 <element key="value">text</element>
618 <element>text</element>tail
625 >>> element = ET.XML("<html><body>text</body></html>")
626 >>> ET.ElementTree(element).write(sys.stdout)
627 <html><body>text</body></html>
628 >>> element = ET.fromstring("<html><body>text</body></html>")
629 >>> ET.ElementTree(element).write(sys.stdout)
630 <html><body>text</body></html>
631 >>> sequence = ["<html><body>", "text</bo", "dy></html>"]
632 >>> element = ET.fromstringlist(sequence)
633 >>> print ET.tostring(element)
634 <html><body>text</body></html>
635 >>> print "".join(ET.tostringlist(element))
636 <html><body>text</body></html>
637 >>> ET.tostring(element, "ascii")
638 "<?xml version='1.0' encoding='ascii'?>\\n<html><body>text</body></html>"
639 >>> _, ids = ET.XMLID("<html><body>text</body></html>")
642 >>> _, ids = ET.XMLID("<html><body id='body'>text</body></html>")
651 Test iterparse interface.
653 >>> iterparse = ET.iterparse
655 >>> context = iterparse(SIMPLE_XMLFILE)
656 >>> action, elem = next(context)
657 >>> print action, elem.tag
659 >>> for action, elem in context:
660 ... print action, elem.tag
667 >>> context = iterparse(SIMPLE_NS_XMLFILE)
668 >>> for action, elem in context:
669 ... print action, elem.tag
670 end {namespace}element
671 end {namespace}element
672 end {namespace}empty-element
676 >>> context = iterparse(SIMPLE_XMLFILE, events)
677 >>> for action, elem in context:
678 ... print action, elem.tag
681 >>> context = iterparse(SIMPLE_XMLFILE, events=events)
682 >>> for action, elem in context:
683 ... print action, elem.tag
685 >>> events = ("start", "end")
686 >>> context = iterparse(SIMPLE_XMLFILE, events)
687 >>> for action, elem in context:
688 ... print action, elem.tag
698 >>> events = ("start", "end", "start-ns", "end-ns")
699 >>> context = iterparse(SIMPLE_NS_XMLFILE, events)
700 >>> for action, elem in context:
701 ... if action in ("start", "end"):
702 ... print action, elem.tag
704 ... print action, elem
705 start-ns ('', 'namespace')
706 start {namespace}root
707 start {namespace}element
708 end {namespace}element
709 start {namespace}element
710 end {namespace}element
711 start {namespace}empty-element
712 end {namespace}empty-element
716 >>> events = ("start", "end", "bogus")
717 >>> with open(SIMPLE_XMLFILE, "rb") as f:
718 ... iterparse(f, events)
719 Traceback (most recent call last):
720 ValueError: unknown event 'bogus'
724 >>> source = StringIO.StringIO(
725 ... "<?xml version='1.0' encoding='iso-8859-1'?>\\n"
726 ... "<body xmlns='http://éffbot.org/ns'\\n"
727 ... " xmlns:cl\\xe9='http://effbot.org/ns'>text</body>\\n")
728 >>> events = ("start-ns",)
729 >>> context = iterparse(source, events)
730 >>> for action, elem in context:
731 ... print action, elem
732 start-ns ('', u'http://\\xe9ffbot.org/ns')
733 start-ns (u'cl\\xe9', 'http://effbot.org/ns')
735 >>> source = StringIO.StringIO("<document />junk")
737 ... for action, elem in iterparse(source):
738 ... print action, elem.tag
739 ... except ET.ParseError, v:
741 junk after document element: line 1, column 12
746 >>> elem = ET.Element("tag")
747 >>> elem.text = "text"
750 >>> ET.SubElement(elem, "subtag").text = "subtext"
752 '<tag>text<subtag>subtext</subtag></tag>'
757 'text<subtag>subtext</subtag>'
758 >>> elem.insert(0, ET.Comment("comment"))
759 >>> serialize(elem) # assumes 1.3
760 'text<!--comment--><subtag>subtext</subtag>'
761 >>> elem[0] = ET.PI("key", "value")
763 'text<?key value?><subtag>subtext</subtag>'
766 def custom_builder():
768 Test parser w. custom builder.
770 >>> with open(SIMPLE_XMLFILE) as f:
773 ... def start(self, tag, attrib):
774 ... print "start", tag
775 ... def end(self, tag):
777 ... def data(self, text):
779 >>> builder = Builder()
780 >>> parser = ET.XMLParser(target=builder)
781 >>> parser.feed(data)
791 >>> with open(SIMPLE_NS_XMLFILE) as f:
794 ... def start(self, tag, attrib):
795 ... print "start", tag
796 ... def end(self, tag):
798 ... def data(self, text):
800 ... def pi(self, target, data):
801 ... print "pi", target, repr(data)
802 ... def comment(self, data):
803 ... print "comment", repr(data)
804 >>> builder = Builder()
805 >>> parser = ET.XMLParser(target=builder)
806 >>> parser.feed(data)
809 start {namespace}root
810 start {namespace}element
811 end {namespace}element
812 start {namespace}element
813 end {namespace}element
814 start {namespace}empty-element
815 end {namespace}empty-element
822 Test Element.getchildren()
824 >>> with open(SIMPLE_XMLFILE, "r") as f:
825 ... tree = ET.parse(f)
826 >>> for elem in tree.getroot().iter():
827 ... summarize_list(elem.getchildren())
828 ['element', 'element', 'empty-element']
832 >>> for elem in tree.getiterator():
833 ... summarize_list(elem.getchildren())
834 ['element', 'element', 'empty-element']
839 >>> elem = ET.XML(SAMPLE_XML)
840 >>> len(elem.getchildren())
842 >>> len(elem[2].getchildren())
844 >>> elem[:] == elem.getchildren()
849 >>> len(elem.getchildren())
851 >>> child1 == elem[0]
853 >>> child2 == elem[1]
855 >>> elem[0:2] = [child2, child1]
856 >>> child2 == elem[0]
858 >>> child1 == elem[1]
860 >>> child1 == elem[0]
863 >>> elem.getchildren()
869 >>> elem = ET.XML("<html><body>text</body></html>")
870 >>> ET.tostring(elem)
871 '<html><body>text</body></html>'
872 >>> elem = ET.fromstring("<html><body>text</body></html>")
873 >>> ET.tostring(elem)
874 '<html><body>text</body></html>'
877 def check_encoding(encoding
):
879 >>> check_encoding("ascii")
880 >>> check_encoding("us-ascii")
881 >>> check_encoding("iso-8859-1")
882 >>> check_encoding("iso-8859-15")
883 >>> check_encoding("cp437")
884 >>> check_encoding("mac-roman")
886 ET
.XML("<?xml version='1.0' encoding='%s'?><xml />" % encoding
)
890 Test encoding issues.
892 >>> elem = ET.Element("tag")
893 >>> elem.text = u"abc"
896 >>> serialize(elem, encoding="utf-8")
898 >>> serialize(elem, encoding="us-ascii")
900 >>> serialize(elem, encoding="iso-8859-1")
901 "<?xml version='1.0' encoding='iso-8859-1'?>\n<tag>abc</tag>"
903 >>> elem.text = "<&\"\'>"
905 '<tag><&"\'>
;</tag
>'
906 >>> serialize(elem, encoding="utf-8")
907 '<tag
><
;&
;"\'></tag>'
908 >>> serialize(elem, encoding="us
-ascii
") # cdata characters
909 '<tag><&"\'>
;</tag
>'
910 >>> serialize(elem, encoding="iso-8859-1")
911 '<?xml version
=\'1.0\' encoding
=\'iso
-8859-1\'?
>\n<tag
><
;&
;"\'></tag>'
913 >>> elem.attrib["key
"] = "<&\"\'>"
916 '<tag key="<
;&
;"
;\'>
;" />'
917 >>> serialize(elem, encoding="utf
-8")
918 '<tag key="<
;&
;"
;\'>
;" />'
919 >>> serialize(elem, encoding="us
-ascii
")
920 '<tag key="<
;&
;"
;\'>
;" />'
921 >>> serialize(elem, encoding="iso
-8859-1")
922 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag key="<
;&
;"
;\'>
;" />'
924 >>> elem.text = u'\xe5\xf6\xf6<>'
925 >>> elem.attrib.clear()
927 '<tag>åöö<></tag>'
928 >>> serialize(elem, encoding="utf
-8")
929 '<tag>\xc3\xa5\xc3\xb6\xc3\xb6<></tag>'
930 >>> serialize(elem, encoding="us
-ascii
")
931 '<tag>åöö<></tag>'
932 >>> serialize(elem, encoding="iso
-8859-1")
933 "<?xml version
='1.0' encoding
='iso-8859-1'?
>\n<tag
>\xe5\xf6\xf6<
;>
;</tag
>"
935 >>> elem.attrib["key
"] = u'\xe5\xf6\xf6<>'
938 '<tag key="åöö<>" />'
939 >>> serialize(elem
, encoding
="utf-8")
940 '<tag key="\xc3\xa5\xc3\xb6\xc3\xb6<>" />'
941 >>> serialize(elem
, encoding
="us-ascii")
942 '<tag key="åöö<>" />'
943 >>> serialize(elem
, encoding
="iso-8859-1")
944 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag key="\xe5\xf6\xf6<>" />'
949 Test serialization methods
.
951 >>> e
= ET
.XML("<html><link/><script>1 < 2</script></html>")
954 '<html><link /><script>1 < 2</script></html>\n'
955 >>> serialize(e
, method
=None)
956 '<html><link /><script>1 < 2</script></html>\n'
957 >>> serialize(e
, method
="xml")
958 '<html><link /><script>1 < 2</script></html>\n'
959 >>> serialize(e
, method
="html")
960 '<html><link><script>1 < 2</script></html>\n'
961 >>> serialize(e
, method
="text")
969 >>> e
= ET
.XML("<html><body>this is a <i>paragraph</i>.</body>..</html>")
970 >>> summarize_list(e
.iter())
971 ['html', 'body', 'i']
972 >>> summarize_list(e
.find("body").iter())
974 >>> summarize(next(e
.iter()))
976 >>> "".join(e
.itertext())
977 'this is a paragraph...'
978 >>> "".join(e
.find("body").itertext())
979 'this is a paragraph.'
980 >>> next(e
.itertext())
983 Method iterparse should
return an iterator
. See bug
6472.
985 >>> sourcefile
= serialize(e
, to_string
=False)
986 >>> next(ET
.iterparse(sourcefile
)) # doctest: +ELLIPSIS
987 ('end', <Element
'i' at
0x
...>)
989 >>> tree
= ET
.ElementTree(None)
991 Traceback (most recent call last
):
992 AttributeError: 'NoneType' object has no attribute
'iter'
997 <!ENTITY
% user
-entities SYSTEM
'user-entities.xml'>
1000 <document
>&entity
;</document
>
1005 Test entity handling
.
1009 >>> e
= ET
.XML("<document title='舰'>test</document>")
1011 '<document title="舰">test</document>'
1015 >>> ET
.XML("<document>&entity;</document>")
1016 Traceback (most recent call last
):
1017 ParseError
: undefined entity
: line
1, column
10
1019 >>> ET
.XML(ENTITY_XML
)
1020 Traceback (most recent call last
):
1021 ParseError
: undefined entity
&entity
;: line
5, column
10
1025 >>> parser
= ET
.XMLParser()
1026 >>> parser
.entity
["entity"] = "text"
1027 >>> parser
.feed(ENTITY_XML
)
1028 >>> root
= parser
.close()
1030 '<document>text</document>'
1036 Test error handling
.
1038 >>> issubclass(ET
.ParseError
, SyntaxError)
1040 >>> error("foo").position
1042 >>> error("<tag>&foo;</tag>").position
1044 >>> error("foobar<").position
1050 except ET.ParseError:
1051 return sys.exc_value
1055 Test namespace issues
.
1059 >>> elem
= ET
.XML("<tag xml:lang='en' />")
1060 >>> serialize(elem
) # 1.1
1061 '<tag xml:lang="en" />'
1063 2) other
"well-known" namespaces
1065 >>> elem
= ET
.XML("<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' />")
1066 >>> serialize(elem
) # 2.1
1067 '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" />'
1069 >>> elem
= ET
.XML("<html:html xmlns:html='http://www.w3.org/1999/xhtml' />")
1070 >>> serialize(elem
) # 2.2
1071 '<html:html xmlns:html="http://www.w3.org/1999/xhtml" />'
1073 >>> elem
= ET
.XML("<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope' />")
1074 >>> serialize(elem
) # 2.3
1075 '<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope" />'
1077 3) unknown namespaces
1078 >>> elem
= ET
.XML(SAMPLE_XML_NS
)
1079 >>> print serialize(elem
)
1080 <ns0
:body xmlns
:ns0
="http://effbot.org/ns">
1081 <ns0
:tag
>text
</ns0
:tag
>
1084 <ns0
:tag
>subtext
</ns0
:tag
>
1091 Test QName handling
.
1095 >>> elem
= ET
.Element("{uri}tag")
1096 >>> serialize(elem
) # 1.1
1097 '<ns0:tag xmlns:ns0="uri" />'
1098 >>> elem
= ET
.Element(ET
.QName("{uri}tag"))
1099 >>> serialize(elem
) # 1.2
1100 '<ns0:tag xmlns:ns0="uri" />'
1101 >>> elem
= ET
.Element(ET
.QName("uri", "tag"))
1102 >>> serialize(elem
) # 1.3
1103 '<ns0:tag xmlns:ns0="uri" />'
1104 >>> elem
= ET
.Element(ET
.QName("uri", "tag"))
1105 >>> subelem
= ET
.SubElement(elem
, ET
.QName("uri", "tag1"))
1106 >>> subelem
= ET
.SubElement(elem
, ET
.QName("uri", "tag2"))
1107 >>> serialize(elem
) # 1.4
1108 '<ns0:tag xmlns:ns0="uri"><ns0:tag1 /><ns0:tag2 /></ns0:tag>'
1110 2) decorated attributes
1113 >>> elem
.attrib
["{uri}key"] = "value"
1114 >>> serialize(elem
) # 2.1
1115 '<ns0:tag xmlns:ns0="uri" ns0:key="value" />'
1118 >>> elem
.attrib
[ET
.QName("{uri}key")] = "value"
1119 >>> serialize(elem
) # 2.2
1120 '<ns0:tag xmlns:ns0="uri" ns0:key="value" />'
1122 3) decorated values are
not converted by default
, but the
1123 QName wrapper can be used
for values
1126 >>> elem
.attrib
["{uri}key"] = "{uri}value"
1127 >>> serialize(elem
) # 3.1
1128 '<ns0:tag xmlns:ns0="uri" ns0:key="{uri}value" />'
1131 >>> elem
.attrib
["{uri}key"] = ET
.QName("{uri}value")
1132 >>> serialize(elem
) # 3.2
1133 '<ns0:tag xmlns:ns0="uri" ns0:key="ns0:value" />'
1136 >>> subelem
= ET
.Element("tag")
1137 >>> subelem
.attrib
["{uri1}key"] = ET
.QName("{uri2}value")
1138 >>> elem
.append(subelem
)
1139 >>> elem
.append(subelem
)
1140 >>> serialize(elem
) # 3.3
1141 '<ns0:tag xmlns:ns0="uri" xmlns:ns1="uri1" xmlns:ns2="uri2"><tag ns1:key="ns2:value" /><tag ns1:key="ns2:value" /></ns0:tag>'
1143 4) Direct QName tests
1145 >>> str(ET
.QName('ns', 'tag'))
1147 >>> str(ET
.QName('{ns}tag'))
1149 >>> q1
= ET
.QName('ns', 'tag')
1150 >>> q2
= ET
.QName('ns', 'tag')
1153 >>> q2
= ET
.QName('ns', 'other-tag')
1162 def doctype_public():
1164 Test PUBLIC doctype
.
1166 >>> elem
= ET
.XML('<!DOCTYPE html PUBLIC'
1167 ... ' "-//W3C//DTD XHTML 1.0 Transitional//EN"'
1168 ... ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
1169 ... '<html>text</html>')
1173 def xpath_tokenizer(p):
1175 Test the XPath tokenizer
.
1177 >>> # tests from the xml specification
1178 >>> xpath_tokenizer("*")
1180 >>> xpath_tokenizer("text()")
1182 >>> xpath_tokenizer("@name")
1184 >>> xpath_tokenizer("@*")
1186 >>> xpath_tokenizer("para[1]")
1187 ['para', '[', '1', ']']
1188 >>> xpath_tokenizer("para[last()]")
1189 ['para', '[', 'last', '()', ']']
1190 >>> xpath_tokenizer("*/para")
1192 >>> xpath_tokenizer("/doc/chapter[5]/section[2]")
1193 ['/', 'doc', '/', 'chapter', '[', '5', ']', '/', 'section', '[', '2', ']']
1194 >>> xpath_tokenizer("chapter//para")
1195 ['chapter', '//', 'para']
1196 >>> xpath_tokenizer("//para")
1198 >>> xpath_tokenizer("//olist/item")
1199 ['//', 'olist', '/', 'item']
1200 >>> xpath_tokenizer(".")
1202 >>> xpath_tokenizer(".//para")
1204 >>> xpath_tokenizer("..")
1206 >>> xpath_tokenizer("../@lang")
1207 ['..', '/', '@', 'lang']
1208 >>> xpath_tokenizer("chapter[title]")
1209 ['chapter', '[', 'title', ']']
1210 >>> xpath_tokenizer("employee[@secretary and @assistant]")
1211 ['employee', '[', '@', 'secretary', '', 'and', '', '@', 'assistant', ']']
1213 >>> # additional tests
1214 >>> xpath_tokenizer("{http://spam}egg")
1215 ['{http://spam}egg']
1216 >>> xpath_tokenizer("./spam.egg")
1217 ['.', '/', 'spam.egg']
1218 >>> xpath_tokenizer(".//{http://spam}egg")
1219 ['.', '//', '{http://spam}egg']
1221 from xml.etree import ElementPath
1223 for op, tag in ElementPath.xpath_tokenizer(p):
1224 out.append(op or tag)
1227 def processinginstruction():
1229 Test ProcessingInstruction directly
1231 >>> ET
.tostring(ET
.ProcessingInstruction('test', 'instruction'))
1232 '<?test instruction?>'
1233 >>> ET
.tostring(ET
.PI('test', 'instruction'))
1234 '<?test instruction?>'
1238 >>> ET
.tostring(ET
.PI('test', '<testing&>'))
1239 '<?test <testing&>?>'
1240 >>> ET
.tostring(ET
.PI('test', u
'<testing&>\xe3'), 'latin1')
1241 "<?xml version='1.0' encoding='latin1'?>\\n<?test <testing&>\\xe3?>"
1245 # xinclude tests (samples from appendix C of the xinclude specification)
1249 XINCLUDE["C1.xml"] = """\
1250 <?xml version
='1.0'?
>
1251 <document xmlns
:xi
="http://www.w3.org/2001/XInclude">
1252 <p
>120 Mz
is adequate
for an average home user
.</p
>
1253 <xi
:include href
="disclaimer.xml"/>
1257 XINCLUDE["disclaimer.xml"] = """\
1258 <?xml version
='1.0'?
>
1260 <p
>The opinions represented herein represent those of the individual
1261 and should
not be interpreted
as official policy endorsed by this
1266 XINCLUDE["C2.xml"] = """\
1267 <?xml version
='1.0'?
>
1268 <document xmlns
:xi
="http://www.w3.org/2001/XInclude">
1269 <p
>This document has been accessed
1270 <xi
:include href
="count.txt" parse
="text"/> times
.</p
>
1274 XINCLUDE["count.txt"] = "324387"
1276 XINCLUDE["C2b.xml"] = """\
1277 <?xml version
='1.0'?
>
1278 <document xmlns
:xi
="http://www.w3.org/2001/XInclude">
1279 <p
>This document has been
<em
>accessed
</em
>
1280 <xi
:include href
="count.txt" parse
="text"/> times
.</p
>
1284 XINCLUDE["C3.xml"] = """\
1285 <?xml version
='1.0'?
>
1286 <document xmlns
:xi
="http://www.w3.org/2001/XInclude">
1287 <p
>The following
is the source of the
"data.xml" resource
:</p
>
1288 <example
><xi
:include href
="data.xml" parse
="text"/></example
>
1292 XINCLUDE["data.xml"] = """\
1293 <?xml version
='1.0'?
>
1295 <item
><![CDATA
[Brooks
& Shields
]]></item
>
1299 XINCLUDE["C5.xml"] = """\
1300 <?xml version
='1.0'?
>
1301 <div xmlns
:xi
="http://www.w3.org/2001/XInclude">
1302 <xi
:include href
="example.txt" parse
="text">
1304 <xi
:include href
="fallback-example.txt" parse
="text">
1305 <xi
:fallback
><a href
="mailto:bob@example.org">Report error
</a
></xi
:fallback
>
1312 XINCLUDE["default.xml"] = """\
1313 <?xml version
='1.0'?
>
1314 <document xmlns
:xi
="http://www.w3.org/2001/XInclude">
1316 <xi
:include href
="{}"/>
1318 """.format(cgi.escape(SIMPLE_XMLFILE, True))
1320 def xinclude_loader(href, parse="xml", encoding=None):
1322 data = XINCLUDE[href]
1324 raise IOError("resource not found")
1326 from xml.etree.ElementTree import XML
1332 Basic inclusion
example (XInclude C
.1)
1334 >>> from xml
.etree
import ElementTree
as ET
1335 >>> from xml
.etree
import ElementInclude
1337 >>> document
= xinclude_loader("C1.xml")
1338 >>> ElementInclude
.include(document
, xinclude_loader
)
1339 >>> print serialize(document
) # C1
1341 <p
>120 Mz
is adequate
for an average home user
.</p
>
1343 <p
>The opinions represented herein represent those of the individual
1344 and should
not be interpreted
as official policy endorsed by this
1349 Textual inclusion
example (XInclude C
.2)
1351 >>> document
= xinclude_loader("C2.xml")
1352 >>> ElementInclude
.include(document
, xinclude_loader
)
1353 >>> print serialize(document
) # C2
1355 <p
>This document has been accessed
1359 Textual inclusion after sibling
element (based on modified XInclude C
.2)
1361 >>> document
= xinclude_loader("C2b.xml")
1362 >>> ElementInclude
.include(document
, xinclude_loader
)
1363 >>> print(serialize(document
)) # C2b
1365 <p
>This document has been
<em
>accessed
</em
>
1369 Textual inclusion of XML
example (XInclude C
.3)
1371 >>> document
= xinclude_loader("C3.xml")
1372 >>> ElementInclude
.include(document
, xinclude_loader
)
1373 >>> print serialize(document
) # C3
1375 <p
>The following
is the source of the
"data.xml" resource
:</p
>
1376 <example
><
;?xml version
='1.0'?
>
;
1378 <
;item
>
;<
;![CDATA
[Brooks
&
; Shields
]]>
;<
;/item
>
;
1383 Fallback
example (XInclude C
.5)
1384 Note
! Fallback support
is not yet implemented
1386 >>> document
= xinclude_loader("C5.xml")
1387 >>> ElementInclude
.include(document
, xinclude_loader
)
1388 Traceback (most recent call last
):
1389 IOError: resource
not found
1390 >>> # print serialize(document) # C5
1393 def xinclude_default():
1395 >>> from xml
.etree
import ElementInclude
1397 >>> document
= xinclude_loader("default.xml")
1398 >>> ElementInclude
.include(document
)
1399 >>> print serialize(document
) # default
1403 <element key
="value">text
</element
>
1404 <element
>text
</element
>tail
1411 # badly formatted xi:include tags
1415 XINCLUDE_BAD["B1.xml"] = """\
1416 <?xml version
='1.0'?
>
1417 <document xmlns
:xi
="http://www.w3.org/2001/XInclude">
1418 <p
>120 Mz
is adequate
for an average home user
.</p
>
1419 <xi
:include href
="disclaimer.xml" parse
="BAD_TYPE"/>
1423 XINCLUDE_BAD["B2.xml"] = """\
1424 <?xml version
='1.0'?
>
1425 <div xmlns
:xi
="http://www.w3.org/2001/XInclude">
1426 <xi
:fallback
></xi
:fallback
>
1430 def xinclude_failures():
1432 Test failure to locate included XML
file.
1434 >>> from xml
.etree
import ElementInclude
1436 >>> def none_loader(href
, parser
, encoding
=None):
1439 >>> document
= ET
.XML(XINCLUDE
["C1.xml"])
1440 >>> ElementInclude
.include(document
, loader
=none_loader
)
1441 Traceback (most recent call last
):
1442 FatalIncludeError
: cannot load
'disclaimer.xml' as 'xml'
1444 Test failure to locate included text
file.
1446 >>> document
= ET
.XML(XINCLUDE
["C2.xml"])
1447 >>> ElementInclude
.include(document
, loader
=none_loader
)
1448 Traceback (most recent call last
):
1449 FatalIncludeError
: cannot load
'count.txt' as 'text'
1451 Test bad parse
type.
1453 >>> document
= ET
.XML(XINCLUDE_BAD
["B1.xml"])
1454 >>> ElementInclude
.include(document
, loader
=none_loader
)
1455 Traceback (most recent call last
):
1456 FatalIncludeError
: unknown parse
type in xi
:include
tag ('BAD_TYPE')
1458 Test xi
:fallback outside xi
:include
.
1460 >>> document
= ET
.XML(XINCLUDE_BAD
["B2.xml"])
1461 >>> ElementInclude
.include(document
, loader
=none_loader
)
1462 Traceback (most recent call last
):
1463 FatalIncludeError
: xi
:fallback tag must be child of xi
:include ('{http://www.w3.org/2001/XInclude}fallback')
1466 # --------------------------------------------------------------------
1469 def bug_xmltoolkit21():
1472 marshaller gives obscure errors
for non
-string values
1474 >>> elem
= ET
.Element(123)
1475 >>> serialize(elem
) # tag
1476 Traceback (most recent call last
):
1477 TypeError: cannot serialize
123 (type int)
1478 >>> elem
= ET
.Element("elem")
1480 >>> serialize(elem
) # text
1481 Traceback (most recent call last
):
1482 TypeError: cannot serialize
123 (type int)
1483 >>> elem
= ET
.Element("elem")
1485 >>> serialize(elem
) # tail
1486 Traceback (most recent call last
):
1487 TypeError: cannot serialize
123 (type int)
1488 >>> elem
= ET
.Element("elem")
1489 >>> elem
.set(123, "123")
1490 >>> serialize(elem
) # attribute key
1491 Traceback (most recent call last
):
1492 TypeError: cannot serialize
123 (type int)
1493 >>> elem
= ET
.Element("elem")
1494 >>> elem
.set("123", 123)
1495 >>> serialize(elem
) # attribute value
1496 Traceback (most recent call last
):
1497 TypeError: cannot serialize
123 (type int)
1501 def bug_xmltoolkit25():
1504 typo
in ElementTree
.findtext
1506 >>> elem
= ET
.XML(SAMPLE_XML
)
1507 >>> tree
= ET
.ElementTree(elem
)
1508 >>> tree
.findtext("tag")
1510 >>> tree
.findtext("section/tag")
1515 def bug_xmltoolkit28():
1518 .//tag causes exceptions
1520 >>> tree
= ET
.XML("<doc><table><tbody/></table></doc>")
1521 >>> summarize_list(tree
.findall(".//thead"))
1523 >>> summarize_list(tree
.findall(".//tbody"))
1528 def bug_xmltoolkitX1():
1531 dump() doesn
't flush the output buffer
1533 >>> tree = ET.XML("<doc><table><tbody/></table></doc>")
1534 >>> ET.dump(tree); sys.stdout.write("tail")
1535 <doc><table><tbody /></table></doc>
1540 def bug_xmltoolkit39():
1543 non-ascii element and attribute names doesn't work
1545 >>> tree
= ET
.XML("<?xml version='1.0' encoding='iso-8859-1'?><t\xe4g />")
1546 >>> ET
.tostring(tree
, "utf-8")
1549 >>> tree
= ET
.XML("<?xml version='1.0' encoding='iso-8859-1'?><tag \xe4ttr='välue' />")
1551 {u
'\\xe4ttr': u
'v\\xe4lue'}
1552 >>> ET
.tostring(tree
, "utf-8")
1553 '<tag \\xc3\\xa4ttr="v\\xc3\\xa4lue" />'
1555 >>> tree
= ET
.XML("<?xml version='1.0' encoding='iso-8859-1'?><t\xe4g>text</t\xe4g>")
1556 >>> ET
.tostring(tree
, "utf-8")
1557 '<t\\xc3\\xa4g>text</t\\xc3\\xa4g>'
1559 >>> tree
= ET
.Element(u
"t\u00e4g")
1560 >>> ET
.tostring(tree
, "utf-8")
1563 >>> tree
= ET
.Element("tag")
1564 >>> tree
.set(u
"\u00e4ttr", u
"v\u00e4lue")
1565 >>> ET
.tostring(tree
, "utf-8")
1566 '<tag \\xc3\\xa4ttr="v\\xc3\\xa4lue" />'
1570 def bug_xmltoolkit54():
1573 problems handling internally defined entities
1575 >>> e
= ET
.XML("<!DOCTYPE doc [<!ENTITY ldots '舰'>]><doc>&ldots;</doc>")
1577 '<doc>舰</doc>'
1581 def bug_xmltoolkit55():
1584 make sure we
're reporting the first error, not the last
1586 >>> e = ET.XML("<!DOCTYPE doc SYSTEM 'doc
.dtd
'><doc>&ldots;&ndots;&rdots;</doc>")
1587 Traceback (most recent call last):
1588 ParseError: undefined entity &ldots;: line 1, column 36
1592 class ExceptionFile:
1599 Handle crash in stream source.
1600 >>> tree = ET.parse(ExceptionFile())
1601 Traceback (most recent call last):
1606 XMLTOOLKIT62_DOC = """<?xml version="1.0" encoding="UTF-8"?>
1607 <!DOCTYPE patent-application-publication SYSTEM "pap-v15-2001-01-31.dtd" []>
1608 <patent-application-publication>
1610 <paragraph id="A-0001" lvl="0">A new cultivar of Begonia plant named ‘BCT9801BEG’.</paragraph>
1612 </patent-application-publication>"""
1618 Don't crash when using custom entities
.
1621 u
'A new cultivar of Begonia plant named \u2018BCT9801BEG\u2019.'
1624 ENTITIES = {u'rsquo': u'\u2019', u'lsquo': u'\u2018'}
1625 parser = ET.XMLTreeBuilder()
1626 parser.entity.update(ENTITIES)
1627 parser.feed(XMLTOOLKIT62_DOC)
1629 return t.find('.//paragraph').text
1634 Check reference leak
.
1636 >>> count
= sys
.getrefcount(None)
1637 >>> for i
in range(1000):
1639 >>> sys
.getrefcount(None) - count
1643 tree = ET.TreeBuilder()
1644 tree.start("tag", {})
1648 # --------------------------------------------------------------------
1651 def bug_200708_newline():
1654 Preserve newlines
in attributes
.
1656 >>> e
= ET
.Element('SomeTag', text
="def _f():\n return 3\n")
1658 '<SomeTag text="def _f(): return 3 " />'
1659 >>> ET
.XML(ET
.tostring(e
)).get("text")
1660 'def _f():\n return 3\n'
1661 >>> ET
.tostring(ET
.XML(ET
.tostring(e
)))
1662 '<SomeTag text="def _f(): return 3 " />'
1666 def bug_200708_close():
1669 Test default builder
.
1670 >>> parser
= ET
.XMLParser() # default
1671 >>> parser
.feed("<element>some text</element>")
1672 >>> summarize(parser
.close())
1675 Test custom builder
.
1676 >>> class EchoTarget
:
1677 ... def close(self
):
1678 ... return ET
.Element("element") # simulate root
1679 >>> parser
= ET
.XMLParser(EchoTarget())
1680 >>> parser
.feed("<element>some text</element>")
1681 >>> summarize(parser
.close())
1686 def bug_200709_default_namespace():
1689 >>> e
= ET
.Element("{default}elem")
1690 >>> s
= ET
.SubElement(e
, "{default}elem")
1691 >>> serialize(e
, default_namespace
="default") # 1
1692 '<elem xmlns="default"><elem /></elem>'
1694 >>> e
= ET
.Element("{default}elem")
1695 >>> s
= ET
.SubElement(e
, "{default}elem")
1696 >>> s
= ET
.SubElement(e
, "{not-default}elem")
1697 >>> serialize(e
, default_namespace
="default") # 2
1698 '<elem xmlns="default" xmlns:ns1="not-default"><elem /><ns1:elem /></elem>'
1700 >>> e
= ET
.Element("{default}elem")
1701 >>> s
= ET
.SubElement(e
, "{default}elem")
1702 >>> s
= ET
.SubElement(e
, "elem") # unprefixed name
1703 >>> serialize(e
, default_namespace
="default") # 3
1704 Traceback (most recent call last
):
1705 ValueError: cannot use non
-qualified names with default_namespace option
1709 def bug_200709_register_namespace():
1712 >>> ET
.tostring(ET
.Element("{http://namespace.invalid/does/not/exist/}title"))
1713 '<ns0:title xmlns:ns0="http://namespace.invalid/does/not/exist/" />'
1714 >>> ET
.register_namespace("foo", "http://namespace.invalid/does/not/exist/")
1715 >>> ET
.tostring(ET
.Element("{http://namespace.invalid/does/not/exist/}title"))
1716 '<foo:title xmlns:foo="http://namespace.invalid/does/not/exist/" />'
1718 And the Dublin Core namespace
is in the default
list:
1720 >>> ET
.tostring(ET
.Element("{http://purl.org/dc/elements/1.1/}title"))
1721 '<dc:title xmlns:dc="http://purl.org/dc/elements/1.1/" />'
1725 def bug_200709_element_comment():
1728 Not sure
if this can be fixed
, really (since the serializer needs
1729 ET
.Comment
, not cET
.comment
).
1731 >>> a
= ET
.Element('a')
1732 >>> a
.append(ET
.Comment('foo'))
1733 >>> a
[0].tag
== ET
.Comment
1736 >>> a
= ET
.Element('a')
1737 >>> a
.append(ET
.PI('foo'))
1738 >>> a
[0].tag
== ET
.PI
1743 def bug_200709_element_insert():
1746 >>> a
= ET
.Element('a')
1747 >>> b
= ET
.SubElement(a
, 'b')
1748 >>> c
= ET
.SubElement(a
, 'c')
1749 >>> d
= ET
.Element('d')
1751 >>> summarize_list(a
)
1754 >>> summarize_list(a
)
1755 ['d', 'b', 'd', 'c']
1759 def bug_200709_iter_comment():
1762 >>> a
= ET
.Element('a')
1763 >>> b
= ET
.SubElement(a
, 'b')
1764 >>> comment_b
= ET
.Comment("TEST-b")
1765 >>> b
.append(comment_b
)
1766 >>> summarize_list(a
.iter(ET
.Comment
))
1771 # --------------------------------------------------------------------
1772 # reported on bugs.python.org
1777 >>> bob
= ET
.TreeBuilder()
1778 >>> e
= bob
.data("data")
1779 >>> e
= bob
.start("tag", {})
1780 >>> e
= bob
.end("tag")
1787 def check_issue6233():
1790 >>> e
= ET
.XML("<?xml version='1.0' encoding='utf-8'?><body>t\\xc3\\xa3g</body>")
1791 >>> ET
.tostring(e
, 'ascii')
1792 "<?xml version='1.0' encoding='ascii'?>\\n<body>tãg</body>"
1793 >>> e
= ET
.XML("<?xml version='1.0' encoding='iso-8859-1'?><body>t\\xe3g</body>")
1794 >>> ET
.tostring(e
, 'ascii')
1795 "<?xml version='1.0' encoding='ascii'?>\\n<body>tãg</body>"
1799 def check_issue3151():
1802 >>> e
= ET
.XML('<prefix:localname xmlns:prefix="${stuff}"/>')
1804 '{${stuff}}localname'
1805 >>> t
= ET
.ElementTree(e
)
1807 '<ns0:localname xmlns:ns0="${stuff}" />'
1811 def check_issue6565():
1814 >>> elem
= ET
.XML("<body><tag/></body>")
1815 >>> summarize_list(elem
)
1817 >>> newelem
= ET
.XML(SAMPLE_XML
)
1818 >>> elem
[:] = newelem
[:]
1819 >>> summarize_list(elem
)
1820 ['tag', 'tag', 'section']
1824 # --------------------------------------------------------------------
1827 class CleanContext(object):
1828 """Provide default namespace mapping
and path cache
."""
1829 checkwarnings = None
1831 def __init__(self, quiet=False):
1832 if sys.flags.optimize >= 2:
1833 # under -OO, doctests cannot be run and therefore not all warnings
1837 # Search behaviour is broken if search path starts with "/".
1838 ("This search is broken in 1.3 and earlier, and will be fixed "
1839 "in a future version. If you rely on the current behaviour, "
1840 "change it to '.+'", FutureWarning),
1841 # Element.getchildren() and Element.getiterator() are deprecated.
1842 ("This method will be removed in future versions. "
1843 "Use .+ instead.", DeprecationWarning),
1844 ("This method will be removed in future versions. "
1845 "Use .+ instead.", PendingDeprecationWarning),
1846 # XMLParser.doctype() is deprecated.
1847 ("This method of XMLParser is deprecated. Define doctype.. "
1848 "method on the TreeBuilder target.", DeprecationWarning))
1849 self.checkwarnings = test_support.check_warnings(*deprecations,
1852 def __enter__(self):
1853 from xml.etree import ElementTree
1854 self._nsmap = ElementTree._namespace_map
1855 self._path_cache = ElementTree.ElementPath._cache
1856 # Copy the default namespace mapping
1857 ElementTree._namespace_map = self._nsmap.copy()
1858 # Copy the path cache (should be empty)
1859 ElementTree.ElementPath._cache = self._path_cache.copy()
1860 self.checkwarnings.__enter__()
1862 def __exit__(self, *args):
1863 from xml.etree import ElementTree
1864 # Restore mapping and path cache
1865 ElementTree._namespace_map = self._nsmap
1866 ElementTree.ElementPath._cache = self._path_cache
1867 self.checkwarnings.__exit__(*args)
1870 def test_main(module_name='xml.etree.ElementTree'):
1871 from test import test_xml_etree
1873 use_py_module = (module_name == 'xml.etree.ElementTree')
1875 # The same doctests are used for both the Python and the C implementations
1876 assert test_xml_etree.ET.__name__ == module_name
1878 # XXX the C module should give the same warnings as the Python module
1879 with CleanContext(quiet=not use_py_module):
1880 test_support.run_doctest(test_xml_etree, verbosity=True)
1882 # The module should not be changed by the tests
1883 assert test_xml_etree.ET.__name__ == module_name
1885 if __name__ == '__main__':