1
2
3
4
5
6
7
8
9
10
11
12 import re, sys
13
15 if sys.version_info[0] < 3:
16 return sys.stdout
17 class bytes_stdout(object):
18 def write(self, data):
19 if isinstance(data, bytes):
20 data = data.decode('ISO8859-1')
21 sys.stdout.write(data)
22 return bytes_stdout()
23
24 try:
25 from StringIO import StringIO as BytesIO
26 except ImportError:
27 from io import BytesIO
28
29 from lxml import etree as ElementTree
30 from lxml import _elementpath as ElementPath
31 from lxml import ElementInclude
32 ET = ElementTree
33
34
35
36
37
38
39
41 xml_data = re.sub(r'\s*xmlns:[a-z0-9]+="http://www.w3.org/2001/XInclude"', '', xml_data)
42 xml_data = xml_data.replace(' />', '/>')
43 if xml_data[-1:] == '\n':
44 xml_data = xml_data[:-1]
45 return xml_data
46
62
65
68
73
74 SAMPLE_XML = ElementTree.XML("""
75 <body>
76 <tag class='a'>text</tag>
77 <tag class='b' />
78 <section>
79 <tag class='b' id='inner'>subtext</tag>
80 </section>
81 </body>
82 """)
83
84
85
86
88 len(string)
89 for char in string:
90 if len(char) != 1:
91 print("expected one-character string, got %r" % char)
92 new_string = string + ""
93 new_string = string + " "
94 string[:0]
95
100
102 len(mapping)
103 keys = mapping.keys()
104 items = mapping.items()
105 for key in keys:
106 item = mapping[key]
107 mapping["key"] = "value"
108 if mapping["key"] != "value":
109 print("expected value string, got %r" % mapping["key"])
110
126
129
130
131
132
134 """
135 >>> from elementtree.ElementTree import *
136 >>> from elementtree.ElementInclude import *
137 >>> from elementtree.ElementPath import *
138 >>> from elementtree.HTMLTreeBuilder import *
139 >>> from elementtree.SimpleXMLWriter import *
140 >>> from elementtree.TidyTools import *
141 """
142
143
144 del sanity
145
147 """
148 >>> ElementTree.VERSION
149 '1.3a2'
150 """
151
152
153 del version
154
156 """
157 Test element tree interface.
158
159 >>> element = ElementTree.Element("tag")
160 >>> check_element(element)
161 >>> tree = ElementTree.ElementTree(element)
162 >>> check_element_tree(tree)
163 """
164
166 """
167 >>> elem = ElementTree.XML("<body><tag/></body>")
168 >>> serialize(elem)
169 '<body><tag/></body>'
170 >>> e = ElementTree.Element("tag2")
171 >>> elem.append(e)
172 >>> serialize(elem)
173 '<body><tag/><tag2/></body>'
174 >>> elem.remove(e)
175 >>> serialize(elem)
176 '<body><tag/></body>'
177 >>> elem.insert(0, e)
178 >>> serialize(elem)
179 '<body><tag2/><tag/></body>'
180 >>> elem.remove(e)
181 >>> elem.extend([e])
182 >>> serialize(elem)
183 '<body><tag/><tag2/></body>'
184 >>> elem.remove(e)
185 """
186
188 """
189 Test find methods using the elementpath fallback.
190
191 >>> CurrentElementPath = ElementTree.ElementPath
192 >>> ElementTree.ElementPath = ElementTree._SimpleElementPath()
193 >>> elem = SAMPLE_XML
194 >>> elem.find("tag").tag
195 'tag'
196 >>> ElementTree.ElementTree(elem).find("tag").tag
197 'tag'
198 >>> elem.findtext("tag")
199 'text'
200 >>> elem.findtext("tog")
201 >>> elem.findtext("tog", "default")
202 'default'
203 >>> ElementTree.ElementTree(elem).findtext("tag")
204 'text'
205 >>> summarize_list(elem.findall("tag"))
206 ['tag', 'tag']
207 >>> summarize_list(elem.findall(".//tag"))
208 ['tag', 'tag', 'tag']
209
210 Path syntax doesn't work in this case.
211
212 >>> elem.find("section/tag")
213 >>> elem.findtext("section/tag")
214 >>> elem.findall("section/tag")
215 []
216
217 >>> ElementTree.ElementPath = CurrentElementPath
218 """
219
220
221 del simplefind
222
224 """
225 Test find methods (including xpath syntax).
226
227 >>> elem = SAMPLE_XML
228 >>> elem.find("tag").tag
229 'tag'
230 >>> ElementTree.ElementTree(elem).find("tag").tag
231 'tag'
232 >>> elem.find("section/tag").tag
233 'tag'
234 >>> ElementTree.ElementTree(elem).find("section/tag").tag
235 'tag'
236 >>> elem.findtext("tag")
237 'text'
238 >>> elem.findtext("tog")
239 >>> elem.findtext("tog", "default")
240 'default'
241 >>> ElementTree.ElementTree(elem).findtext("tag")
242 'text'
243 >>> elem.findtext("section/tag")
244 'subtext'
245 >>> ElementTree.ElementTree(elem).findtext("section/tag")
246 'subtext'
247 >>> summarize_list(elem.findall("tag"))
248 ['tag', 'tag']
249 >>> summarize_list(elem.findall("*"))
250 ['tag', 'tag', 'section']
251 >>> summarize_list(elem.findall(".//tag"))
252 ['tag', 'tag', 'tag']
253 >>> summarize_list(elem.findall("section/tag"))
254 ['tag']
255 >>> summarize_list(elem.findall("section//tag"))
256 ['tag']
257 >>> summarize_list(elem.findall("section/*"))
258 ['tag']
259 >>> summarize_list(elem.findall("section//*"))
260 ['tag']
261 >>> summarize_list(elem.findall("section/.//*"))
262 ['tag']
263 >>> summarize_list(elem.findall("*/*"))
264 ['tag']
265 >>> summarize_list(elem.findall("*//*"))
266 ['tag']
267 >>> summarize_list(elem.findall("*/tag"))
268 ['tag']
269 >>> summarize_list(elem.findall("*/./tag"))
270 ['tag']
271 >>> summarize_list(elem.findall("./tag"))
272 ['tag', 'tag']
273 >>> summarize_list(elem.findall(".//tag"))
274 ['tag', 'tag', 'tag']
275 >>> summarize_list(elem.findall("././tag"))
276 ['tag', 'tag']
277 >>> summarize_list(elem.findall(".//tag[@class]"))
278 ['tag', 'tag', 'tag']
279 >>> summarize_list(elem.findall(".//tag[@class='a']"))
280 ['tag']
281 >>> summarize_list(elem.findall(".//tag[@class='b']"))
282 ['tag', 'tag']
283 >>> summarize_list(elem.findall(".//tag[@id]"))
284 ['tag']
285 >>> summarize_list(elem.findall(".//section[tag]"))
286 ['section']
287 >>> summarize_list(elem.findall(".//section[element]"))
288 []
289 >>> summarize_list(elem.findall("../tag"))
290 []
291 >>> summarize_list(elem.findall("section/../tag"))
292 ['tag', 'tag']
293 >>> summarize_list(ElementTree.ElementTree(elem).findall("./tag"))
294 ['tag', 'tag']
295
296 FIXME: ET's Path module handles this case incorrectly; this gives
297 a warning in 1.3, and the behaviour will be modified in 1.4.
298
299 >>> summarize_list(ElementTree.ElementTree(elem).findall("/tag"))
300 ['tag', 'tag']
301 """
302
304 """
305 Check bad or unsupported path expressions.
306
307 >>> elem = SAMPLE_XML
308 >>> elem.findall("/tag")
309 Traceback (most recent call last):
310 SyntaxError: cannot use absolute path on element
311
312 # this is supported in ET 1.3:
313 #>>> elem.findall("section//")
314 #Traceback (most recent call last):
315 #SyntaxError: invalid path
316 """
317
319 """
320 Test parsing from file.
321
322 >>> tree = ElementTree.parse("samples/simple.xml")
323 >>> normalize_crlf(tree)
324 >>> tree.write(stdout())
325 <root>
326 <element key="value">text</element>
327 <element>text</element>tail
328 <empty-element/>
329 </root>
330 >>> tree = ElementTree.parse("samples/simple-ns.xml")
331 >>> normalize_crlf(tree)
332 >>> tree.write(stdout())
333 <root xmlns="http://namespace/">
334 <element key="value">text</element>
335 <element>text</element>tail
336 <empty-element/>
337 </root>
338
339 ## <ns0:root xmlns:ns0="http://namespace/">
340 ## <ns0:element key="value">text</ns0:element>
341 ## <ns0:element>text</ns0:element>tail
342 ## <ns0:empty-element/>
343 ## </ns0:root>
344 """
345
347 """
348 Test HTML parsing.
349
350 >>> # p = HTMLTreeBuilder.TreeBuilder()
351 >>> p = ElementTree.HTMLParser()
352 >>> p.feed("<p><p>spam<b>egg</b></p>")
353 >>> serialize(p.close())
354 '<p>spam<b>egg</b></p>'
355 """
356
357
358 del parsehtml
359
361 r"""
362 >>> element = ElementTree.XML("<html><body>text</body></html>")
363 >>> ElementTree.ElementTree(element).write(stdout())
364 <html><body>text</body></html>
365 >>> element = ElementTree.fromstring("<html><body>text</body></html>")
366 >>> ElementTree.ElementTree(element).write(stdout())
367 <html><body>text</body></html>
368
369 ## >>> sequence = ["<html><body>", "text</bo", "dy></html>"]
370 ## >>> element = ElementTree.fromstringlist(sequence)
371 ## >>> ElementTree.ElementTree(element).write(stdout())
372 ## <html><body>text</body></html>
373
374 >>> print(repr(ElementTree.tostring(element)).lstrip('b'))
375 '<html><body>text</body></html>'
376
377 # looks different in lxml
378 # >>> print(ElementTree.tostring(element, "ascii"))
379 # <?xml version='1.0' encoding='ascii'?>
380 # <html><body>text</body></html>
381
382 >>> _, ids = ElementTree.XMLID("<html><body>text</body></html>")
383 >>> len(ids)
384 0
385 >>> _, ids = ElementTree.XMLID("<html><body id='body'>text</body></html>")
386 >>> len(ids)
387 1
388 >>> ids["body"].tag
389 'body'
390 """
391
393 """
394 Test the xmllib-based parser.
395
396 >>> from elementtree import SimpleXMLTreeBuilder
397 >>> parser = SimpleXMLTreeBuilder.TreeBuilder()
398 >>> tree = ElementTree.parse("samples/simple.xml", parser)
399 >>> normalize_crlf(tree)
400 >>> tree.write(sys.stdout)
401 <root>
402 <element key="value">text</element>
403 <element>text</element>tail
404 <empty-element />
405 </root>
406 """
407
408
409 del simpleparsefile
410
412 """
413 Test iterparse interface.
414
415 >>> iterparse = ElementTree.iterparse
416
417 >>> context = iterparse("samples/simple.xml")
418 >>> for action, elem in context:
419 ... print("%s %s" % (action, elem.tag))
420 end element
421 end element
422 end empty-element
423 end root
424 >>> context.root.tag
425 'root'
426
427 >>> context = iterparse("samples/simple-ns.xml")
428 >>> for action, elem in context:
429 ... print("%s %s" % (action, elem.tag))
430 end {http://namespace/}element
431 end {http://namespace/}element
432 end {http://namespace/}empty-element
433 end {http://namespace/}root
434
435 >>> events = ()
436 >>> context = iterparse("samples/simple.xml", events)
437 >>> for action, elem in context:
438 ... print("%s %s" % (action, elem.tag))
439
440 >>> events = ()
441 >>> context = iterparse("samples/simple.xml", events=events)
442 >>> for action, elem in context:
443 ... print("%s %s" % (action, elem.tag))
444
445 >>> events = ("start", "end")
446 >>> context = iterparse("samples/simple.xml", events)
447 >>> for action, elem in context:
448 ... print("%s %s" % (action, elem.tag))
449 start root
450 start element
451 end element
452 start element
453 end element
454 start empty-element
455 end empty-element
456 end root
457
458 >>> events = ("start", "end", "start-ns", "end-ns")
459 >>> context = iterparse("samples/simple-ns.xml", events)
460 >>> for action, elem in context:
461 ... if action in ("start", "end"):
462 ... print("%s %s" % (action, elem.tag))
463 ... else:
464 ... print("%s %s" % (action, elem))
465 start-ns ('', 'http://namespace/')
466 start {http://namespace/}root
467 start {http://namespace/}element
468 end {http://namespace/}element
469 start {http://namespace/}element
470 end {http://namespace/}element
471 start {http://namespace/}empty-element
472 end {http://namespace/}empty-element
473 end {http://namespace/}root
474 end-ns None
475
476 """
477
479 """
480 Test the "fancy" parser.
481
482 Sanity check.
483 >>> from elementtree import XMLTreeBuilder
484 >>> parser = XMLTreeBuilder.FancyTreeBuilder()
485 >>> tree = ElementTree.parse("samples/simple.xml", parser)
486 >>> normalize_crlf(tree)
487 >>> tree.write(sys.stdout)
488 <root>
489 <element key="value">text</element>
490 <element>text</element>tail
491 <empty-element />
492 </root>
493
494 Callback check.
495 >>> class MyFancyParser(XMLTreeBuilder.FancyTreeBuilder):
496 ... def start(self, elem):
497 ... print("START %s" % elem.tag)
498 ... def end(self, elem):
499 ... print("END %s" % elem.tag)
500 >>> parser = MyFancyParser()
501 >>> tree = ElementTree.parse("samples/simple.xml", parser)
502 START root
503 START element
504 END element
505 START element
506 END element
507 START empty-element
508 END empty-element
509 END root
510 """
511
512
513 del fancyparsefile
514
516 """
517 >>> elem = ElementTree.Element("tag")
518 >>> elem.text = "text"
519 >>> serialize(elem)
520 '<tag>text</tag>'
521 >>> ElementTree.SubElement(elem, "subtag").text = "subtext"
522 >>> serialize(elem)
523 '<tag>text<subtag>subtext</subtag></tag>'
524
525 ## Test tag suppression
526 ## >>> elem.tag = None
527 ## >>> serialize(elem)
528 ## 'text<subtag>subtext</subtag>'
529 """
530
532 """
533 >>> elem = ElementTree.XML("<html><body>text</body></html>")
534 >>> print(repr(ElementTree.tostring(elem)).lstrip('b'))
535 '<html><body>text</body></html>'
536 >>> elem = ElementTree.fromstring("<html><body>text</body></html>")
537 >>> print(repr(ElementTree.tostring(elem)).lstrip('b'))
538 '<html><body>text</body></html>'
539 """
540
542 r"""
543 Test encoding issues.
544
545 >>> elem = ElementTree.Element("tag")
546 >>> elem.text = u'abc'
547 >>> serialize(elem)
548 '<tag>abc</tag>'
549 >>> serialize(elem, encoding="utf-8")
550 '<tag>abc</tag>'
551 >>> serialize(elem, encoding="us-ascii")
552 '<tag>abc</tag>'
553 >>> serialize(elem, encoding="iso-8859-1").lower()
554 "<?xml version='1.0' encoding='iso-8859-1'?>\n<tag>abc</tag>"
555
556 >>> elem.text = "<&\"\'>"
557 >>> serialize(elem)
558 '<tag><&"\'></tag>'
559 >>> serialize(elem, encoding="utf-8")
560 '<tag><&"\'></tag>'
561 >>> serialize(elem, encoding="us-ascii") # cdata characters
562 '<tag><&"\'></tag>'
563 >>> serialize(elem, encoding="iso-8859-1").lower()
564 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag><&"\'></tag>'
565
566 >>> elem.attrib["key"] = "<&\"\'>"
567 >>> elem.text = None
568 >>> serialize(elem)
569 '<tag key="<&"\'>"/>'
570 >>> serialize(elem, encoding="utf-8")
571 '<tag key="<&"\'>"/>'
572 >>> serialize(elem, encoding="us-ascii")
573 '<tag key="<&"\'>"/>'
574 >>> serialize(elem, encoding="iso-8859-1").lower()
575 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag key="<&"\'>"/>'
576
577 >>> elem.text = u'\xe5\xf6\xf6<>'
578 >>> elem.attrib.clear()
579 >>> serialize(elem)
580 '<tag>åöö<></tag>'
581 >>> serialize(elem, encoding="utf-8")
582 '<tag>\xc3\xa5\xc3\xb6\xc3\xb6<></tag>'
583 >>> serialize(elem, encoding="us-ascii")
584 '<tag>åöö<></tag>'
585 >>> serialize(elem, encoding="iso-8859-1").lower()
586 "<?xml version='1.0' encoding='iso-8859-1'?>\n<tag>\xe5\xf6\xf6<></tag>"
587
588 >>> elem.attrib["key"] = u'\xe5\xf6\xf6<>'
589 >>> elem.text = None
590 >>> serialize(elem)
591 '<tag key="åöö<>"/>'
592 >>> serialize(elem, encoding="utf-8")
593 '<tag key="\xc3\xa5\xc3\xb6\xc3\xb6<>"/>'
594 >>> serialize(elem, encoding="us-ascii")
595 '<tag key="åöö<>"/>'
596 >>> serialize(elem, encoding="iso-8859-1").lower()
597 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag key="\xe5\xf6\xf6<>"/>'
598 """
599
600 if sys.version_info[0] >= 3:
601 encoding.__doc__ = encoding.__doc__.replace("u'", "'")
602
604 r"""
605 Test serialization methods.
606
607 >>> e = ET.XML("<html><link/><script>1 < 2</script></html>")
608 >>> e.tail = "\n"
609 >>> serialize(e)
610 '<html><link /><script>1 < 2</script></html>\n'
611 >>> serialize(e, method=None)
612 '<html><link /><script>1 < 2</script></html>\n'
613 >>> serialize(e, method="xml")
614 '<html><link /><script>1 < 2</script></html>\n'
615 >>> serialize(e, method="html")
616 '<html><link><script>1 < 2</script></html>\n'
617 >>> serialize(e, method="text")
618 '1 < 2\n'
619
620 """
621
622
623 del methods
624
626 """
627 Test iterators.
628
629 >>> e = ET.XML("<html><body>this is a <i>paragraph</i>.</body>..</html>")
630 >>> summarize_list(e.iter())
631 ['html', 'body', 'i']
632 >>> summarize_list(e.find("body").iter())
633 ['body', 'i']
634 >>> "".join(e.itertext())
635 'this is a paragraph...'
636 >>> "".join(e.find("body").itertext())
637 'this is a paragraph.'
638 """
639
640 ENTITY_XML = """\
641 <!DOCTYPE points [
642 <!ENTITY % user-entities SYSTEM 'user-entities.xml'>
643 %user-entities;
644 ]>
645 <document>&entity;</document>
646 """
647
649 """
650 Test entity handling.
651
652 1) bad entities
653
654 >>> ElementTree.XML("<document>&entity;</document>")
655 Traceback (most recent call last):
656 ExpatError: undefined entity: line 1, column 10
657
658 >>> ElementTree.XML(ENTITY_XML)
659 Traceback (most recent call last):
660 ExpatError: undefined entity &entity;: line 5, column 10
661
662 (add more tests here)
663
664 """
665
666
667 del entity
668
670 """
671 Test error handling.
672
673 >>> error("foo").position
674 (1, 0)
675 >>> error("<tag>&foo;</tag>").position
676 (1, 5)
677 >>> error("foobar<").position
678 (1, 6)
679
680 """
681 try:
682 ET.XML(xml)
683 except ET.ParseError:
684 return sys.exc_value
685
686
687 del error
688
690 """
691 Test namespace issues.
692
693 1) xml namespace
694
695 >>> elem = ElementTree.XML("<tag xml:lang='en' />")
696 >>> serialize(elem) # 1.1
697 '<tag xml:lang="en"/>'
698
699 2) other "well-known" namespaces
700
701 >>> elem = ElementTree.XML("<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' />")
702 >>> serialize(elem) # 2.1
703 '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>'
704
705 >>> elem = ElementTree.XML("<html:html xmlns:html='http://www.w3.org/1999/xhtml' />")
706 >>> serialize(elem) # 2.2
707 '<html:html xmlns:html="http://www.w3.org/1999/xhtml"/>'
708
709 >>> elem = ElementTree.XML("<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope' />")
710 >>> serialize(elem) # 2.3
711 '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"/>'
712
713 3) unknown namespaces
714
715 """
716
718 """
719 Test QName handling.
720
721 1) decorated tags
722
723 >>> elem = ElementTree.Element("{uri}tag")
724 >>> serialize(elem) # 1.1
725 '<ns0:tag xmlns:ns0="uri"/>'
726 >>> elem = ElementTree.Element(ElementTree.QName("{uri}tag"))
727 >>> serialize(elem) # 1.2
728 '<ns0:tag xmlns:ns0="uri"/>'
729 >>> elem = ElementTree.Element(ElementTree.QName("uri", "tag"))
730 >>> serialize(elem) # 1.3
731 '<ns0:tag xmlns:ns0="uri"/>'
732
733 # ns/attribute order ...
734
735 ## 2) decorated attributes
736
737 ## >>> elem.clear()
738 ## >>> elem.attrib["{uri}key"] = "value"
739 ## >>> serialize(elem) # 2.1
740 ## '<ns0:tag ns0:key="value" xmlns:ns0="uri"/>'
741
742 ## >>> elem.clear()
743 ## >>> elem.attrib[ElementTree.QName("{uri}key")] = "value"
744 ## >>> serialize(elem) # 2.2
745 ## '<ns0:tag ns0:key="value" xmlns:ns0="uri"/>'
746
747 ## 3) decorated values are not converted by default, but the
748 ## QName wrapper can be used for values
749
750 ## >>> elem.clear()
751 ## >>> elem.attrib["{uri}key"] = "{uri}value"
752 ## >>> serialize(elem) # 3.1
753 ## '<ns0:tag ns0:key="{uri}value" xmlns:ns0="uri"/>'
754
755 ## >>> elem.clear()
756 ## >>> elem.attrib["{uri}key"] = ElementTree.QName("{uri}value")
757 ## >>> serialize(elem) # 3.2
758 ## '<ns0:tag ns0:key="ns0:value" xmlns:ns0="uri"/>'
759
760 ## >>> elem.clear()
761 ## >>> subelem = ElementTree.Element("tag")
762 ## >>> subelem.attrib["{uri1}key"] = ElementTree.QName("{uri2}value")
763 ## >>> elem.append(subelem)
764 ## >>> elem.append(subelem)
765 ## >>> serialize(elem) # 3.3
766 ## '<ns0:tag xmlns:ns0="uri"><tag ns1:key="ns2:value" xmlns:ns1="uri1" xmlns:ns2="uri2"/><tag ns1:key="ns2:value" xmlns:ns1="uri1" xmlns:ns2="uri2"/></ns0:tag>'
767
768 """
769
771 """
772 Test the XPath tokenizer.
773
774 >>> # tests from the xml specification
775 >>> xpath_tokenizer("*")
776 ['*']
777 >>> xpath_tokenizer("text()")
778 ['text', '()']
779 >>> xpath_tokenizer("@name")
780 ['@', 'name']
781 >>> xpath_tokenizer("@*")
782 ['@', '*']
783 >>> xpath_tokenizer("para[1]")
784 ['para', '[', '1', ']']
785 >>> xpath_tokenizer("para[last()]")
786 ['para', '[', 'last', '()', ']']
787 >>> xpath_tokenizer("*/para")
788 ['*', '/', 'para']
789 >>> xpath_tokenizer("/doc/chapter[5]/section[2]")
790 ['/', 'doc', '/', 'chapter', '[', '5', ']', '/', 'section', '[', '2', ']']
791 >>> xpath_tokenizer("chapter//para")
792 ['chapter', '//', 'para']
793 >>> xpath_tokenizer("//para")
794 ['//', 'para']
795 >>> xpath_tokenizer("//olist/item")
796 ['//', 'olist', '/', 'item']
797 >>> xpath_tokenizer(".")
798 ['.']
799 >>> xpath_tokenizer(".//para")
800 ['.', '//', 'para']
801 >>> xpath_tokenizer("..")
802 ['..']
803 >>> xpath_tokenizer("../@lang")
804 ['..', '/', '@', 'lang']
805 >>> xpath_tokenizer("chapter[title]")
806 ['chapter', '[', 'title', ']']
807 >>> xpath_tokenizer("employee[@secretary and @assistant]")
808 ['employee', '[', '@', 'secretary', '', 'and', '', '@', 'assistant', ']']
809
810 >>> # additional tests
811 >>> xpath_tokenizer("{http://spam}egg")
812 ['{http://spam}egg']
813 >>> xpath_tokenizer("./spam.egg")
814 ['.', '/', 'spam.egg']
815 >>> xpath_tokenizer(".//{http://spam}egg")
816 ['.', '//', '{http://spam}egg']
817 """
818 out = []
819 for op, tag in ElementPath.xpath_tokenizer(p):
820 out.append(op or tag)
821 return out
822
823
824
825
826 XINCLUDE = {}
827
828 XINCLUDE["C1.xml"] = """\
829 <?xml version='1.0'?>
830 <document xmlns:xi="http://www.w3.org/2001/XInclude">
831 <p>120 Mz is adequate for an average home user.</p>
832 <xi:include href="disclaimer.xml"/>
833 </document>
834 """
835
836 XINCLUDE["disclaimer.xml"] = """\
837 <?xml version='1.0'?>
838 <disclaimer>
839 <p>The opinions represented herein represent those of the individual
840 and should not be interpreted as official policy endorsed by this
841 organization.</p>
842 </disclaimer>
843 """
844
845 XINCLUDE["C2.xml"] = """\
846 <?xml version='1.0'?>
847 <document xmlns:xi="http://www.w3.org/2001/XInclude">
848 <p>This document has been accessed
849 <xi:include href="count.txt" parse="text"/> times.</p>
850 </document>
851 """
852
853 XINCLUDE["count.txt"] = "324387"
854
855 XINCLUDE["C3.xml"] = """\
856 <?xml version='1.0'?>
857 <document xmlns:xi="http://www.w3.org/2001/XInclude">
858 <p>The following is the source of the "data.xml" resource:</p>
859 <example><xi:include href="data.xml" parse="text"/></example>
860 </document>
861 """
862
863 XINCLUDE["data.xml"] = """\
864 <?xml version='1.0'?>
865 <data>
866 <item><![CDATA[Brooks & Shields]]></item>
867 </data>
868 """
869
870 XINCLUDE["C5.xml"] = """\
871 <?xml version='1.0'?>
872 <div xmlns:xi="http://www.w3.org/2001/XInclude">
873 <xi:include href="example.txt" parse="text">
874 <xi:fallback>
875 <xi:include href="fallback-example.txt" parse="text">
876 <xi:fallback><a href="mailto:bob@example.org">Report error</a></xi:fallback>
877 </xi:include>
878 </xi:fallback>
879 </xi:include>
880 </div>
881 """
882
883 XINCLUDE["default.xml"] = """\
884 <?xml version='1.0'?>
885 <document xmlns:xi="http://www.w3.org/2001/XInclude">
886 <p>Example.</p>
887 <xi:include href="samples/simple.xml"/>
888 </document>
889 """
890
899
901 r"""
902 Basic inclusion example (XInclude C.1)
903
904 >>> document = xinclude_loader("C1.xml")
905 >>> ElementInclude.include(document, xinclude_loader)
906 >>> print(serialize(document)) # C1
907 <document>
908 <p>120 Mz is adequate for an average home user.</p>
909 <disclaimer>
910 <p>The opinions represented herein represent those of the individual
911 and should not be interpreted as official policy endorsed by this
912 organization.</p>
913 </disclaimer>
914 </document>
915
916 Textual inclusion example (XInclude C.2)
917
918 >>> document = xinclude_loader("C2.xml")
919 >>> ElementInclude.include(document, xinclude_loader)
920 >>> print(serialize(document)) # C2
921 <document>
922 <p>This document has been accessed
923 324387 times.</p>
924 </document>
925
926 Textual inclusion of XML example (XInclude C.3)
927
928 >>> document = xinclude_loader("C3.xml")
929 >>> ElementInclude.include(document, xinclude_loader)
930 >>> print(serialize(document)) # C3
931 <document>
932 <p>The following is the source of the "data.xml" resource:</p>
933 <example><?xml version='1.0'?>
934 <data>
935 <item><![CDATA[Brooks & Shields]]></item>
936 </data>
937 </example>
938 </document>
939
940 ## Fallback example (XInclude C.5)
941 ## Note! Fallback support is not yet implemented
942
943 ## >>> document = xinclude_loader("C5.xml")
944 ## >>> ElementInclude.include(document, xinclude_loader)
945 ## Traceback (most recent call last):
946 ## IOError: resource not found
947 ## >>> # print(serialize(document)) # C5
948
949 """
950
952 """
953 >>> document = xinclude_loader("default.xml")
954 >>> ElementInclude.include(document)
955 >>> print(serialize(document)) # default
956 <document>
957 <p>Example.</p>
958 <root>
959 <element key="value">text</element>
960 <element>text</element>tail
961 <empty-element/>
962 </root>
963 </document>
964 """
965
966
967
968
970 r"""
971 >>> file = BytesIO()
972 >>> w = SimpleXMLWriter.XMLWriter(file)
973 >>> html = w.start("html")
974 >>> x = w.start("head")
975 >>> w.element("title", "my document")
976 >>> w.data("\n")
977 >>> w.element("meta", name="hello", value="goodbye")
978 >>> w.data("\n")
979 >>> w.end()
980 >>> x = w.start("body")
981 >>> w.element("h1", "this is a heading")
982 >>> w.data("\n")
983 >>> w.element("p", u"this is a paragraph")
984 >>> w.data("\n")
985 >>> w.element("p", u"reserved characters: <&>")
986 >>> w.data("\n")
987 >>> w.element("p", u"detta är också ett stycke")
988 >>> w.data("\n")
989 >>> w.close(html)
990 >>> print(file.getvalue())
991 <html><head><title>my document</title>
992 <meta name="hello" value="goodbye" />
993 </head><body><h1>this is a heading</h1>
994 <p>this is a paragraph</p>
995 <p>reserved characters: <&></p>
996 <p>detta är också ett stycke</p>
997 </body></html>
998 """
999
1000
1001 del xmlwriter
1002
1003
1004
1005
1036
1037
1038 del bug_xmltoolkit21
1039
1050
1061
1071
1072
1073 del bug_xmltoolkitX1
1074
1103
1104
1105 del bug_xmltoolkit39
1106
1154
1155
1156 del bug_xmltoolkit45
1157
1168
1169
1170 del bug_xmltoolkit46
1171
1180
1181
1182 del bug_xmltoolkit54
1183
1192
1193
1194 del bug_xmltoolkit55
1195
1197 """
1198 >>> parser = ET.XMLParser()
1199 >>> parser.version
1200 'Expat 2.0.0'
1201 >>> parser.feed(open("samples/simple.xml").read())
1202 >>> print(serialize(parser.close()))
1203 <root>
1204 <element key="value">text</element>
1205 <element>text</element>tail
1206 <empty-element />
1207 </root>
1208 """
1209
1210
1211 del bug_200708_version
1212
1214 r"""
1215
1216 Preserve newlines in attributes.
1217
1218 >>> e = ET.Element('SomeTag', text="def _f():\n return 3\n")
1219 >>> ET.tostring(e)
1220 '<SomeTag text="def _f(): return 3 " />'
1221 >>> ET.XML(ET.tostring(e)).get("text")
1222 'def _f():\n return 3\n'
1223 >>> ET.tostring(ET.XML(ET.tostring(e)))
1224 '<SomeTag text="def _f(): return 3 " />'
1225 """
1226
1227
1228 del bug_200708_newline
1229
1231 """
1232
1233 >>> e = ET.Element("{default}elem")
1234 >>> s = ET.SubElement(e, "{default}elem")
1235 >>> serialize(e, default_namespace="default") # 1
1236 '<elem xmlns="default"><elem /></elem>'
1237
1238 >>> e = ET.Element("{default}elem")
1239 >>> s = ET.SubElement(e, "{default}elem")
1240 >>> s = ET.SubElement(e, "{not-default}elem")
1241 >>> serialize(e, default_namespace="default") # 2
1242 '<elem xmlns="default" xmlns:ns1="not-default"><elem /><ns1:elem /></elem>'
1243
1244 >>> e = ET.Element("{default}elem")
1245 >>> s = ET.SubElement(e, "{default}elem")
1246 >>> s = ET.SubElement(e, "elem") # unprefixed name
1247 >>> serialize(e, default_namespace="default") # 3
1248 Traceback (most recent call last):
1249 ValueError: cannot use non-qualified names with default_namespace option
1250
1251 """
1252
1253
1254 del bug_200709_default_namespace
1255
1256
1257
1258 if __name__ == "__main__":
1259 import doctest, selftest
1260 failed, tested = doctest.testmod(selftest)
1261 print("%d tests ok." % (tested - failed))
1262 if failed > 0:
1263 print("%d tests failed. Exiting with non-zero return code." % failed)
1264 sys.exit(1)
1265