| 1 |
(* Print XML documents, using PXP *)
|
| 2 |
|
| 3 |
open Pxp_aux
|
| 4 |
open Pxp_types
|
| 5 |
open Value
|
| 6 |
open Ident
|
| 7 |
module U = Encodings.Utf8
|
| 8 |
|
| 9 |
let exn_print_xml = CDuceExn (Pair (
|
| 10 |
Atom (Atoms.V.mk_ascii "Invalid_argument"),
|
| 11 |
string_latin1 "print_xml"))
|
| 12 |
|
| 13 |
let blank = U.mk " "
|
| 14 |
let true_literal = U.mk "true"
|
| 15 |
let false_literal = U.mk "false"
|
| 16 |
|
| 17 |
(* @raise exn_print_xml in case of failure. Rationale: schema printing is
|
| 18 |
* the last attempt to print a value, others have already failed *)
|
| 19 |
let rec schema_value ?(recurs=true) ~wds v =
|
| 20 |
match v with
|
| 21 |
| Record _ as v ->
|
| 22 |
(try
|
| 23 |
wds (Schema_builtin.string_of_time_type (Value.get_fields v))
|
| 24 |
with Schema_builtin.Error _ -> raise exn_print_xml)
|
| 25 |
| Integer i -> wds (U.mk (Intervals.V.to_string i))
|
| 26 |
| v when Value.equal v Value.vtrue -> wds true_literal
|
| 27 |
| v when Value.equal v Value.vfalse -> wds false_literal
|
| 28 |
| Pair _ as v when recurs -> schema_values ~wds v
|
| 29 |
| String_utf8 _ as v -> wds (fst (get_string_utf8 v))
|
| 30 |
| _ -> raise exn_print_xml
|
| 31 |
|
| 32 |
and schema_values ~wds v =
|
| 33 |
match v with
|
| 34 |
| Pair (hd, Atom a) when a = Sequence.nil_atom ->
|
| 35 |
schema_value ~recurs:false ~wds hd
|
| 36 |
| Pair (hd, tl) ->
|
| 37 |
schema_value ~recurs:false ~wds hd;
|
| 38 |
wds blank;
|
| 39 |
schema_values ~wds tl
|
| 40 |
| _ -> raise exn_print_xml
|
| 41 |
|
| 42 |
let string_of_xml ~utf8 ns_table v =
|
| 43 |
let to_enc = if utf8 then `Enc_utf8 else `Enc_iso88591 in
|
| 44 |
|
| 45 |
let buffer = Buffer.create 127 in
|
| 46 |
let printer = Ns.Printer.printer ns_table in
|
| 47 |
|
| 48 |
let wms =
|
| 49 |
write_markup_string
|
| 50 |
~from_enc:`Enc_utf8
|
| 51 |
~to_enc
|
| 52 |
(`Out_buffer buffer)
|
| 53 |
|
| 54 |
and wds s =
|
| 55 |
write_data_string
|
| 56 |
~from_enc:`Enc_utf8
|
| 57 |
~to_enc
|
| 58 |
(`Out_buffer buffer)
|
| 59 |
(U.get_str s)
|
| 60 |
in
|
| 61 |
let write_att (n,v) =
|
| 62 |
wms (" " ^ (Ns.Printer.attr printer n) ^ "=\""); wds v; wms "\"" in
|
| 63 |
let write_xmlns (pr,ns) =
|
| 64 |
let pr = U.get_str pr in
|
| 65 |
if pr = "" then wms " xmlns"
|
| 66 |
else (wms " xmlns:"; wms pr);
|
| 67 |
wms "=\"";
|
| 68 |
wds (Ns.value ns);
|
| 69 |
wms "\"" in
|
| 70 |
|
| 71 |
let element_start n xmlns attrs =
|
| 72 |
wms ("<" ^ (Ns.Printer.tag printer n));
|
| 73 |
List.iter write_xmlns xmlns;
|
| 74 |
List.iter write_att attrs;
|
| 75 |
wms ">"
|
| 76 |
and empty_element n xmlns attrs =
|
| 77 |
wms ("<" ^ (Ns.Printer.tag printer n));
|
| 78 |
List.iter write_xmlns xmlns;
|
| 79 |
List.iter write_att attrs;
|
| 80 |
wms "/>"
|
| 81 |
and element_end n =
|
| 82 |
wms ("</" ^ (Ns.Printer.attr printer n) ^ ">")
|
| 83 |
and document_start () =
|
| 84 |
(* wms ("<?xml version='1.0' encoding='" ^
|
| 85 |
Netconversion.string_of_encoding to_enc ^
|
| 86 |
"'?>\n") *)
|
| 87 |
()
|
| 88 |
in
|
| 89 |
|
| 90 |
let rec register_elt = function
|
| 91 |
| Xml (Atom tag, Record attrs, content) ->
|
| 92 |
List.iter
|
| 93 |
(fun (n,_) -> Ns.Printer.register_attr printer (LabelPool.value n))
|
| 94 |
(LabelMap.get attrs);
|
| 95 |
Ns.Printer.register_tag printer (Atoms.V.value tag);
|
| 96 |
register_content content
|
| 97 |
| _ -> ()
|
| 98 |
and register_content = function
|
| 99 |
| String_utf8 (_,_,_,q)
|
| 100 |
| String_latin1 (_,_,_,q) -> register_content q
|
| 101 |
| Pair (x, q) -> register_elt x; register_content q
|
| 102 |
| Concat (x,y) -> register_content x; register_content y
|
| 103 |
| _ -> ()
|
| 104 |
in
|
| 105 |
register_elt v;
|
| 106 |
|
| 107 |
let rec print_elt xmlns = function
|
| 108 |
| Xml (Atom tag, Record attrs, content) ->
|
| 109 |
let tag = Atoms.V.value tag in
|
| 110 |
let attrs = LabelMap.mapi_to_list
|
| 111 |
(fun n v ->
|
| 112 |
if is_str v then begin
|
| 113 |
let (s,q) = get_string_utf8 v in
|
| 114 |
match q with
|
| 115 |
| Atom a when a = Sequence.nil_atom ->
|
| 116 |
(LabelPool.value n), s
|
| 117 |
| _ -> raise exn_print_xml
|
| 118 |
end else begin
|
| 119 |
let buf = Buffer.create 20 in
|
| 120 |
let wds s = Buffer.add_string buf (U.get_str s) in
|
| 121 |
schema_value ~wds v;
|
| 122 |
(LabelPool.value n, U.mk (Buffer.contents buf))
|
| 123 |
end
|
| 124 |
) attrs in
|
| 125 |
(match content with
|
| 126 |
| Atom a when a = Sequence.nil_atom -> empty_element tag xmlns attrs
|
| 127 |
| _ ->
|
| 128 |
element_start tag xmlns attrs;
|
| 129 |
print_content content;
|
| 130 |
element_end tag)
|
| 131 |
| _ -> raise exn_print_xml
|
| 132 |
and print_content v =
|
| 133 |
let (s,q) = get_string_utf8 v in
|
| 134 |
wds s;
|
| 135 |
match q with
|
| 136 |
| Pair (Xml _ as x, q) -> print_elt [] x; print_content q
|
| 137 |
| Atom a when a = Sequence.nil_atom -> ()
|
| 138 |
| v -> schema_value ~wds v
|
| 139 |
in
|
| 140 |
document_start ();
|
| 141 |
print_elt (Ns.Printer.prefixes printer) v;
|
| 142 |
Buffer.contents buffer
|
| 143 |
|
| 144 |
let print_xml ~utf8 ns_table s =
|
| 145 |
try
|
| 146 |
let s = string_of_xml ~utf8 ns_table s in
|
| 147 |
if utf8 then string_utf8 (U.mk s) else string_latin1 s
|
| 148 |
with
|
| 149 |
CDuceExn _ as exn -> raise exn
|
| 150 |
| exn -> raise (Location.Generic (Pxp_types.string_of_exn exn))
|
| 151 |
|