<s> import re <EOL> xpath_tokenizer_re = re . compile ( <EOL> "<STR_LIT:(>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) <EOL> def xpath_tokenizer ( pattern , namespaces = None ) : <EOL> for token in xpath_tokenizer_re . findall ( pattern ) : <EOL> tag = token [ <NUM_LIT:1> ] <EOL> if tag and tag [ <NUM_LIT:0> ] != "<STR_LIT:{>" and "<STR_LIT::>" in tag : <EOL> try : <EOL> prefix , uri = tag . split ( "<STR_LIT::>" , <NUM_LIT:1> ) <EOL> if not namespaces : <EOL> raise KeyError <EOL> yield token [ <NUM_LIT:0> ] , "<STR_LIT>" % ( namespaces [ prefix ] , uri ) <EOL> except KeyError : <EOL> raise SyntaxError ( "<STR_LIT>" % prefix ) <EOL> else : <EOL> yield token <EOL> def prepare_child ( next , token ) : <EOL> tag = token [ <NUM_LIT:1> ] <EOL> def select ( result ) : <EOL> for elem in result : <EOL> for e in elem . iterchildren ( tag ) : <EOL> yield e <EOL> return select <EOL> def prepare_star ( next , token ) : <EOL> def select ( result ) : <EOL> for elem in result : <EOL> for e in elem . iterchildren ( '<STR_LIT:*>' ) : <EOL> yield e <EOL> return select <EOL> def prepare_self ( next , token ) : <EOL> def select ( result ) : <EOL> return result <EOL> return select <EOL> def prepare_descendant ( next , token ) : <EOL> token = next ( ) <EOL> if token [ <NUM_LIT:0> ] == "<STR_LIT:*>" : <EOL> tag = "<STR_LIT:*>" <EOL> elif not token [ <NUM_LIT:0> ] : <EOL> tag = token [ <NUM_LIT:1> ] <EOL> else : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> def select ( result ) : <EOL> for elem in result : <EOL> for e in elem . iterdescendants ( tag ) : <EOL> yield e <EOL> return select <EOL> def prepare_parent ( next , token ) : <EOL> def select ( result ) : <EOL> for elem in result : <EOL> parent = elem . getparent ( ) <EOL> if parent is not None : <EOL> yield parent <EOL> return select <EOL> def prepare_predicate ( next , token ) : <EOL> signature = [ ] <EOL> predicate = [ ] <EOL> while <NUM_LIT:1> : <EOL> token = next ( ) <EOL> if token [ <NUM_LIT:0> ] == "<STR_LIT:]>" : <EOL> break <EOL> if token [ <NUM_LIT:0> ] and token [ <NUM_LIT:0> ] [ : <NUM_LIT:1> ] in "<STR_LIT>" : <EOL> token = "<STR_LIT:'>" , token [ <NUM_LIT:0> ] [ <NUM_LIT:1> : - <NUM_LIT:1> ] <EOL> signature . append ( token [ <NUM_LIT:0> ] or "<STR_LIT:->" ) <EOL> predicate . append ( token [ <NUM_LIT:1> ] ) <EOL> signature = "<STR_LIT>" . join ( signature ) <EOL> if signature == "<STR_LIT>" : <EOL> key = predicate [ <NUM_LIT:1> ] <EOL> def select ( result ) : <EOL> for elem in result : <EOL> if elem . get ( key ) is not None : <EOL> yield elem <EOL> return select <EOL> if signature == "<STR_LIT>" : <EOL> key = predicate [ <NUM_LIT:1> ] <EOL> value = predicate [ - <NUM_LIT:1> ] <EOL> def select ( result ) : <EOL> for elem in result : <EOL> if elem . get ( key ) == value : <EOL> yield elem <EOL> return select <EOL> if signature == "<STR_LIT:->" and not re . match ( "<STR_LIT>" , predicate [ <NUM_LIT:0> ] ) : <EOL> tag = predicate [ <NUM_LIT:0> ] <EOL> def select ( result ) : <EOL> for elem in result : <EOL> for _ in elem . iterchildren ( tag ) : <EOL> yield elem <EOL> break <EOL> return select <EOL> if signature == "<STR_LIT>" and not re . match ( "<STR_LIT>" , predicate [ <NUM_LIT:0> ] ) : <EOL> tag = predicate [ <NUM_LIT:0> ] <EOL> value = predicate [ - <NUM_LIT:1> ] <EOL> def select ( result ) : <EOL> for elem in result : <EOL> for e in elem . iterchildren ( tag ) : <EOL> if "<STR_LIT>" . join ( e . itertext ( ) ) == value : <EOL> yield elem <EOL> break <EOL> return select <EOL> if signature == "<STR_LIT:->" or signature == "<STR_LIT>" or signature == "<STR_LIT>" : <EOL> if signature == "<STR_LIT:->" : <EOL> index = int ( predicate [ <NUM_LIT:0> ] ) - <NUM_LIT:1> <EOL> if index < <NUM_LIT:0> : <EOL> if index == - <NUM_LIT:1> : <EOL> raise SyntaxError ( <EOL> "<STR_LIT>" ) <EOL> else : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> else : <EOL> if predicate [ <NUM_LIT:0> ] != "<STR_LIT>" : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> if signature == "<STR_LIT>" : <EOL> try : <EOL> index = int ( predicate [ <NUM_LIT:2> ] ) - <NUM_LIT:1> <EOL> except ValueError : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> else : <EOL> index = - <NUM_LIT:1> <EOL> def select ( result ) : <EOL> for elem in result : <EOL> parent = elem . getparent ( ) <EOL> if parent is None : <EOL> continue <EOL> try : <EOL> elems = list ( parent . iterchildren ( elem . tag ) ) <EOL> if elems [ index ] is elem : <EOL> yield elem <EOL> except IndexError : <EOL> pass <EOL> return select <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> ops = { <EOL> "<STR_LIT>" : prepare_child , <EOL> "<STR_LIT:*>" : prepare_star , <EOL> "<STR_LIT:.>" : prepare_self , <EOL> "<STR_LIT:..>" : prepare_parent , <EOL> "<STR_LIT>" : prepare_descendant , <EOL> "<STR_LIT:[>" : prepare_predicate , <EOL> } <EOL> _cache = { } <EOL> def _build_path_iterator ( path , namespaces ) : <EOL> if path [ - <NUM_LIT:1> : ] == "<STR_LIT:/>" : <EOL> path = path + "<STR_LIT:*>" <EOL> try : <EOL> return _cache [ ( path , namespaces and tuple ( sorted ( namespaces . items ( ) ) ) or None ) ] <EOL> except KeyError : <EOL> pass <EOL> if len ( _cache ) > <NUM_LIT:100> : <EOL> _cache . clear ( ) <EOL> if path [ : <NUM_LIT:1> ] == "<STR_LIT:/>" : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> stream = iter ( xpath_tokenizer ( path , namespaces ) ) <EOL> try : <EOL> _next = stream . next <EOL> except AttributeError : <EOL> _next = stream . __next__ <EOL> try : <EOL> token = _next ( ) <EOL> except StopIteration : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> selector = [ ] <EOL> while <NUM_LIT:1> : <EOL> try : <EOL> selector . append ( ops [ token [ <NUM_LIT:0> ] ] ( _next , token ) ) <EOL> except StopIteration : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> try : <EOL> token = _next ( ) <EOL> if token [ <NUM_LIT:0> ] == "<STR_LIT:/>" : <EOL> token = _next ( ) <EOL> except StopIteration : <EOL> break <EOL> _cache [ path ] = selector <EOL> return selector <EOL> def iterfind ( elem , path , namespaces = None ) : <EOL> selector = _build_path_iterator ( path , namespaces ) <EOL> result = iter ( ( elem , ) ) <EOL> for select in selector : <EOL> result = select ( result ) <EOL> return result <EOL> def find ( elem , path , namespaces = None ) : <EOL> it = iterfind ( elem , path , namespaces ) <EOL> try : <EOL> try : <EOL> _next = it . next <EOL> except AttributeError : <EOL> return next ( it ) <EOL> else : <EOL> return _next ( ) <EOL> except StopIteration : <EOL> return None <EOL> def findall ( elem , path , namespaces = None ) : <EOL> return list ( iterfind ( elem , path , namespaces ) ) <EOL> def findtext ( elem , path , default = None , namespaces = None ) : <EOL> el = find ( elem , path , namespaces ) <EOL> if el is None : <EOL> return default <EOL> else : <EOL> return el . text or '<STR_LIT>' </s>
