struct
  type t = {
    mslevel: int; 
      (** 1: MS, 2: MS/MS,... *)

    mz: float;  
       (** MassToChargeRatio *)

    z: float;   
        (** ChargeState *)

    int: float; 
      (** Intensity *)

  }

  (* Commission of atomic weights and isotopic abondance *)
  let mass_proton = 1.00727646677 (* Dalton *)

  let mass p = (p.mz -. mass_proton) *. p.z

  (* Get <ionSelection> content. FIXME: the spec does not define which
     param. should be present. *)

  let rec get_ionSelection xml p depth =
    match Xmlm.input xml with
    | `El_start((_, "cvParam"), attr) ->
      let depth = depth + 1 in (* for </cvParam> *)
      let name = attribute_exn "name" attr in
      let value = attribute_exn "value" attr in
      if name = "MassToChargeRatio" then
        get_ionSelection xml { p with mz = Float.of_string value } depth
      else if name = "ChargeState" then
        get_ionSelection xml { p with z = Float.of_string value } depth
      else if name = "Intensity" then
        get_ionSelection xml { p with int = Float.of_string value } depth
      else
        get_ionSelection xml p depth
    | `El_start _ -> get_ionSelection xml p (depth + 1)
    | `El_end -> if depth = 0 then p  (* </ionSelection> *)
                else get_ionSelection xml p (depth - 1)
    | `Data _ | `Dtd _ -> get_ionSelection xml p depth (* skip *)

  let rec get_precursor xml p =
    match Xmlm.input xml with
    | `El_start((_, "ionSelection"), _) -> get_ionSelection xml p 0
    | `El_start _ -> skip_tag xml; get_precursor xml p (* <activation> *)
    | `El_end -> p (* </precursor> *)
    | `Data _ | `Dtd _ -> get_precursor xml p

  (* Knowing that <precursorList> was just read, parse the [xml] to
     get the list of precursors.  *)

  let rec add_list xml pl =
    match Xmlm.input xml with
    | `El_start((_, "precursor"), attr) ->
      let mslevel = int_of_string(attribute_exn "msLevel" attr) in
      let p = get_precursor xml { mslevel; mz = Float.nan; z = Float.nan; int = Float.nan } in
      add_list xml (p :: pl)
    | `El_start _ -> skip_tag xml;  add_list xml pl
    | `El_end -> pl                      (* </precursorList> *)
    | `Data _ | `Dtd _ -> add_list xml pl

  let list xml = add_list xml []
end