Xml in OCaml

Our program demonstrates XML handling in OCaml using the Xml-light library. Here’s the full source code:

open Xml

(* Plant will be mapped to XML. *)
type plant = {
  id: int;
  name: string;
  origin: string list;
}

(* String representation of a plant *)
let string_of_plant p =
  Printf.sprintf "Plant id=%d, name=%s, origin=[%s]"
    p.id p.name (String.concat "; " p.origin)

(* Convert a plant to XML *)
let plant_to_xml p =
  Element ("plant", [("id", string_of_int p.id)], [
    Element ("name", [], [PCData p.name]);
    Element ("origin", [], List.map (fun o -> Element ("origin", [], [PCData o])) p.origin)
  ])

(* Convert XML to a plant *)
let xml_to_plant xml =
  match xml with
  | Element ("plant", attrs, children) ->
      let id = int_of_string (List.assoc "id" attrs) in
      let name = match List.find (fun e -> match e with Element ("name", _, _) -> true | _ -> false) children with
        | Element (_, _, [PCData n]) -> n
        | _ -> failwith "Invalid XML structure for name"
      in
      let origin = List.filter_map (function
        | Element ("origin", _, [PCData o]) -> Some o
        | _ -> None
      ) children
      in
      { id; name; origin }
  | _ -> failwith "Invalid XML structure"

let () =
  (* Create a plant *)
  let coffee = { id = 27; name = "Coffee"; origin = ["Ethiopia"; "Brazil"] } in

  (* Convert plant to XML *)
  let coffee_xml = plant_to_xml coffee in

  (* Print the XML *)
  print_endline (to_string_fmt coffee_xml);

  (* Convert XML back to plant *)
  let parsed_coffee = xml_to_plant coffee_xml in
  print_endline (string_of_plant parsed_coffee);

  (* Create another plant *)
  let tomato = { id = 81; name = "Tomato"; origin = ["Mexico"; "California"] } in

  (* Create a nesting structure *)
  let nesting = Element ("nesting", [], [
    Element ("parent", [], [
      Element ("child", [], [
        plant_to_xml coffee;
        plant_to_xml tomato
      ])
    ])
  ]) in

  (* Print the nested XML *)
  print_endline (to_string_fmt nesting)

To run the program, save it as xml_example.ml and use ocamlc to compile it:

$ ocamlfind ocamlc -o xml_example -package xml-light -linkpkg xml_example.ml
$ ./xml_example

This will output:

<plant id="27">
  <name>Coffee</name>
  <origin>Ethiopia</origin>
  <origin>Brazil</origin>
</plant>
Plant id=27, name=Coffee, origin=[Ethiopia; Brazil]
<nesting>
  <parent>
    <child>
      <plant id="27">
        <name>Coffee</name>
        <origin>Ethiopia</origin>
        <origin>Brazil</origin>
      </plant>
      <plant id="81">
        <name>Tomato</name>
        <origin>Mexico</origin>
        <origin>California</origin>
      </plant>
    </child>
  </parent>
</nesting>

This OCaml program demonstrates XML handling using the Xml-light library. It defines a plant type and provides functions to convert between the plant type and XML representation. The program creates plant instances, converts them to XML, prints the XML, and then parses it back into plant structures. It also demonstrates nested XML structures.

Note that OCaml doesn’t have built-in XML support like Go, so we’re using a third-party library. The concepts are similar, but the implementation details differ due to the language’s characteristics and available libraries.