1
2
3
4
5
6
7 import sys
8
9 try:
10 from StringIO import StringIO
11 BytesIO = StringIO
12 except ImportError:
13 from io import BytesIO, StringIO
14
15 from lxml import etree as ElementTree
16
18 if sys.version_info[0] < 3:
19 return sys.stdout
20 class bytes_stdout(object):
21 def write(self, data):
22 if isinstance(data, bytes):
23 data = data.decode('ISO8859-1')
24 sys.stdout.write(data)
25 return bytes_stdout()
26
31
33 file = BytesIO()
34 tree = ElementTree.ElementTree(elem)
35 if encoding:
36 tree.write(file, encoding=encoding)
37 else:
38 tree.write(file)
39 result = file.getvalue()
40 if sys.version_info[0] >= 3:
41 result = result.decode('ISO8859-1')
42 result = result.replace(' />', '/>')
43 if result[-1:] == '\n':
44 result = result[:-1]
45 return result
46
49
52
53 SAMPLE_XML = unserialize("""
54 <body>
55 <tag>text</tag>
56 <tag />
57 <section>
58 <tag>subtext</tag>
59 </section>
60 </body>
61 """)
62
63 SAMPLE_XML_NS = unserialize("""
64 <body xmlns="http://effbot.org/ns">
65 <tag>text</tag>
66 <tag />
67 <section>
68 <tag>subtext</tag>
69 </section>
70 </body>
71 """)
72
73
74
76 len(string)
77 for char in string:
78 if len(char) != 1:
79 print("expected one-character string, got %r" % char)
80 new_string = string + ""
81 new_string = string + " "
82 string[:0]
83
85 len(mapping)
86 keys = mapping.keys()
87 items = mapping.items()
88 for key in keys:
89 item = mapping[key]
90 mapping["key"] = "value"
91 if mapping["key"] != "value":
92 print("expected value string, got %r" % mapping["key"])
93
109
112
114 """
115 Test element tree interface.
116
117 >>> element = ElementTree.Element("tag")
118 >>> check_element(element)
119 >>> tree = ElementTree.ElementTree(element)
120 >>> check_element_tree(tree)
121 """
122
124 """
125 Test parsing from file. Note that we're opening the files in
126 here; by default, the 'parse' function opens the file in binary
127 mode, and doctest doesn't filter out carriage returns.
128
129 >>> file = open("samples/simple.xml", "rb")
130 >>> tree = ElementTree.parse(file)
131 >>> file.close()
132 >>> tree.write(stdout())
133 <root>
134 <element key="value">text</element>
135 <element>text</element>tail
136 <empty-element/>
137 </root>
138 >>> file = open("samples/simple-ns.xml", "rb")
139 >>> tree = ElementTree.parse(file)
140 >>> file.close()
141 >>> tree.write(stdout())
142 <root xmlns="http://namespace/">
143 <element key="value">text</element>
144 <element>text</element>tail
145 <empty-element/>
146 </root>
147 """
148
150 """
151 >>> elem = ElementTree.Element("tag")
152 >>> elem.text = "text"
153 >>> serialize(elem)
154 '<tag>text</tag>'
155 >>> ElementTree.SubElement(elem, "subtag").text = "subtext"
156 >>> serialize(elem)
157 '<tag>text<subtag>subtext</subtag></tag>'
158 """
159
161 r"""
162 Test encoding issues.
163
164 >>> elem = ElementTree.Element("tag")
165 >>> elem.text = u'abc'
166 >>> serialize(elem)
167 '<tag>abc</tag>'
168 >>> serialize(elem, "utf-8")
169 '<tag>abc</tag>'
170 >>> serialize(elem, "us-ascii")
171 '<tag>abc</tag>'
172 >>> serialize(elem, "iso-8859-1").lower()
173 "<?xml version='1.0' encoding='iso-8859-1'?>\n<tag>abc</tag>"
174
175 >>> elem.text = "<&\"\'>"
176 >>> serialize(elem)
177 '<tag><&"\'></tag>'
178 >>> serialize(elem, "utf-8")
179 '<tag><&"\'></tag>'
180 >>> serialize(elem, "us-ascii") # cdata characters
181 '<tag><&"\'></tag>'
182 >>> serialize(elem, "iso-8859-1").lower()
183 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag><&"\'></tag>'
184
185 >>> elem.attrib["key"] = "<&\"\'>"
186 >>> elem.text = None
187 >>> serialize(elem)
188 '<tag key="<&"\'>"/>'
189 >>> serialize(elem, "utf-8")
190 '<tag key="<&"\'>"/>'
191 >>> serialize(elem, "us-ascii")
192 '<tag key="<&"\'>"/>'
193 >>> serialize(elem, "iso-8859-1").lower()
194 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag key="<&"\'>"/>'
195
196 >>> elem.text = u'\xe5\xf6\xf6<>'
197 >>> elem.attrib.clear()
198 >>> serialize(elem)
199 '<tag>åöö<></tag>'
200 >>> serialize(elem, "utf-8")
201 '<tag>\xc3\xa5\xc3\xb6\xc3\xb6<></tag>'
202 >>> serialize(elem, "us-ascii")
203 '<tag>åöö<></tag>'
204 >>> serialize(elem, "iso-8859-1").lower()
205 "<?xml version='1.0' encoding='iso-8859-1'?>\n<tag>\xe5\xf6\xf6<></tag>"
206
207 >>> elem.attrib["key"] = u'\xe5\xf6\xf6<>'
208 >>> elem.text = None
209 >>> serialize(elem)
210 '<tag key="åöö<>"/>'
211 >>> serialize(elem, "utf-8")
212 '<tag key="\xc3\xa5\xc3\xb6\xc3\xb6<>"/>'
213 >>> serialize(elem, "us-ascii")
214 '<tag key="åöö<>"/>'
215 >>> serialize(elem, "iso-8859-1").lower()
216 '<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>\n<tag key="\xe5\xf6\xf6<>"/>'
217
218 """
219
220 if sys.version_info[0] >= 3:
221 encoding.__doc__ = encoding.__doc__.replace("u'", "'")
222
224 """
225 Test QName handling.
226
227 1) decorated tags
228
229 >>> elem = ElementTree.Element("{uri}tag")
230 >>> serialize(elem) # 1.1
231 '<ns0:tag xmlns:ns0="uri"/>'
232
233 ## 2) decorated attributes
234
235 ## >>> elem.attrib["{uri}key"] = "value"
236 ## >>> serialize(elem) # 2.1
237 ## '<ns0:tag ns0:key="value" xmlns:ns0="uri"/>'
238
239 """
240
242 """
243 Test CDATA handling (etc).
244
245 >>> serialize(unserialize("<tag>hello</tag>"))
246 '<tag>hello</tag>'
247 >>> serialize(unserialize("<tag>hello</tag>"))
248 '<tag>hello</tag>'
249 >>> serialize(unserialize("<tag><![CDATA[hello]]></tag>"))
250 '<tag>hello</tag>'
251
252 """
253
255 """
256 Test find methods (including xpath syntax).
257
258 >>> elem = SAMPLE_XML
259 >>> elem.find("tag").tag
260 'tag'
261 >>> ElementTree.ElementTree(elem).find("tag").tag
262 'tag'
263 >>> elem.find("section/tag").tag
264 'tag'
265 >>> ElementTree.ElementTree(elem).find("section/tag").tag
266 'tag'
267 >>> elem.findtext("tag")
268 'text'
269 >>> elem.findtext("tog", "default")
270 'default'
271 >>> ElementTree.ElementTree(elem).findtext("tag")
272 'text'
273 >>> elem.findtext("section/tag")
274 'subtext'
275 >>> ElementTree.ElementTree(elem).findtext("section/tag")
276 'subtext'
277 >>> summarize_list(elem.findall("tag"))
278 ['tag', 'tag']
279 >>> summarize_list(elem.findall("*"))
280 ['tag', 'tag', 'section']
281 >>> summarize_list(elem.findall(".//tag"))
282 ['tag', 'tag', 'tag']
283 >>> summarize_list(elem.findall("section/tag"))
284 ['tag']
285 >>> summarize_list(elem.findall("section//tag"))
286 ['tag']
287 >>> summarize_list(elem.findall("section/*"))
288 ['tag']
289 >>> summarize_list(elem.findall("section//*"))
290 ['tag']
291 >>> summarize_list(elem.findall("section/.//*"))
292 ['tag']
293 >>> summarize_list(elem.findall("*/*"))
294 ['tag']
295 >>> summarize_list(elem.findall("*//*"))
296 ['tag']
297 >>> summarize_list(elem.findall("*/tag"))
298 ['tag']
299 >>> summarize_list(elem.findall("*/./tag"))
300 ['tag']
301 >>> summarize_list(elem.findall("./tag"))
302 ['tag', 'tag']
303 >>> summarize_list(elem.findall(".//tag"))
304 ['tag', 'tag', 'tag']
305 >>> summarize_list(elem.findall("././tag"))
306 ['tag', 'tag']
307 >>> summarize_list(ElementTree.ElementTree(elem).findall("/tag"))
308 ['tag', 'tag']
309 >>> summarize_list(ElementTree.ElementTree(elem).findall("./tag"))
310 ['tag', 'tag']
311 >>> elem = SAMPLE_XML_NS
312 >>> summarize_list(elem.findall("tag"))
313 []
314 >>> summarize_list(elem.findall("{http://effbot.org/ns}tag"))
315 ['{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag']
316 >>> summarize_list(elem.findall(".//{http://effbot.org/ns}tag"))
317 ['{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag', '{http://effbot.org/ns}tag']
318 """
319
320
321
323 """
324 Test copy handling (etc).
325
326 >>> import copy
327 >>> e1 = unserialize("<tag>hello<foo/></tag>")
328 >>> # e2 = copy.copy(e1)
329 >>> e3 = copy.deepcopy(e1)
330 >>> e1.find("foo").tag = "bar"
331
332 >>> serialize(e1).replace(' ', '')
333 '<tag>hello<bar/></tag>'
334
335 ## >>> serialize(e2).replace(' ', '')
336 ## '<tag>hello<bar/></tag>'
337
338 >>> serialize(e3).replace(' ', '')
339 '<tag>hello<foo/></tag>'
340
341 """
342
344 """
345 Test attribute handling.
346
347 >>> elem = ElementTree.Element("tag")
348 >>> elem.get("key") # 1.1
349 >>> elem.get("key", "default") # 1.2
350 'default'
351 >>> elem.set("key", "value")
352 >>> elem.get("key") # 1.3
353 'value'
354
355 >>> elem = ElementTree.Element("tag", key="value")
356 >>> elem.get("key") # 2.1
357 'value'
358 >>> elem.attrib # 2.2
359 {'key': 'value'}
360
361 >>> elem = ElementTree.Element("tag", {"key": "value"})
362 >>> elem.get("key") # 3.1
363 'value'
364 >>> elem.attrib # 3.2
365 {'key': 'value'}
366
367 >>> elem = ElementTree.Element("tag", {"key": "other"}, key="value")
368 >>> elem.get("key") # 4.1
369 'value'
370 >>> elem.attrib # 4.2
371 {'key': 'value'}
372
373 """
374
376 """
377 Test makeelement handling.
378
379 >>> elem = ElementTree.Element("tag")
380 >>> subelem = elem.makeelement("subtag", {"key": "value"})
381 >>> elem.append(subelem)
382 >>> serialize(elem)
383 '<tag><subtag key="value"/></tag>'
384
385 >>> elem.clear()
386 >>> serialize(elem)
387 '<tag/>'
388 >>> elem.append(subelem)
389 >>> serialize(elem)
390 '<tag><subtag key="value"/></tag>'
391
392 """
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 ENTITY_XML = """\
418 <!DOCTYPE points [
419 <!ENTITY % user-entities SYSTEM 'user-entities.xml'>
420 %user-entities;
421 ]>
422 <document>&entity;</document>
423 """
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 if __name__ == "__main__":
447 import doctest, selftest2
448 failed, tested = doctest.testmod(selftest2)
449 print("%d tests ok." % (tested - failed))
450 if failed > 0:
451 print("%d tests failed. Exiting with non-zero return code." % failed)
452 sys.exit(1)
453