struct
    type t = { 
      _type : [ `unknown | `tRNA | `rRNA | `snRNA | `scRNA |
                `snoRNA | `protein_coding | `pseudo | `transposon | `miscRNA |
                `ncRNA | `other ] ;
      
      summary : string option ;
      gene : Gene_ref.t ;
    }

    let type_of_int = function
    | 0 -> `unknown
    | 1 -> `tRNA
    | 2 -> `rRNA
    | 3 -> `snRNA
    | 4 -> `scRNA
    | 5 -> `snoRNA
    | 6 -> `protein_coding
    | 7 -> `pseudo
    | 8 -> `transposon
    | 9 -> `miscRNA
    | 10 -> `ncRNA
    | 11 -> `ncRNA
    | n -> invalid_arg (sprintf "Entrez.Make.Gene.type_of_int: %d" n)

    let parse_entrez_gene = function
    | E ("Entrezgene",_,_) as x -> Some {
      summary = sleaf "Entrezgene_summary" x ;
      _type = type_of_int (ileaf_exn "Entrezgene_type" x) ;
      gene = Gene_ref.of_xml (echild_exn "Entrezgene_gene" x) ;
    }
    | _ -> None

    let parse_entrez_gene_set = function
    | E ("Entrezgene-Set",_,children) ->
        List.filter_map ~f:parse_entrez_gene children
    | _ -> assert false

    let search query = 
      let database = `gene in
      let of_xml = parse_entrez_gene_set in
      let query_url = esearch_url database query in
      (* print_endline query_url ; *)
      fetch query_url esearch_answer_of_string >>= fun answer ->
      let object_url = efetch_url ~retmode:`xml database answer.ids in
      (* print_endline object_url ; *)
      fetch object_url (fun x -> x |> tree_of_string |> snd |> of_xml)
  end