2

I'm looking for a simple example for the ppx_xml_conv module from janestreet. I'm not terribly familiar with the (relatively) new ppx thing and can't really figure it out from the source code. Ultimately, I'm trying to write a client for an old SOAP service, and want to turn the xsd (from the wsdl) into a type and serializer/deserializer.

nlucaroni
  • 47,556
  • 6
  • 64
  • 86
Juan Chanco
  • 157
  • 6
  • 2
    I was going to post an answer, but can't get it working myself. I [reported](https://github.com/janestreet/ppx_xml_conv/issues/1) this. In the mean time, note all of Jane Street's ppx_*_conv packages work similarly. Since ppx_sexp_conv is the most commonly used, google'ing for it will lead to more results. The [ppx_variants_conv](https://github.com/janestreet/ppx_variants_conv) has a README that gives an example. – Ashish Agarwal Nov 06 '15 at 19:01
  • That gave me exactly what I needed. I too now get as far as "Error: Unbound module Fields." I saw the issue (and response) on github, so I'll probably wait until the ppx_driver framework is a little more stable. – Juan Chanco Nov 09 '15 at 18:46

2 Answers2

3

For those of you who, like me, tend to plunge ahead in ignorance, I would recommend looking at the readme for [ppx_driver] (https://github.com/janestreet/ppx_driver).

To summarize though, the basic procecure is, first build a driver (replace -package ppx_sexp_conv -package ppx_bin_prot with the conversion modules you're using):

$ ocamlfind ocamlopt -predicates ppx_driver -o ppx -linkpkg \
  -package ppx_sexp_conv -package ppx_bin_prot \
  ppx_driver_runner.cmxa

This will give you a ppx executable. Running this against your source file will dump the expanded version of the source.

$ ./ppx -help
ppx [extra_args] [files] ...
$ ./ppx src/myFile.ml

Then this executable can be used as a preprocessor when building.

$ ocamlc -c -pp ./ppx src/myFile.ml

My source had

type attr = {
  attr_id : string;
  attr_path : string;
  attr_value : string;
} [@@deriving xml]

and the preprocessor added to_xml t and from_xml xml functions.

As noted above though, this is as far as you'll get, since the ppx_driver framework still has a some outstanding issues.

Juan Chanco
  • 157
  • 6
  • 1
    You don't have to generate the executable and call it separately. There's a way to have the compiler to do this internally. I'll post an example. – Ashish Agarwal Nov 17 '15 at 16:06
3

Since there is a bug in ppx_xml_conv, I'll give an example for ppx_sexp_conv which works identically.

$ cat a.ml
open Sexplib.Std

type attr = {
  attr_id : string;
  attr_path : string;
  attr_value : string;
} [@@deriving sexp]

$ cat a.mli
type attr = {
  attr_id : string;
  attr_path : string;
  attr_value : string;
} [@@deriving sexp]

$ ocamlfind ocamlc -package sexplib,ppx_sexp_conv -dsource -c a.mli
type attr = {
  attr_id: string;
  attr_path: string;
  attr_value: string;}[@@deriving sexp]
val attr_of_sexp : Sexplib.Sexp.t -> attr
val sexp_of_attr : attr -> Sexplib.Sexp.t

$ ocamlfind ocamlc -package sexplib,ppx_sexp_conv -dsource -c a.ml
(* ... long output ... *)

I used the -dsource flag so you can see the generated output. Note that it wasn't necessary to create a ppx executable and call it separately. Compiling with the ppx_sexp_conv package causes that package's ppx extension to automatically get applied.

As another example here's an executable:

$ cat b.ml
open Sexplib.Std

type attr = {
  attr_id : string;
  attr_path : string;
  attr_value : string;
} [@@deriving sexp]

let x = {attr_id="abc"; attr_path="foo/bar"; attr_value="something"}

let () = Printf.printf "sexp: %s\n" (Sexplib.Sexp.to_string (sexp_of_attr x))

$ ocamlfind ocamlc -package sexplib,ppx_sexp_conv -linkpkg b.ml

$ ./a.out 
sexp: ((attr_id abc)(attr_path foo/bar)(attr_value something))
Ashish Agarwal
  • 3,000
  • 16
  • 18