blob: 86052d7909a6cb1d40dbf6220051a23499efbcc2 [file] [log] [blame]
Armin Rigo9ed73062005-12-14 18:10:45 +00001# xmlcore.etree test. This file contains enough tests to make sure that
2# all included components work as they should. For a more extensive
3# test suite, see the selftest script in the ElementTree distribution.
4
5import doctest, sys
6
7from test import test_support
8
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +00009from xmlcore.etree import ElementTree as ET
10
Armin Rigo9ed73062005-12-14 18:10:45 +000011SAMPLE_XML = """
12<body>
13 <tag>text</tag>
14 <tag />
15 <section>
16 <tag>subtext</tag>
17 </section>
18</body>
19"""
20
21SAMPLE_XML_NS = """
22<body xmlns="http://effbot.org/ns">
23 <tag>text</tag>
24 <tag />
25 <section>
26 <tag>subtext</tag>
27 </section>
28</body>
29"""
30
31def sanity():
32 """
33 Import sanity.
34
35 >>> from xmlcore.etree import ElementTree
36 >>> from xmlcore.etree import ElementInclude
37 >>> from xmlcore.etree import ElementPath
38 """
39
40def check_method(method):
41 if not callable(method):
42 print method, "not callable"
43
44def serialize(ET, elem, encoding=None):
45 import StringIO
46 file = StringIO.StringIO()
47 tree = ET.ElementTree(elem)
48 if encoding:
49 tree.write(file, encoding)
50 else:
51 tree.write(file)
52 return file.getvalue()
53
54def summarize(elem):
55 return elem.tag
56
57def summarize_list(seq):
58 return map(summarize, seq)
59
60def interface():
61 """
62 Test element tree interface.
63
Armin Rigo9ed73062005-12-14 18:10:45 +000064 >>> element = ET.Element("tag", key="value")
65 >>> tree = ET.ElementTree(element)
66
67 Make sure all standard element methods exist.
68
69 >>> check_method(element.append)
70 >>> check_method(element.insert)
71 >>> check_method(element.remove)
72 >>> check_method(element.getchildren)
73 >>> check_method(element.find)
74 >>> check_method(element.findall)
75 >>> check_method(element.findtext)
76 >>> check_method(element.clear)
77 >>> check_method(element.get)
78 >>> check_method(element.set)
79 >>> check_method(element.keys)
80 >>> check_method(element.items)
81 >>> check_method(element.getiterator)
82
83 Basic method sanity checks.
84
85 >>> serialize(ET, element) # 1
86 '<tag key="value" />'
87 >>> subelement = ET.Element("subtag")
88 >>> element.append(subelement)
89 >>> serialize(ET, element) # 2
90 '<tag key="value"><subtag /></tag>'
91 >>> element.insert(0, subelement)
92 >>> serialize(ET, element) # 3
93 '<tag key="value"><subtag /><subtag /></tag>'
94 >>> element.remove(subelement)
95 >>> serialize(ET, element) # 4
96 '<tag key="value"><subtag /></tag>'
97 >>> element.remove(subelement)
98 >>> serialize(ET, element) # 5
99 '<tag key="value" />'
100 >>> element.remove(subelement)
101 Traceback (most recent call last):
102 ValueError: list.remove(x): x not in list
103 >>> serialize(ET, element) # 6
104 '<tag key="value" />'
105 """
106
107def find():
108 """
109 Test find methods (including xpath syntax).
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
Armin Rigo9ed73062005-12-14 18:10:45 +0000177 >>> element = ET.XML("<html><body>text</body></html>")
178 >>> ET.ElementTree(element).write(sys.stdout)
179 <html><body>text</body></html>
180 >>> element = ET.fromstring("<html><body>text</body></html>")
181 >>> ET.ElementTree(element).write(sys.stdout)
182 <html><body>text</body></html>
183 >>> print ET.tostring(element)
184 <html><body>text</body></html>
185 >>> print ET.tostring(element, "ascii")
186 <?xml version='1.0' encoding='ascii'?>
187 <html><body>text</body></html>
188 >>> _, ids = ET.XMLID("<html><body>text</body></html>")
189 >>> len(ids)
190 0
191 >>> _, ids = ET.XMLID("<html><body id='body'>text</body></html>")
192 >>> len(ids)
193 1
194 >>> ids["body"].tag
195 'body'
196 """
197
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +0000198def check_encoding(encoding):
199 """
200 >>> check_encoding("ascii")
201 >>> check_encoding("us-ascii")
202 >>> check_encoding("iso-8859-1")
203 >>> check_encoding("iso-8859-15")
204 >>> check_encoding("cp437")
205 >>> check_encoding("mac-roman")
206 """
207 ET.XML(
208 "<?xml version='1.0' encoding='%s'?><xml />" % encoding
209 )
210
Armin Rigo9ed73062005-12-14 18:10:45 +0000211#
212# xinclude tests (samples from appendix C of the xinclude specification)
213
214XINCLUDE = {}
215
216XINCLUDE["C1.xml"] = """\
217<?xml version='1.0'?>
218<document xmlns:xi="http://www.w3.org/2001/XInclude">
219 <p>120 Mz is adequate for an average home user.</p>
220 <xi:include href="disclaimer.xml"/>
221</document>
222"""
223
224XINCLUDE["disclaimer.xml"] = """\
225<?xml version='1.0'?>
226<disclaimer>
227 <p>The opinions represented herein represent those of the individual
228 and should not be interpreted as official policy endorsed by this
229 organization.</p>
230</disclaimer>
231"""
232
233XINCLUDE["C2.xml"] = """\
234<?xml version='1.0'?>
235<document xmlns:xi="http://www.w3.org/2001/XInclude">
236 <p>This document has been accessed
237 <xi:include href="count.txt" parse="text"/> times.</p>
238</document>
239"""
240
241XINCLUDE["count.txt"] = "324387"
242
243XINCLUDE["C3.xml"] = """\
244<?xml version='1.0'?>
245<document xmlns:xi="http://www.w3.org/2001/XInclude">
246 <p>The following is the source of the "data.xml" resource:</p>
247 <example><xi:include href="data.xml" parse="text"/></example>
248</document>
249"""
250
251XINCLUDE["data.xml"] = """\
252<?xml version='1.0'?>
253<data>
254 <item><![CDATA[Brooks & Shields]]></item>
255</data>
256"""
257
258XINCLUDE["C5.xml"] = """\
259<?xml version='1.0'?>
260<div xmlns:xi="http://www.w3.org/2001/XInclude">
261 <xi:include href="example.txt" parse="text">
262 <xi:fallback>
263 <xi:include href="fallback-example.txt" parse="text">
264 <xi:fallback><a href="mailto:bob@example.org">Report error</a></xi:fallback>
265 </xi:include>
266 </xi:fallback>
267 </xi:include>
268</div>
269"""
270
271XINCLUDE["default.xml"] = """\
272<?xml version='1.0'?>
273<document xmlns:xi="http://www.w3.org/2001/XInclude">
274 <p>Example.</p>
275 <xi:include href="samples/simple.xml"/>
276</document>
277"""
278
279def xinclude_loader(href, parse="xml", encoding=None):
280 try:
281 data = XINCLUDE[href]
282 except KeyError:
283 raise IOError("resource not found")
284 if parse == "xml":
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +0000285 return ET.XML(data)
Armin Rigo9ed73062005-12-14 18:10:45 +0000286 return data
287
288def xinclude():
289 r"""
290 Basic inclusion example (XInclude C.1)
291
Armin Rigo9ed73062005-12-14 18:10:45 +0000292 >>> from xmlcore.etree import ElementInclude
293
294 >>> document = xinclude_loader("C1.xml")
295 >>> ElementInclude.include(document, xinclude_loader)
296 >>> print serialize(ET, document) # C1
297 <document>
298 <p>120 Mz is adequate for an average home user.</p>
299 <disclaimer>
300 <p>The opinions represented herein represent those of the individual
301 and should not be interpreted as official policy endorsed by this
302 organization.</p>
303 </disclaimer>
304 </document>
305
306 Textual inclusion example (XInclude C.2)
307
308 >>> document = xinclude_loader("C2.xml")
309 >>> ElementInclude.include(document, xinclude_loader)
310 >>> print serialize(ET, document) # C2
311 <document>
312 <p>This document has been accessed
313 324387 times.</p>
314 </document>
315
316 Textual inclusion of XML example (XInclude C.3)
317
318 >>> document = xinclude_loader("C3.xml")
319 >>> ElementInclude.include(document, xinclude_loader)
320 >>> print serialize(ET, document) # C3
321 <document>
322 <p>The following is the source of the "data.xml" resource:</p>
323 <example>&lt;?xml version='1.0'?&gt;
324 &lt;data&gt;
325 &lt;item&gt;&lt;![CDATA[Brooks &amp; Shields]]&gt;&lt;/item&gt;
326 &lt;/data&gt;
327 </example>
328 </document>
329
330 Fallback example (XInclude C.5)
331 Note! Fallback support is not yet implemented
332
333 >>> document = xinclude_loader("C5.xml")
334 >>> ElementInclude.include(document, xinclude_loader)
335 Traceback (most recent call last):
336 IOError: resource not found
337 >>> # print serialize(ET, document) # C5
338
339 """
340
341def test_main():
342 from test import test_xml_etree
343 test_support.run_doctest(test_xml_etree, verbosity=True)
344
345if __name__ == '__main__':
346 test_main()