(elem, path, namespaces=None)
| 358 | # Generate all matching objects. |
| 359 | |
| 360 | def iterfind(elem, path, namespaces=None): |
| 361 | # compile selector pattern |
| 362 | if path[-1:] == "/": |
| 363 | path = path + "*" # implicit all (FIXME: keep this?) |
| 364 | |
| 365 | cache_key = (path,) |
| 366 | if namespaces: |
| 367 | cache_key += tuple(sorted(namespaces.items())) |
| 368 | |
| 369 | try: |
| 370 | selector = _cache[cache_key] |
| 371 | except KeyError: |
| 372 | if len(_cache) > 100: |
| 373 | _cache.clear() |
| 374 | if path[:1] == "/": |
| 375 | raise SyntaxError("cannot use absolute path on element") |
| 376 | next = iter(xpath_tokenizer(path, namespaces)).__next__ |
| 377 | try: |
| 378 | token = next() |
| 379 | except StopIteration: |
| 380 | return |
| 381 | selector = [] |
| 382 | while 1: |
| 383 | try: |
| 384 | selector.append(ops[token[0]](next, token)) |
| 385 | except StopIteration: |
| 386 | raise SyntaxError("invalid path") from None |
| 387 | try: |
| 388 | token = next() |
| 389 | if token[0] == "/": |
| 390 | token = next() |
| 391 | except StopIteration: |
| 392 | break |
| 393 | _cache[cache_key] = selector |
| 394 | # execute selector pattern |
| 395 | result = [elem] |
| 396 | context = _SelectorContext(elem) |
| 397 | for select in selector: |
| 398 | result = select(context, result) |
| 399 | return result |
| 400 | |
| 401 | ## |
| 402 | # Find first matching object. |
no test coverage detected
searching dependent graphs…