Package lxml :: Package tests :: Module test_elementpath
[hide private]
[frames] | no frames]

Source Code for Module lxml.tests.test_elementpath

  1  # -*- coding: utf-8 -*- 
  2   
  3  """ 
  4  Tests for the ElementPath implementation. 
  5  """ 
  6   
  7  from __future__ import absolute_import 
  8   
  9  import unittest 
 10  from copy import deepcopy 
 11  from .common_imports import etree, HelperTestCase 
 12   
 13   
14 -def summarize(elem):
15 return elem.tag
16
17 -def summarize_list(seq):
18 return list(map(summarize, seq))
19
20 -def normalize_crlf(tree):
21 for elem in tree.getiterator(): 22 if elem.text: elem.text = elem.text.replace("\r\n", "\n") 23 if elem.tail: elem.tail = elem.tail.replace("\r\n", "\n")
24 25
26 -class EtreeElementPathTestCase(HelperTestCase):
27 etree = etree 28 from lxml import _elementpath 29
30 - def test_cache(self):
31 self._elementpath._cache.clear() 32 el = self.etree.XML(b'<a><b><c/><c/></b></a>') 33 self.assertFalse(self._elementpath._cache) 34 35 self.assertTrue(el.findall('b/c')) 36 self.assertEqual(1, len(self._elementpath._cache)) 37 self.assertTrue(el.findall('b/c')) 38 self.assertEqual(1, len(self._elementpath._cache)) 39 self.assertFalse(el.findall('xxx')) 40 self.assertEqual(2, len(self._elementpath._cache)) 41 self.assertFalse(el.findall('xxx')) 42 self.assertEqual(2, len(self._elementpath._cache)) 43 self.assertTrue(el.findall('b/c')) 44 self.assertEqual(2, len(self._elementpath._cache))
45
46 - def _assert_tokens(self, tokens, path, namespaces=None):
47 self.assertEqual(tokens, list(self._elementpath.xpath_tokenizer(path, namespaces)))
48
49 - def test_tokenizer(self):
50 assert_tokens = self._assert_tokens 51 assert_tokens( 52 [('/', '')], 53 '/', 54 ) 55 assert_tokens( 56 [('.', ''), ('/', ''), ('', 'a'), ('/', ''), ('', 'b'), ('/', ''), ('', 'c')], 57 './a/b/c', 58 ) 59 assert_tokens( 60 [('/', ''), ('', 'a'), ('/', ''), ('', 'b'), ('/', ''), ('', 'c')], 61 '/a/b/c', 62 ) 63 assert_tokens( 64 [('/', ''), ('', '{nsx}a'), ('/', ''), ('', '{nsy}b'), ('/', ''), ('', 'c')], 65 '/x:a/y:b/c', 66 {'x': 'nsx', 'y': 'nsy'}, 67 ) 68 assert_tokens( 69 [('/', ''), ('', '{nsx}a'), ('/', ''), ('', '{nsy}b'), ('/', ''), ('', '{nsnone}c')], 70 '/x:a/y:b/c', 71 {'x': 'nsx', 'y': 'nsy', None: 'nsnone'}, 72 )
73
75 assert_tokens = self._assert_tokens 76 assert_tokens( 77 [('', 'a'), ('[', ''), ('', 'b'), (']', '')], 78 'a[b]', 79 ) 80 assert_tokens( 81 [('', 'a'), ('[', ''), ('', 'b'), ('=', ''), ('"abc"', ''), (']', '')], 82 'a[b="abc"]', 83 ) 84 assert_tokens( 85 [('', 'a'), ('[', ''), ('.', ''), ('', ''), ('=', ''), ('', ''), ('"abc"', ''), (']', '')], 86 'a[. = "abc"]', 87 )
88
89 - def test_xpath_tokenizer(self):
90 # Test the XPath tokenizer. Copied from CPython's "test_xml_etree.py" 91 ElementPath = self._elementpath 92 93 def check(p, expected, namespaces=None): 94 self.assertEqual([op or tag 95 for op, tag in ElementPath.xpath_tokenizer(p, namespaces)], 96 expected)
97 98 # tests from the xml specification 99 check("*", ['*']) 100 check("text()", ['text', '()']) 101 check("@name", ['@', 'name']) 102 check("@*", ['@', '*']) 103 check("para[1]", ['para', '[', '1', ']']) 104 check("para[last()]", ['para', '[', 'last', '()', ']']) 105 check("*/para", ['*', '/', 'para']) 106 check("/doc/chapter[5]/section[2]", 107 ['/', 'doc', '/', 'chapter', '[', '5', ']', 108 '/', 'section', '[', '2', ']']) 109 check("chapter//para", ['chapter', '//', 'para']) 110 check("//para", ['//', 'para']) 111 check("//olist/item", ['//', 'olist', '/', 'item']) 112 check(".", ['.']) 113 check(".//para", ['.', '//', 'para']) 114 check("..", ['..']) 115 check("../@lang", ['..', '/', '@', 'lang']) 116 check("chapter[title]", ['chapter', '[', 'title', ']']) 117 check("employee[@secretary and @assistant]", ['employee', 118 '[', '@', 'secretary', '', 'and', '', '@', 'assistant', ']']) 119 120 # additional tests 121 check("@{ns}attr", ['@', '{ns}attr']) 122 check("{http://spam}egg", ['{http://spam}egg']) 123 check("./spam.egg", ['.', '/', 'spam.egg']) 124 check(".//{http://spam}egg", ['.', '//', '{http://spam}egg']) 125 126 # wildcard tags 127 check("{ns}*", ['{ns}*']) 128 check("{}*", ['{}*']) 129 check("{*}tag", ['{*}tag']) 130 check("{*}*", ['{*}*']) 131 check(".//{*}tag", ['.', '//', '{*}tag']) 132 133 # namespace prefix resolution 134 check("./xsd:type", ['.', '/', '{http://www.w3.org/2001/XMLSchema}type'], 135 {'xsd': 'http://www.w3.org/2001/XMLSchema'}) 136 check("type", ['{http://www.w3.org/2001/XMLSchema}type'], 137 {'': 'http://www.w3.org/2001/XMLSchema'}) 138 check("@xsd:type", ['@', '{http://www.w3.org/2001/XMLSchema}type'], 139 {'xsd': 'http://www.w3.org/2001/XMLSchema'}) 140 check("@type", ['@', 'type'], 141 {'': 'http://www.w3.org/2001/XMLSchema'}) 142 check("@{*}type", ['@', '{*}type'], 143 {'': 'http://www.w3.org/2001/XMLSchema'}) 144 check("@{ns}attr", ['@', '{ns}attr'], 145 {'': 'http://www.w3.org/2001/XMLSchema', 146 'ns': 'http://www.w3.org/2001/XMLSchema'})
147
148 - def test_find(self):
149 """ 150 Test find methods (including xpath syntax). 151 Originally copied from 'selftest.py'. 152 """ 153 elem = etree.XML(""" 154 <body> 155 <tag class='a'>text</tag> 156 <tag class='b' /> 157 <section> 158 <tag class='b' id='inner'>subtext</tag> 159 </section> 160 </body> 161 """) 162 163 self.assertEqual(elem.find("tag").tag, 164 'tag') 165 self.assertEqual(etree.ElementTree(elem).find("tag").tag, 166 'tag') 167 self.assertEqual(elem.find("section/tag").tag, 168 'tag') 169 self.assertEqual(etree.ElementTree(elem).find("section/tag").tag, 170 'tag') 171 172 self.assertEqual(elem.findtext("tag"), 173 'text') 174 self.assertEqual(elem.findtext("tog"), 175 None) 176 self.assertEqual(elem.findtext("tog", "default"), 177 'default') 178 self.assertEqual(etree.ElementTree(elem).findtext("tag"), 179 'text') 180 self.assertEqual(elem.findtext("section/tag"), 181 'subtext') 182 self.assertEqual(etree.ElementTree(elem).findtext("section/tag"), 183 'subtext') 184 185 self.assertEqual(summarize_list(elem.findall("tag")), 186 ['tag', 'tag']) 187 self.assertEqual(summarize_list(elem.findall("*")), 188 ['tag', 'tag', 'section']) 189 self.assertEqual(summarize_list(elem.findall(".//tag")), 190 ['tag', 'tag', 'tag']) 191 self.assertEqual(summarize_list(elem.findall("section/tag")), 192 ['tag']) 193 self.assertEqual(summarize_list(elem.findall("section//tag")), 194 ['tag']) 195 196 self.assertEqual(summarize_list(elem.findall("section/*")), 197 ['tag']) 198 self.assertEqual(summarize_list(elem.findall("section//*")), 199 ['tag']) 200 self.assertEqual(summarize_list(elem.findall("section/.//*")), 201 ['tag']) 202 self.assertEqual(summarize_list(elem.findall("*/*")), 203 ['tag']) 204 self.assertEqual(summarize_list(elem.findall("*//*")), 205 ['tag']) 206 self.assertEqual(summarize_list(elem.findall("*/tag")), 207 ['tag']) 208 self.assertEqual(summarize_list(elem.findall("*/./tag")), 209 ['tag']) 210 self.assertEqual(summarize_list(elem.findall("./tag")), 211 ['tag', 'tag']) 212 self.assertEqual(summarize_list(elem.findall(".//tag")), 213 ['tag', 'tag', 'tag']) 214 self.assertEqual(summarize_list(elem.findall("././tag")), 215 ['tag', 'tag']) 216 217 self.assertEqual(summarize_list(elem.findall(".//tag[@class]")), 218 ['tag', 'tag', 'tag']) 219 self.assertEqual(summarize_list(elem.findall(".//tag[ @class]")), 220 ['tag', 'tag', 'tag']) 221 self.assertEqual(summarize_list(elem.findall(".//tag[@class ]")), 222 ['tag', 'tag', 'tag']) 223 self.assertEqual(summarize_list(elem.findall(".//tag[ @class ]")), 224 ['tag', 'tag', 'tag']) 225 self.assertEqual(summarize_list(elem.findall(".//tag[@class='a']")), 226 ['tag']) 227 self.assertEqual(summarize_list(elem.findall('.//tag[@class="a"]')), 228 ['tag']) 229 self.assertEqual(summarize_list(elem.findall(".//tag[@class='b']")), 230 ['tag', 'tag']) 231 self.assertEqual(summarize_list(elem.findall('.//tag[@class="b"]')), 232 ['tag', 'tag']) 233 self.assertEqual(summarize_list(elem.findall('.//tag[@class = "b"]')), 234 ['tag', 'tag']) 235 self.assertEqual(summarize_list(elem.findall(".//tag[@id]")), 236 ['tag']) 237 self.assertEqual(summarize_list(elem.findall(".//tag[@class][@id]")), 238 ['tag']) 239 self.assertEqual(summarize_list(elem.findall(".//section[tag]")), 240 ['section']) 241 self.assertEqual(summarize_list(elem.findall(".//section[element]")), 242 []) 243 244 self.assertEqual(summarize_list(elem.findall(".//section[tag='subtext']")), 245 ['section']) 246 self.assertEqual(summarize_list(elem.findall(".//section[tag ='subtext']")), 247 ['section']) 248 self.assertEqual(summarize_list(elem.findall(".//section[tag= 'subtext']")), 249 ['section']) 250 self.assertEqual(summarize_list(elem.findall(".//section[tag = 'subtext']")), 251 ['section']) 252 self.assertEqual(summarize_list(elem.findall(".//section[ tag = 'subtext' ]")), 253 ['section']) 254 self.assertEqual(summarize_list(elem.findall(".//tag[.='subtext']")), 255 ['tag']) 256 self.assertEqual(summarize_list(elem.findall(".//tag[. ='subtext']")), 257 ['tag']) 258 self.assertEqual(summarize_list(elem.findall('.//tag[.= "subtext"]')), 259 ['tag']) 260 self.assertEqual(summarize_list(elem.findall(".//tag[. = 'subtext']")), 261 ['tag']) 262 self.assertEqual(summarize_list(elem.findall(".//tag[. = 'subtext ']")), 263 []) 264 self.assertEqual(summarize_list(elem.findall(".//tag[.= ' subtext']")), 265 []) 266 267 self.assertEqual(summarize_list(elem.findall("../tag")), 268 []) 269 self.assertEqual(summarize_list(elem.findall("section/../tag")), 270 ['tag', 'tag']) 271 self.assertEqual(summarize_list(etree.ElementTree(elem).findall("./tag")), 272 ['tag', 'tag']) 273 274 # FIXME: ET's Path module handles this case incorrectly; this gives 275 # a warning in 1.3, and the behaviour will be modified in 1.4. 276 self.assertEqual(summarize_list(etree.ElementTree(elem).findall("/tag")), 277 ['tag', 'tag']) 278 279 # duplicate section => 2x tag matches 280 elem[1] = deepcopy(elem[2]) 281 self.assertEqual(summarize_list(elem.findall(".//section[tag = 'subtext']")), 282 ['section', 'section']) 283 self.assertEqual(summarize_list(elem.findall(".//tag[. = 'subtext']")), 284 ['tag', 'tag']) 285 self.assertEqual(summarize_list(elem.findall(".//tag[@class][@id]")), 286 ['tag', 'tag'])
287 288 289 #class ElementTreeElementPathTestCase(EtreeElementPathTestCase): 290 # import xml.etree.ElementTree as etree 291 # import xml.etree.ElementPath as _elementpath 292 293
294 -def test_suite():
295 suite = unittest.TestSuite() 296 suite.addTests([unittest.makeSuite(EtreeElementPathTestCase)]) 297 #suite.addTests([unittest.makeSuite(ElementTreeElementPathTestCase)]) 298 return suite
299 300 301 if __name__ == '__main__': 302 print('to test use test.py %s' % __file__) 303