parameters: ( filterpath )
return_statement: return specs, attr
docstring: >>> def parse_filter(path):
      ...     specs, attr =  _filterpath_to_node_specification(path)
      ...     return [(s.ns, s.tag, s.filter) for s in specs], attr
      ...
      >>> parse_filter('book[@author==Hopkins]/@barcode')
      ([('', 'book', '@author==Hopkins')], 'barcode')
      >>> parse_filter('books/*/title/author')
      ([('', 'books', ''), ('', '*', ''), ('', 'title', ''), ('', 'author', '')], None)
      >>> parse_filter('{ns}book[@price<20]/{ns}title')
      ([('{ns}', 'book', '@price<20'), ('{ns}', 'title', '')], None)
      >>> parse_filter('@id')
      ([], 'id')
      >>> parse_filter('@{ns}id')
      ([], '{ns}id')
      >>> parse_filter('{ns}@id')
      Traceback (most recent call last):
          ...
      InvalidFilterException
      >>> parse_filter('{ns}*')
      ([('{ns}', '*', '')], None)
      >>> parse_filter('{ns}*') == parse_filter('{ns}')
      True
      >>> parse_filter('{ns}/@id')
      ([('{ns}', '*', '')], 'id')
      >>> parse_filter('{ns}*[@name.startswith("A")]/@id')
      ([('{ns}', '*', '@name.startswith("A")')], 'id')
      >>> parse_filter('/portal/content-node[@create-type==explicit]/@action')
      ([('', 'portal', ''), ('', 'content-node', '@create-type==explicit')], 'action')
docstring_summary: >>> def parse_filter(path):
      ...     specs, attr =  _filterpath_to_node_specification(path)
      ...     return [(s.ns, s.tag, s.filter) for s in specs], attr
      ...
      >>> parse_filter('book[
docstring_tokens: >>> def parse_filter ( path ) : ... specs attr = _filterpath_to_node_specification ( path ) ... return [ ( s . ns s . tag s . filter ) for s in specs ] attr ... >>> parse_filter ( book [
function: def _filterpath_to_node_specification( filterpath ):
      '''
      >>> def parse_filter(path):
      ...     specs, attr =  _filterpath_to_node_specification(path)
      ...     return [(s.ns, s.tag, s.filter) for s in specs], attr
      ...
      >>> parse_filter('book[@author==Hopkins]/@barcode')
      ([('', 'book', '@author==Hopkins')], 'barcode')
      >>> parse_filter('books/*/title/author')
      ([('', 'books', ''), ('', '*', ''), ('', 'title', ''), ('', 'author', '')], None)
      >>> parse_filter('{ns}book[@price<20]/{ns}title')
      ([('{ns}', 'book', '@price<20'), ('{ns}', 'title', '')], None)
      >>> parse_filter('@id')
      ([], 'id')
      >>> parse_filter('@{ns}id')
      ([], '{ns}id')
      >>> parse_filter('{ns}@id')
      Traceback (most recent call last):
          ...
      InvalidFilterException
      >>> parse_filter('{ns}*')
      ([('{ns}', '*', '')], None)
      >>> parse_filter('{ns}*') == parse_filter('{ns}')
      True
      >>> parse_filter('{ns}/@id')
      ([('{ns}', '*', '')], 'id')
      >>> parse_filter('{ns}*[@name.startswith("A")]/@id')
      ([('{ns}', '*', '@name.startswith("A")')], 'id')
      >>> parse_filter('/portal/content-node[@create-type==explicit]/@action')
      ([('', 'portal', ''), ('', 'content-node', '@create-type==explicit')], 'action')
      '''
      specs = []
      #does the filterpath end with an attribute, eg. @id ?
      #Note: RE_ATTRIBUTE will produce id, not @id
      attr = re.search(RE_ATTRIBUTE, filterpath)
      if attr:
          attr = attr.group(0)
          #remove the attribute just found from the filterpath
          filterpath =  re.sub(RE_ATTRIBUTE, '', filterpath)
          #strip trailing @
          filterpath = filterpath[:-1]
          if filterpath and filterpath[-1] != '/': raise InvalidFilterException()
      else:
          attr = None
      if filterpath:
          #the filterpath passed to RE_XPATH.findall() must begin with a forward slash
          if filterpath[0] != '/':
              filterpath = '/' + filterpath
          #strip any trailing forward slash
          if filterpath[-1] == '/':
              filterpath = filterpath[:-1]
      for ns, tag, filter in RE_XPATH.findall(filterpath):
          specs.append( _NodeSpecification(ns, tag, filter) )
      return specs, attr
function_tokens: def _filterpath_to_node_specification ( filterpath ) : specs = [ ] #does the filterpath end with an attribute, eg. @id ? #Note: RE_ATTRIBUTE will produce id, not @id attr = re . search ( RE_ATTRIBUTE , filterpath ) if attr : attr = attr . group ( 0 ) #remove the attribute just found from the filterpath filterpath = re . sub ( RE_ATTRIBUTE , '' , filterpath ) #strip trailing @ filterpath = filterpath [ : - 1 ] if filterpath and filterpath [ - 1 ] != '/' : raise InvalidFilterException ( ) else : attr = None if filterpath : #the filterpath passed to RE_XPATH.findall() must begin with a forward slash if filterpath [ 0 ] != '/' : filterpath = '/' + filterpath #strip any trailing forward slash if filterpath [ - 1 ] == '/' : filterpath = filterpath [ : - 1 ] for ns , tag , filter in RE_XPATH . findall ( filterpath ) : specs . append ( _NodeSpecification ( ns , tag , filter ) ) return specs , attr