/[svn]/schema/schema_parser.ml
ViewVC logotype

Contents of /schema/schema_parser.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 500 - (show annotations)
Tue Jul 10 17:39:22 2007 UTC (5 years, 10 months ago) by abate
File size: 19480 byte(s)
[r2003-06-12 11:54:45 by cvscast] Merging schema

Original author: cvscast
Date: 2003-06-12 11:54:49+00:00
1
2 open Printf ;;
3 open Pxp_document ;;
4 open Schema_types ;;
5
6 (* TODO when looking for xsd:{restriction,extension,...} has_element is used so
7 actually is possible that both more of them are provided.
8 IDEA: validate schema document using DTD for Schemas? *)
9
10 exception Not_implemented of string ;;
11
12 let debug = true ;;
13
14 let hashtbl_values tbl = Hashtbl.fold (fun _ valu acc -> valu :: acc) tbl [] ;;
15 let rec filter_out_none = function (* not tail recursive *)
16 | [] -> []
17 | Some v :: tl -> v :: filter_out_none tl
18 | None :: tl -> filter_out_none tl
19 ;;
20
21 let get_facet_nodes n = [] (* TODO facets *) ;;
22 let restrict_simple_type base_type_def facets = base_type_def ;;
23 let get_minOccurs n =
24 try
25 int_of_string n#extension#minOccurs
26 with Not_found -> 1
27 ;;
28 let get_maxOccurs n =
29 try
30 (match n#extension#maxOccurs with
31 | "unbounded" -> None
32 | s -> Some (int_of_string s))
33 with Not_found -> Some 1
34 ;;
35
36 let content_type_of_def = function
37 | S def -> CT_simple def
38 | C (CBuilt_in _) -> assert false
39 | C (CUser_defined (_, _, _, _, ct)) -> ct
40 ;;
41
42 let parse_facet resolver base_type_def n =
43 let validate_base_type =
44 Schema_validator.validate_simple_type base_type_def
45 in
46 let value =
47 try
48 n#extension#value
49 with Not_found ->
50 raise (XSD_validation_error "Missing required 'value' attribute")
51 in
52 let fixed =
53 try
54 bool_of_string n#extension#fixed
55 with
56 | Not_found -> false
57 | Invalid_argument "bool_of_string" ->
58 raise (XSD_validation_error (sprintf
59 "Invalid value for 'fixed' attribute: '%s'" n#extension#fixed))
60 in
61 match n#node_type with
62 | T_element "xsd:length" ->
63 let length =
64 Value.get_int (Schema_builtin.validate_nonNegativeInteger value)
65 in
66 F_length (length, fixed)
67 | T_element "xsd:minLength" ->
68 let length =
69 Value.get_int (Schema_builtin.validate_nonNegativeInteger value)
70 in
71 F_minLength (length, fixed)
72 | T_element "xsd:maxLength" ->
73 let length =
74 Value.get_int (Schema_builtin.validate_nonNegativeInteger value)
75 in
76 F_maxLength (length, fixed)
77 | T_element "xsd:pattern" -> (* TODO Schema regexp <> PCRE regexp :-(( *)
78 F_pattern (Pcre.regexp value)
79 | T_element "xsd:enumeration" ->
80 F_enumeration (ValueSet.singleton (validate_base_type value))
81 | T_element "xsd:whiteSpace" ->
82 F_whiteSpace
83 ((match value with
84 | "collapse" -> WS_collapse
85 | "preserve" -> WS_preserve
86 | "replace" -> WS_replace
87 | _ ->
88 raise (XSD_validation_error (sprintf
89 "'%s' isn't a valid whiteSpace value" value))),
90 fixed)
91 | T_element "xsd:maxInclusive" ->
92 F_maxInclusive (validate_base_type value, fixed)
93 | T_element "xsd:maxExclusive" ->
94 F_maxExclusive (validate_base_type value, fixed)
95 | T_element "xsd:minInclusive" ->
96 F_minInclusive (validate_base_type value, fixed)
97 | T_element "xsd:minExclusive" ->
98 F_minExclusive (validate_base_type value, fixed)
99 | T_element "xsd:totalDigits" ->
100 let digits =
101 Value.get_int (Schema_builtin.validate_positiveInteger value)
102 in
103 F_totalDigits (digits, fixed)
104 | T_element "xsd:fractionDigits" ->
105 let digits =
106 Value.get_int (Schema_builtin.validate_nonNegativeInteger value)
107 in
108 F_fractionDigits (digits, fixed)
109 | T_element unexpected ->
110 raise (XSD_validation_error (sprintf "'%s' isn't a valid facet element"
111 unexpected))
112 | _ -> assert false
113 ;;
114
115 let parse_simple_type resolver n =
116 assert (n#node_type = T_element "xsd:simpleType");
117 SBuilt_in "FAKE" (* TODO facets *)
118 (* FINQUI *)
119 ;;
120
121 (** @return a value_constraint option from a attribute node *)
122 let constr_of_attr_node n validate =
123 let (default, fixed) =
124 ((try Some n#extension#default with Not_found -> None),
125 (try Some n#extension#fixed with Not_found -> None))
126 in
127 try
128 (match default, fixed with
129 | Some v, None -> Some (Default (validate v))
130 | None, Some v -> Some (Fixed (validate v))
131 | None, None -> None
132 | Some _, Some _ ->
133 raise (XSD_validation_error ("Both 'default' and 'fixed' specified for \
134 attribute " ^ n#extension#name)))
135 with XSI_validation_error _ ->
136 raise (XSD_validation_error ("Invalid value for constraint on \
137 attribute " ^ n#extension#name))
138 ;;
139
140 let parse_att_decl resolver n =
141 let name = n#extension#name in
142 match n#parent#node_type with
143 | T_element "xsd:schema" -> (* global element *)
144 let simple_type_def =
145 (try
146 parse_simple_type resolver (find_element "xsd:simpleType" n)
147 with Not_found ->
148 (try
149 (match !(resolver#resolve_typ n#extension#typ) with
150 | S st -> st
151 | C _ -> failwith "Attributes can only assume simple type values")
152 with Not_found -> SBuilt_in "xsd:anySimpleType"))
153 in
154 let self_validate =
155 Schema_validator.validate_simple_type simple_type_def
156 in
157 let constr = constr_of_attr_node n self_validate in
158 name, ref simple_type_def, constr
159 | _ -> assert false (* you have to use parse_attribute_use *)
160 ;;
161
162 (** @return an attribute_use option. None means that the attribute is
163 prohibited *)
164 let parse_attribute_use resolver n =
165 assert
166 (match n#node_type with T_element "xsd:attribute" -> true | _ -> false);
167 let prohibited = try n#extension#prohibited with Not_found -> false in
168 if prohibited then (* attribute prohibited *)
169 None
170 else begin (* attribute not prohibited *)
171 let required = try n#extension#required with Not_found -> false in
172 if n#extension#has_attribute "ref" then begin (* "ref" attribute *)
173 let att_decl = !(resolver#resolve_att n#extension#ref) in
174 let simple_type_def = match att_decl with (_, std, _) -> !std in
175 let self_validate =
176 Schema_validator.validate_simple_type simple_type_def
177 in
178 let constr = constr_of_attr_node n self_validate in
179 Some (required, att_decl, constr)
180 end else begin (* no "ref" attribute *)
181 let name = n#extension#name in
182 let simple_type_def =
183 (try
184 parse_simple_type resolver (find_element "xsd:simpleType" n)
185 with Not_found ->
186 (try
187 (match !(resolver#resolve_typ n#extension#typ) with
188 | S st -> st
189 | C _ -> failwith "Attributes can only assume simple type values")
190 with Not_found -> SBuilt_in "xsd:anySimpleType"))
191 in
192 let self_validate =
193 Schema_validator.validate_simple_type simple_type_def
194 in
195 let att_decl = name, ref simple_type_def, None in
196 let constr = constr_of_attr_node n self_validate in
197 Some (required, att_decl, constr)
198 end
199 end
200 ;;
201
202 (** @return a list of attribute uses from a xsd:restriction node wrt a base
203 type definition *)
204 let attribute_uses_of_restriction ~resolver ~n ~base =
205 let embedded = (* associative list <name, attribute_use option> *)
206 List.map
207 (fun n ->
208 let use = parse_attribute_use resolver n in
209 n#extension#name, use)
210 n#extension#find_attributes
211 in
212 let from_base =
213 match base with
214 | C (CUser_defined (_, _, _, attribute_uses, _)) ->
215 List.filter (* filters out attribute uses redefined and
216 prohibited in this type *)
217 (fun use ->
218 not (List.mem_assoc (name_of_attribute_use use) embedded))
219 attribute_uses
220 | _ -> []
221 in
222 (* remove prohibited from embedded attribute list *)
223 filter_out_none (snd (List.split embedded)) @ from_base
224 ;;
225
226 (** @return a list of attribute uses from a xsd:extension node wrt a base type
227 definition *)
228 let attribute_uses_of_extension ~resolver ~n ~base =
229 let embedded = (* attribute_use option list *)
230 List.map (parse_attribute_use resolver) n#extension#find_attributes
231 in
232 let from_base =
233 match base with
234 | C (CUser_defined (_, _, _, attribute_uses, _)) -> attribute_uses
235 | _ -> []
236 in
237 filter_out_none embedded @ from_base
238 ;;
239
240 let rec parse_complex_type resolver n =
241 let name = try Some n#extension#name with Not_found -> None in
242 if n#extension#has_element "xsd:simpleContent" then begin
243 let content = find_element "xsd:simpleContent" n in
244 if content#extension#has_element "xsd:restriction" then begin
245 (* simpleContent, restriction *)
246 let restriction = find_element "xsd:restriction" content in
247 let base = resolver#resolve_typ restriction#extension#base in
248 let attribute_uses =
249 attribute_uses_of_restriction ~resolver ~n:restriction ~base:!base
250 in
251 let content_type =
252 (match !base with
253 | C (CUser_defined (_, _, _, _, (CT_simple base))) ->
254 let base =
255 try
256 parse_simple_type resolver
257 (find_element "xsd:simpleType" restriction)
258 with Not_found -> base
259 in
260 CT_simple (restrict_simple_type base (get_facet_nodes n))
261 | _ -> assert false)
262 in
263 CUser_defined (name, base, Restriction, attribute_uses, content_type)
264 end else if content#extension#has_element "xsd:extension" then begin
265 (* simpleContent, extension *)
266 let extension = find_element "xsd:extension" content in
267 let base = resolver#resolve_typ extension#extension#base in
268 let attribute_uses =
269 attribute_uses_of_extension ~resolver ~n:extension ~base:!base
270 in
271 let content_type =
272 (match !base with
273 | C (CUser_defined (_, _, _, _, (CT_simple base))) -> CT_simple base
274 | S simple_type_def -> CT_simple simple_type_def
275 | _ -> assert false)
276 in
277 CUser_defined (name, base, Extension, attribute_uses, content_type)
278 end else
279 (* simpleContent, neither extension nor restriction *)
280 raise (XSD_validation_error "Neither <extension> nor <restriction> \
281 element inside <simpleContent> element")
282 end else if n#extension#has_element "xsd:complexContent" then begin
283 let content = find_element "xsd:complexContent" n in
284 if content#extension#has_element "xsd:restriction" then begin
285 (* complexContent, restriction *)
286 let restriction = find_element "xsd:restriction" content in
287 let base = resolver#resolve_typ restriction#extension#base in
288 let attribute_uses =
289 attribute_uses_of_restriction ~resolver ~n:restriction ~base:!base
290 in
291 let content_type =
292 if restriction#extension#has_no_term then begin
293 CT_empty
294 end else begin
295 let mixed =
296 (try content#extension#mixed with Not_found ->
297 (try restriction#extension#mixed with Not_found -> false))
298 in
299 CT_model
300 (parse_particle resolver restriction#extension#find_term, mixed)
301 end
302 in
303 CUser_defined (name, base, Restriction, attribute_uses, content_type)
304 end else if content#extension#has_element "xsd:extension" then begin
305 (* complexContent, extension *)
306 let extension = find_element "xsd:extension" content in
307 let base = resolver#resolve_typ extension#extension#base in
308 let attribute_uses =
309 attribute_uses_of_extension ~resolver ~n:extension ~base:!base
310 in
311 let content_type =
312 let mixed =
313 (try content#extension#mixed with Not_found ->
314 (try extension#extension#mixed with Not_found -> false))
315 in
316 let base_ct = content_type_of_def !base in
317 if extension#extension#has_no_term then
318 base_ct
319 else
320 match base_ct with
321 | CT_empty ->
322 CT_model
323 (parse_particle resolver extension#extension#find_term, mixed)
324 | CT_model (p, _) ->
325 CT_model
326 ((1, Some 1, Sequence
327 (p::[parse_particle resolver extension#extension#find_term])),
328 mixed)
329 | _ -> assert false
330 in
331 CUser_defined (name, base, Extension, attribute_uses, content_type)
332 end else
333 (* complexContent, neither extension nor restriction *)
334 raise (XSD_validation_error "Neither <extension> nor <restriction> \
335 element inside <complexContent> element")
336 end else begin
337 (* neither simpleContent nor simpleContent, therefore ... *)
338 (* ... complexContent, restriction: shortcut *)
339 let base = resolver#resolve_typ "xsd:anyType" in
340 let attribute_uses =
341 attribute_uses_of_restriction ~resolver ~n ~base:!base
342 in
343 let content_type =
344 if n#extension#has_no_term then begin
345 CT_empty
346 end else begin
347 let mixed = false in
348 CT_model (parse_particle resolver n#extension#find_term, mixed)
349 end
350 in
351 CUser_defined (name, base, Restriction, attribute_uses, content_type)
352 end
353
354 and parse_elt_decl resolver n =
355 match n#parent#node_type with
356 | T_element "xsd:schema" -> (* global element *)
357 let name = n#extension#name in
358 let type_def =
359 (try
360 S (parse_simple_type resolver (find_element "xsd:simpleType" n))
361 with Not_found ->
362 (try
363 C (parse_complex_type resolver (find_element "xsd:complexType" n))
364 with Not_found ->
365 !(resolver#resolve_typ n#extension#typ)))
366 in
367 name, ref type_def, None
368 | _ -> assert false (* you have to use parse_particle *)
369
370 and parse_particle resolver n =
371 let (minOccurs, maxOccurs) = (get_minOccurs n, get_maxOccurs n) in
372 match n#node_type with
373 | T_element "xsd:element" when not (n#extension#has_attribute "ref") ->
374 let name = n#extension#name in
375 let type_def =
376 (try
377 S (parse_simple_type resolver (find_element "xsd:simpleType" n))
378 with Not_found ->
379 (try
380 C (parse_complex_type resolver (find_element "xsd:complexType" n))
381 with Not_found ->
382 !(resolver#resolve_typ n#extension#typ)))
383 in
384 minOccurs, maxOccurs, Elt (ref (name, ref type_def, None))
385 | T_element "xsd:element" when n#extension#has_attribute "ref" ->
386 let elt_decl = resolver#resolve_elt n#extension#ref in
387 minOccurs, maxOccurs, (Elt elt_decl)
388 | T_element "xsd:all" ->
389 minOccurs, maxOccurs,
390 All (List.map (parse_particle resolver) n#extension#find_terms)
391 | T_element "xsd:sequence" ->
392 minOccurs, maxOccurs,
393 Sequence (List.map (parse_particle resolver) n#extension#find_terms)
394 | T_element "xsd:choice" ->
395 minOccurs, maxOccurs,
396 Choice (List.map (parse_particle resolver) n#extension#find_terms)
397 | _ -> assert false
398
399 ;;
400
401 module OrderedNode =
402 struct
403 type t = Schema_xml.schema_extension node
404 let compare = Pxp_document.compare
405 end
406 ;;
407 module NodeSet = Set.Make (OrderedNode) ;;
408
409 (* lazy resolver: resolve types/elements/attributes as soon as it encounter
410 references to them. DOESN'T WORK WITH RECURSIVE ENTITIES [ probably it loops ]
411
412 @param node schema document root node
413 *)
414 class lazy_resolver node =
415 object (self)
416
417 val typs = Hashtbl.create 17
418 val attrs = Hashtbl.create 17
419 val elts = Hashtbl.create 17
420
421 val mutable seen_nodes = NodeSet.empty
422
423 initializer (* register built-in types *)
424 List.iter (fun name -> Hashtbl.add typs name (ref (S (SBuilt_in name))))
425 Schema_builtin.names
426
427 method already_seen n = NodeSet.mem n seen_nodes
428
429 method private register_typ' node name def =
430 if Hashtbl.mem typs name then
431 failwith ("Redefinition of type: " ^ name);
432 if debug then
433 (Format.fprintf Format.std_formatter
434 "\nSchema_parser: registering TYPE %s:\n%a\n"
435 name print_type !def;
436 Format.pp_print_flush Format.std_formatter ());
437 Hashtbl.add typs name def;
438 seen_nodes <- NodeSet.add node seen_nodes
439
440 method private register_elt' node name decl =
441 if Hashtbl.mem elts name then
442 failwith ("Redefinition of element: " ^ name);
443 if debug then
444 (Format.fprintf Format.std_formatter
445 "\nSchema_parser: registering ELEMENT %s:\n%a\n"
446 name print_elt_decl !decl;
447 Format.pp_print_flush Format.std_formatter ());
448 Hashtbl.add elts name decl;
449 seen_nodes <- NodeSet.add node seen_nodes
450
451 method private register_att' node name decl =
452 if Hashtbl.mem attrs name then
453 failwith ("Redefinition of attribute: " ^ name);
454 if debug then
455 (Format.fprintf Format.std_formatter
456 "\nSchema_parser: registering ATTRIBUTE %s:\n%a\n"
457 name print_att_decl !decl;
458 Format.pp_print_flush Format.std_formatter ());
459 Hashtbl.add attrs name decl;
460 seen_nodes <- NodeSet.add node seen_nodes
461
462 method register_simple_type n =
463 let st_def = parse_simple_type (self :> resolver) n in
464 self#register_typ' n n#extension#name (ref (S st_def))
465
466 method register_complex_type n =
467 let ct_def = parse_complex_type (self :> resolver) n in
468 self#register_typ' n n#extension#name (ref (C ct_def))
469
470 method register_elt n =
471 let elt_decl = parse_elt_decl (self :> resolver) n in
472 self#register_elt' n n#extension#name (ref elt_decl)
473
474 method type_defs = List.map (!) (hashtbl_values typs)
475 method att_decls = List.map (!) (hashtbl_values attrs)
476 method elt_decls = List.map (!) (hashtbl_values elts)
477
478 method resolve_typ name =
479 (try
480 Hashtbl.find typs name
481 with Not_found ->
482 (try
483 let node = node#extension#find_simpleType name in
484 let typ_def = ref (S (parse_simple_type (self :> resolver) node)) in
485 self#register_typ' node name typ_def;
486 typ_def
487 with Not_found ->
488 (try
489 let node = node#extension#find_complexType name in
490 let typ_def =
491 ref (C (parse_complex_type (self :> resolver) node))
492 in
493 self#register_typ' node name typ_def;
494 typ_def
495 with Not_found ->
496 failwith ("Can't find definition of type: " ^ name))))
497
498 method resolve_elt name =
499 (try
500 Hashtbl.find elts name
501 with Not_found ->
502 (try
503 let node = node#extension#find_global_element name in
504 let elt_decl = ref (parse_elt_decl (self :> resolver) node) in
505 self#register_elt' node name elt_decl;
506 elt_decl
507 with Not_found ->
508 failwith ("Can't find declaration of element: " ^ name)))
509
510 method resolve_att name =
511 (try
512 Hashtbl.find attrs name
513 with Not_found ->
514 (try
515 let node = node#extension#find_global_attribute name in
516 let att_decl = ref (parse_att_decl (self :> resolver) node) in
517 self#register_att' node name att_decl;
518 att_decl
519 with Not_found ->
520 failwith ("Can't find declaration of attribute: " ^ name)))
521
522 end
523 ;;
524
525 let parse_schema doc =
526 let root = doc#root in
527 let resolver = new lazy_resolver root in
528 root#iter_nodes (fun n ->
529 if not (resolver#already_seen n) then
530 (match n#node_type with
531 | T_element "xsd:element" -> resolver#register_elt n
532 | T_element "xsd:simpleType" -> resolver#register_simple_type n
533 | T_element "xsd:complexType" -> resolver#register_complex_type n
534 | T_element e -> failwith ("Unexpected root element " ^ e)
535 | _ -> ()));
536 {
537 type_defs = resolver#type_defs;
538 att_decls = resolver#att_decls;
539 elt_decls = resolver#elt_decls;
540 }
541 ;;
542

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5