blob: 895902f02f36a06dfaaf533da96b008f1924ef35 [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001# xml.etree test. This file contains enough tests to make sure that
Armin Rigo9ed73062005-12-14 18:10:45 +00002# all included components work as they should. For a more extensive
3# test suite, see the selftest script in the ElementTree distribution.
4
Christian Heimes05e8be12008-02-23 18:30:17 +00005import doctest
6import sys
Armin Rigo9ed73062005-12-14 18:10:45 +00007
Benjamin Petersonee8712c2008-05-20 21:35:26 +00008from test import support
Armin Rigo9ed73062005-12-14 18:10:45 +00009
10SAMPLE_XML = """
11<body>
12 <tag>text</tag>
13 <tag />
14 <section>
15 <tag>subtext</tag>
16 </section>
17</body>
18"""
19
20SAMPLE_XML_NS = """
21<body xmlns="http://effbot.org/ns">
22 <tag>text</tag>
23 <tag />
24 <section>
25 <tag>subtext</tag>
26 </section>
27</body>
28"""
29
30def sanity():
31 """
32 Import sanity.
33
Thomas Wouters0e3f5912006-08-11 14:57:12 +000034 >>> from xml.etree import ElementTree
35 >>> from xml.etree import ElementInclude
36 >>> from xml.etree import ElementPath
Armin Rigo9ed73062005-12-14 18:10:45 +000037 """
38
39def check_method(method):
Guido van Rossumd59da4b2007-05-22 18:11:13 +000040 if not hasattr(method, '__call__'):
Guido van Rossumbe19ed72007-02-09 05:37:30 +000041 print(method, "not callable")
Armin Rigo9ed73062005-12-14 18:10:45 +000042
Guido van Rossum34d19282007-08-09 01:03:29 +000043def serialize(ET, elem):
44 import io
Armin Rigo9ed73062005-12-14 18:10:45 +000045 tree = ET.ElementTree(elem)
Guido van Rossum34d19282007-08-09 01:03:29 +000046 file = io.StringIO()
47 tree.write(file)
Armin Rigo9ed73062005-12-14 18:10:45 +000048 return file.getvalue()
49
50def summarize(elem):
51 return elem.tag
52
53def summarize_list(seq):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000054 return list(map(summarize, seq))
Armin Rigo9ed73062005-12-14 18:10:45 +000055
56def interface():
57 """
58 Test element tree interface.
59
Thomas Wouters0e3f5912006-08-11 14:57:12 +000060 >>> from xml.etree import ElementTree as ET
61
Armin Rigo9ed73062005-12-14 18:10:45 +000062 >>> element = ET.Element("tag", key="value")
63 >>> tree = ET.ElementTree(element)
64
65 Make sure all standard element methods exist.
66
67 >>> check_method(element.append)
68 >>> check_method(element.insert)
69 >>> check_method(element.remove)
70 >>> check_method(element.getchildren)
71 >>> check_method(element.find)
72 >>> check_method(element.findall)
73 >>> check_method(element.findtext)
74 >>> check_method(element.clear)
75 >>> check_method(element.get)
76 >>> check_method(element.set)
77 >>> check_method(element.keys)
78 >>> check_method(element.items)
79 >>> check_method(element.getiterator)
80
81 Basic method sanity checks.
82
83 >>> serialize(ET, element) # 1
84 '<tag key="value" />'
85 >>> subelement = ET.Element("subtag")
86 >>> element.append(subelement)
87 >>> serialize(ET, element) # 2
88 '<tag key="value"><subtag /></tag>'
89 >>> element.insert(0, subelement)
90 >>> serialize(ET, element) # 3
91 '<tag key="value"><subtag /><subtag /></tag>'
92 >>> element.remove(subelement)
93 >>> serialize(ET, element) # 4
94 '<tag key="value"><subtag /></tag>'
95 >>> element.remove(subelement)
96 >>> serialize(ET, element) # 5
97 '<tag key="value" />'
98 >>> element.remove(subelement)
99 Traceback (most recent call last):
100 ValueError: list.remove(x): x not in list
101 >>> serialize(ET, element) # 6
102 '<tag key="value" />'
103 """
104
105def find():
106 """
107 Test find methods (including xpath syntax).
108
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000109 >>> from xml.etree import ElementTree as ET
110
Armin Rigo9ed73062005-12-14 18:10:45 +0000111 >>> elem = ET.XML(SAMPLE_XML)
112 >>> elem.find("tag").tag
113 'tag'
114 >>> ET.ElementTree(elem).find("tag").tag
115 'tag'
116 >>> elem.find("section/tag").tag
117 'tag'
118 >>> ET.ElementTree(elem).find("section/tag").tag
119 'tag'
120 >>> elem.findtext("tag")
121 'text'
122 >>> elem.findtext("tog")
123 >>> elem.findtext("tog", "default")
124 'default'
125 >>> ET.ElementTree(elem).findtext("tag")
126 'text'
127 >>> elem.findtext("section/tag")
128 'subtext'
129 >>> ET.ElementTree(elem).findtext("section/tag")
130 'subtext'
131 >>> summarize_list(elem.findall("tag"))
132 ['tag', 'tag']
133 >>> summarize_list(elem.findall("*"))
134 ['tag', 'tag', 'section']
135 >>> summarize_list(elem.findall(".//tag"))
136 ['tag', 'tag', 'tag']
137 >>> summarize_list(elem.findall("section/tag"))
138 ['tag']
139 >>> summarize_list(elem.findall("section//tag"))
140 ['tag']
141 >>> summarize_list(elem.findall("section/*"))
142 ['tag']
143 >>> summarize_list(elem.findall("section//*"))
144 ['tag']
145 >>> summarize_list(elem.findall("section/.//*"))
146 ['tag']
147 >>> summarize_list(elem.findall("*/*"))
148 ['tag']
149 >>> summarize_list(elem.findall("*//*"))
150 ['tag']
151 >>> summarize_list(elem.findall("*/tag"))
152 ['tag']
153 >>> summarize_list(elem.findall("*/./tag"))
154 ['tag']
155 >>> summarize_list(elem.findall("./tag"))
156 ['tag', 'tag']
157 >>> summarize_list(elem.findall(".//tag"))
158 ['tag', 'tag', 'tag']
159 >>> summarize_list(elem.findall("././tag"))
160 ['tag', 'tag']
161 >>> summarize_list(ET.ElementTree(elem).findall("/tag"))
162 ['tag', 'tag']
163 >>> summarize_list(ET.ElementTree(elem).findall("./tag"))
164 ['tag', 'tag']
165 >>> elem = ET.XML(SAMPLE_XML_NS)
166 >>> summarize_list(elem.findall("tag"))
167 []
168 >>> summarize_list(elem.findall("{http://effbot.org/ns}tag"))
169 ['{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag']
170 >>> summarize_list(elem.findall(".//{http://effbot.org/ns}tag"))
171 ['{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag']
172 """
173
174def parseliteral():
175 r"""
176
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000177 >>> from xml.etree import ElementTree as ET
178
Armin Rigo9ed73062005-12-14 18:10:45 +0000179 >>> element = ET.XML("<html><body>text</body></html>")
180 >>> ET.ElementTree(element).write(sys.stdout)
181 <html><body>text</body></html>
182 >>> element = ET.fromstring("<html><body>text</body></html>")
183 >>> ET.ElementTree(element).write(sys.stdout)
184 <html><body>text</body></html>
Guido van Rossum7131f842007-02-09 20:13:25 +0000185 >>> print(ET.tostring(element))
Armin Rigo9ed73062005-12-14 18:10:45 +0000186 <html><body>text</body></html>
Guido van Rossumb62e8a82007-10-10 22:48:24 +0000187 >>> print(repr(ET.tostring(element, "ascii")))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000188 b"<?xml version='1.0' encoding='ascii'?>\n<html><body>text</body></html>"
Armin Rigo9ed73062005-12-14 18:10:45 +0000189 >>> _, ids = ET.XMLID("<html><body>text</body></html>")
190 >>> len(ids)
191 0
192 >>> _, ids = ET.XMLID("<html><body id='body'>text</body></html>")
193 >>> len(ids)
194 1
195 >>> ids["body"].tag
196 'body'
197 """
198
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000199
200def check_encoding(ET, encoding):
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +0000201 """
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000202 >>> from xml.etree import ElementTree as ET
203
204 >>> check_encoding(ET, "ascii")
205 >>> check_encoding(ET, "us-ascii")
206 >>> check_encoding(ET, "iso-8859-1")
207 >>> check_encoding(ET, "iso-8859-15")
208 >>> check_encoding(ET, "cp437")
209 >>> check_encoding(ET, "mac-roman")
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +0000210 """
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000211 ET.XML("<?xml version='1.0' encoding='%s'?><xml />" % encoding)
212
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +0000213
Armin Rigo9ed73062005-12-14 18:10:45 +0000214#
215# xinclude tests (samples from appendix C of the xinclude specification)
216
217XINCLUDE = {}
218
219XINCLUDE["C1.xml"] = """\
220<?xml version='1.0'?>
221<document xmlns:xi="http://www.w3.org/2001/XInclude">
222 <p>120 Mz is adequate for an average home user.</p>
223 <xi:include href="disclaimer.xml"/>
224</document>
225"""
226
227XINCLUDE["disclaimer.xml"] = """\
228<?xml version='1.0'?>
229<disclaimer>
230 <p>The opinions represented herein represent those of the individual
231 and should not be interpreted as official policy endorsed by this
232 organization.</p>
233</disclaimer>
234"""
235
236XINCLUDE["C2.xml"] = """\
237<?xml version='1.0'?>
238<document xmlns:xi="http://www.w3.org/2001/XInclude">
239 <p>This document has been accessed
240 <xi:include href="count.txt" parse="text"/> times.</p>
241</document>
242"""
243
244XINCLUDE["count.txt"] = "324387"
245
246XINCLUDE["C3.xml"] = """\
247<?xml version='1.0'?>
248<document xmlns:xi="http://www.w3.org/2001/XInclude">
249 <p>The following is the source of the "data.xml" resource:</p>
250 <example><xi:include href="data.xml" parse="text"/></example>
251</document>
252"""
253
254XINCLUDE["data.xml"] = """\
255<?xml version='1.0'?>
256<data>
257 <item><![CDATA[Brooks & Shields]]></item>
258</data>
259"""
260
261XINCLUDE["C5.xml"] = """\
262<?xml version='1.0'?>
263<div xmlns:xi="http://www.w3.org/2001/XInclude">
264 <xi:include href="example.txt" parse="text">
265 <xi:fallback>
266 <xi:include href="fallback-example.txt" parse="text">
267 <xi:fallback><a href="mailto:bob@example.org">Report error</a></xi:fallback>
268 </xi:include>
269 </xi:fallback>
270 </xi:include>
271</div>
272"""
273
274XINCLUDE["default.xml"] = """\
275<?xml version='1.0'?>
276<document xmlns:xi="http://www.w3.org/2001/XInclude">
277 <p>Example.</p>
278 <xi:include href="samples/simple.xml"/>
279</document>
280"""
281
282def xinclude_loader(href, parse="xml", encoding=None):
283 try:
284 data = XINCLUDE[href]
285 except KeyError:
286 raise IOError("resource not found")
287 if parse == "xml":
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000288 from xml.etree.ElementTree import XML
289 return XML(data)
Armin Rigo9ed73062005-12-14 18:10:45 +0000290 return data
291
292def xinclude():
293 r"""
294 Basic inclusion example (XInclude C.1)
295
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000296 >>> from xml.etree import ElementTree as ET
297 >>> from xml.etree import ElementInclude
Armin Rigo9ed73062005-12-14 18:10:45 +0000298
299 >>> document = xinclude_loader("C1.xml")
300 >>> ElementInclude.include(document, xinclude_loader)
Guido van Rossum7131f842007-02-09 20:13:25 +0000301 >>> print(serialize(ET, document)) # C1
Armin Rigo9ed73062005-12-14 18:10:45 +0000302 <document>
303 <p>120 Mz is adequate for an average home user.</p>
304 <disclaimer>
305 <p>The opinions represented herein represent those of the individual
306 and should not be interpreted as official policy endorsed by this
307 organization.</p>
308 </disclaimer>
309 </document>
310
311 Textual inclusion example (XInclude C.2)
312
313 >>> document = xinclude_loader("C2.xml")
314 >>> ElementInclude.include(document, xinclude_loader)
Guido van Rossum7131f842007-02-09 20:13:25 +0000315 >>> print(serialize(ET, document)) # C2
Armin Rigo9ed73062005-12-14 18:10:45 +0000316 <document>
317 <p>This document has been accessed
318 324387 times.</p>
319 </document>
320
321 Textual inclusion of XML example (XInclude C.3)
322
323 >>> document = xinclude_loader("C3.xml")
324 >>> ElementInclude.include(document, xinclude_loader)
Guido van Rossum7131f842007-02-09 20:13:25 +0000325 >>> print(serialize(ET, document)) # C3
Armin Rigo9ed73062005-12-14 18:10:45 +0000326 <document>
327 <p>The following is the source of the "data.xml" resource:</p>
328 <example>&lt;?xml version='1.0'?&gt;
329 &lt;data&gt;
330 &lt;item&gt;&lt;![CDATA[Brooks &amp; Shields]]&gt;&lt;/item&gt;
331 &lt;/data&gt;
332 </example>
333 </document>
334
335 Fallback example (XInclude C.5)
336 Note! Fallback support is not yet implemented
337
338 >>> document = xinclude_loader("C5.xml")
339 >>> ElementInclude.include(document, xinclude_loader)
340 Traceback (most recent call last):
341 IOError: resource not found
342 >>> # print serialize(ET, document) # C5
343
344 """
345
346def test_main():
347 from test import test_xml_etree
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000348 support.run_doctest(test_xml_etree, verbosity=True)
Armin Rigo9ed73062005-12-14 18:10:45 +0000349
350if __name__ == '__main__':
351 test_main()