| 1 |
|
| 2 |
open Printf
|
| 3 |
open Pxp_document
|
| 4 |
|
| 5 |
open Encodings
|
| 6 |
open Encodings.Utf8.Pcre
|
| 7 |
open Schema_common
|
| 8 |
open Schema_types
|
| 9 |
open Schema_validator
|
| 10 |
open Schema_xml
|
| 11 |
open Schema_xml.Pxp_helpers
|
| 12 |
|
| 13 |
let debug = false
|
| 14 |
let debug_print ?(n: pxp_node option) s =
|
| 15 |
if debug then
|
| 16 |
(match n with
|
| 17 |
| None -> prerr_endline s
|
| 18 |
| Some n ->
|
| 19 |
let line = match n#position with (_,l,_) -> l in
|
| 20 |
prerr_endline (sprintf "[%d] %s" line s);
|
| 21 |
flush stderr)
|
| 22 |
|
| 23 |
let space_RE = pcre_regexp " "
|
| 24 |
let split s = pcre_split ~rex:space_RE s
|
| 25 |
let unqualify s = snd (Ns.split_qname s)
|
| 26 |
let hashtbl_deref tbl =
|
| 27 |
(* ASSUMPTION: no multiple bindings *)
|
| 28 |
let tbl' = Hashtbl.create 1024 in
|
| 29 |
Hashtbl.iter (fun key value -> Hashtbl.add tbl' key !value) tbl;
|
| 30 |
tbl'
|
| 31 |
let hashtbl_values tbl = Hashtbl.fold (fun _ v acc -> v :: acc) tbl []
|
| 32 |
|
| 33 |
class type resolver =
|
| 34 |
object
|
| 35 |
(** add a node to the list of "seen" nodes.
|
| 36 |
@raise Osv_validation_error if the same node is seen twice *)
|
| 37 |
method see : pxp_node -> unit
|
| 38 |
|
| 39 |
method resolve_att: ?fix_ns:bool -> Utf8.t -> attribute_declaration
|
| 40 |
method resolve_elt:
|
| 41 |
?fix_ns:bool -> now:bool -> Utf8.t -> element_declaration ref
|
| 42 |
method resolve_typ:
|
| 43 |
?fix_ns:bool -> now:bool -> Utf8.t -> type_definition ref
|
| 44 |
method resolve_att_group:
|
| 45 |
?fix_ns:bool -> Utf8.t -> attribute_group_definition
|
| 46 |
method resolve_model_group: ?fix_ns:bool -> Utf8.t -> model_group_definition
|
| 47 |
method resolve_simple_typ: ?fix_ns:bool -> Utf8.t -> simple_type_definition
|
| 48 |
end
|
| 49 |
|
| 50 |
module OrderedNode =
|
| 51 |
struct
|
| 52 |
type t = pxp_node
|
| 53 |
let compare = Pxp_document.compare
|
| 54 |
end
|
| 55 |
module NodeSet = Set.Make (OrderedNode)
|
| 56 |
|
| 57 |
(* element and complex type constructors which take cares of unique id *)
|
| 58 |
let element, complex =
|
| 59 |
let counter = ref 0 in
|
| 60 |
let element name (type_def: type_definition ref) constr =
|
| 61 |
incr counter;
|
| 62 |
!counter, name, type_def, constr
|
| 63 |
in
|
| 64 |
let complex name (type_def: type_definition) deriv attrs ct =
|
| 65 |
incr counter;
|
| 66 |
!counter, name, type_def, deriv, attrs, ct
|
| 67 |
in
|
| 68 |
(element, complex)
|
| 69 |
|
| 70 |
let integer_of_value_t = function
|
| 71 |
| Value.Integer i -> i
|
| 72 |
| _ -> assert false
|
| 73 |
|
| 74 |
let parse_facets base n =
|
| 75 |
debug_print ~n "Schema_parser.parse_facet";
|
| 76 |
let validate_base_type = Schema_validator.validate_simple_type base in
|
| 77 |
let validate_nonNegativeInteger =
|
| 78 |
Schema_builtin.validate_builtin
|
| 79 |
(Schema_xml.add_xsd_prefix (Utf8.mk "nonNegativeInteger"))
|
| 80 |
in
|
| 81 |
let facets = ref no_facets in
|
| 82 |
n#iter_nodes (fun n ->
|
| 83 |
let fixed =
|
| 84 |
(_has_attribute "fixed" n) && (_attribute "fixed" n = Utf8.mk "true")
|
| 85 |
in
|
| 86 |
match n#node_type with
|
| 87 |
| T_element "xsd:length" ->
|
| 88 |
let value = _attribute "value" n in
|
| 89 |
let length = integer_of_value_t (validate_nonNegativeInteger value) in
|
| 90 |
facets := { !facets with length = Some (length, fixed) }
|
| 91 |
| T_element "xsd:minLength" ->
|
| 92 |
let value = _attribute "value" n in
|
| 93 |
let length = integer_of_value_t (validate_nonNegativeInteger value) in
|
| 94 |
facets := { !facets with minLength = Some (length, fixed) }
|
| 95 |
| T_element "xsd:maxLength" ->
|
| 96 |
let value = _attribute "value" n in
|
| 97 |
let length = integer_of_value_t (validate_nonNegativeInteger value) in
|
| 98 |
facets := { !facets with maxLength = Some (length, fixed) }
|
| 99 |
| T_element "xsd:enumeration" ->
|
| 100 |
let value = Value.string_utf8 (_attribute "value" n) in
|
| 101 |
let value = validate_base_type value in
|
| 102 |
let new_enumeration =
|
| 103 |
(match !facets.enumeration with
|
| 104 |
| None -> Some (Value.ValueSet.singleton value)
|
| 105 |
| Some entries -> Some (Value.ValueSet.add value entries))
|
| 106 |
in
|
| 107 |
facets := { !facets with enumeration = new_enumeration }
|
| 108 |
| T_element "xsd:whiteSpace" ->
|
| 109 |
let value = Utf8.get_str (_attribute "value" n) in
|
| 110 |
facets := { !facets with whiteSpace =
|
| 111 |
((match value with
|
| 112 |
| "collapse" -> `Collapse
|
| 113 |
| "preserve" -> `Preserve
|
| 114 |
| "replace" -> `Replace
|
| 115 |
| _ -> assert false),
|
| 116 |
fixed) }
|
| 117 |
| T_element "xsd:maxInclusive" ->
|
| 118 |
let value = Value.string_utf8 (_attribute "value" n) in
|
| 119 |
facets := { !facets with
|
| 120 |
maxInclusive = Some (validate_base_type value, fixed) }
|
| 121 |
| T_element "xsd:maxExclusive" ->
|
| 122 |
let value = Value.string_utf8 (_attribute "value" n) in
|
| 123 |
facets := { !facets with
|
| 124 |
maxExclusive = Some (validate_base_type value, fixed) }
|
| 125 |
| T_element "xsd:minInclusive" ->
|
| 126 |
let value = Value.string_utf8 (_attribute "value" n) in
|
| 127 |
facets := { !facets with
|
| 128 |
minInclusive = Some (validate_base_type value, fixed) }
|
| 129 |
| T_element "xsd:minExclusive" ->
|
| 130 |
let value = Value.string_utf8 (_attribute "value" n) in
|
| 131 |
facets := { !facets with
|
| 132 |
minExclusive = Some (validate_base_type value, fixed) }
|
| 133 |
| _ -> ());
|
| 134 |
!facets
|
| 135 |
|
| 136 |
let merge_facets' base new_facets =
|
| 137 |
merge_facets (facets_of_simple_type_definition base) new_facets
|
| 138 |
|
| 139 |
(* parse an xsd:simpleType element *)
|
| 140 |
let rec parse_simple_type (resolver: resolver) n =
|
| 141 |
debug_print ~n "Schema_parser.parse_simple_type";
|
| 142 |
resolver#see n;
|
| 143 |
let name =
|
| 144 |
if _has_attribute "name" n then Some (_attribute "name" n) else None
|
| 145 |
in
|
| 146 |
if _has_element "xsd:restriction" n then begin (* restriction *)
|
| 147 |
let restriction = _element "xsd:restriction" n in
|
| 148 |
let base = find_base_simple_type resolver restriction in
|
| 149 |
let facets = parse_facets base restriction in
|
| 150 |
restrict base facets name
|
| 151 |
end else if _has_element "xsd:list" n then begin (* list *)
|
| 152 |
let list = _element "xsd:list" n in
|
| 153 |
let items = find_item_type resolver list in
|
| 154 |
Derived (name, List items, no_facets, anySimpleType)
|
| 155 |
end else begin (* union *)
|
| 156 |
let union = _element "xsd:union" n in
|
| 157 |
let members = find_member_types resolver union in
|
| 158 |
Derived (name, Union members, no_facets, anySimpleType)
|
| 159 |
end
|
| 160 |
|
| 161 |
(* look for a simple type def: try attribute "base", try "simpleType" child,
|
| 162 |
* fail *)
|
| 163 |
and find_base_simple_type (resolver: resolver) n =
|
| 164 |
if _has_attribute "base" n then
|
| 165 |
resolver#resolve_simple_typ (_attribute "base" n)
|
| 166 |
else if _has_element "xsd:simpleType" n then
|
| 167 |
parse_simple_type resolver (_element "xsd:simpleType" n)
|
| 168 |
else
|
| 169 |
raise (XSD_validation_error "no base simple type specified")
|
| 170 |
|
| 171 |
(* look for a simple type def: try attribute "itemType", try "simpleType"
|
| 172 |
* child, fail *)
|
| 173 |
and find_item_type (resolver: resolver) n =
|
| 174 |
if _has_attribute "itemType" n then
|
| 175 |
resolver#resolve_simple_typ (_attribute "itemType" n)
|
| 176 |
else if _has_element "xsd:simpleType" n then
|
| 177 |
parse_simple_type resolver (_element "xsd:simpleType" n)
|
| 178 |
else
|
| 179 |
raise (XSD_validation_error "no itemType specified")
|
| 180 |
|
| 181 |
(* look for a list of simple type defs: try attribute "memberTypes", try
|
| 182 |
* "simpleType" children, fail *)
|
| 183 |
and find_member_types (resolver: resolver) n =
|
| 184 |
let members1 =
|
| 185 |
if _has_attribute "memberTypes" n then
|
| 186 |
let names = split (_attribute "memberTypes" n) in
|
| 187 |
List.map resolver#resolve_simple_typ names
|
| 188 |
else
|
| 189 |
[]
|
| 190 |
in
|
| 191 |
let members2 =
|
| 192 |
let nodes = _elements "xsd:simpleType" n in
|
| 193 |
List.map (parse_simple_type resolver) nodes
|
| 194 |
in
|
| 195 |
(match members1 @ members2 with
|
| 196 |
| [] -> raise (XSD_validation_error "no member types specified")
|
| 197 |
| members -> members)
|
| 198 |
|
| 199 |
(* parse an attribute value constraint *)
|
| 200 |
let parse_att_value_constraint stype_def n =
|
| 201 |
debug_print ~n "Schema_parser.parse_att_value_constraint";
|
| 202 |
if _has_attribute "default" n then
|
| 203 |
let value = Value.string_utf8 (_attribute "default" n) in
|
| 204 |
let value = validate_simple_type stype_def value in
|
| 205 |
Some (`Default value)
|
| 206 |
else if _has_attribute "fixed" n then
|
| 207 |
let value = Value.string_utf8 (_attribute "fixed" n) in
|
| 208 |
let value = validate_simple_type stype_def value in
|
| 209 |
Some (`Fixed value)
|
| 210 |
else
|
| 211 |
None
|
| 212 |
|
| 213 |
(* parse an element value constraint *)
|
| 214 |
let parse_elt_value_constraint type_def n =
|
| 215 |
debug_print ~n "Schema_parser.parse_elt_value_constraint";
|
| 216 |
let validate_value =
|
| 217 |
match type_def with
|
| 218 |
| Simple st_def | Complex (_, _, _, _, _, CT_simple st_def) ->
|
| 219 |
validate_simple_type st_def
|
| 220 |
| _ -> validate_simple_type (Primitive (Utf8.mk "xsd:string"))
|
| 221 |
in
|
| 222 |
if _has_attribute "default" n then
|
| 223 |
let value = Value.string_utf8 (_attribute "default" n) in
|
| 224 |
let value = validate_value value in
|
| 225 |
Some (`Default value)
|
| 226 |
else if _has_attribute "fixed" n then
|
| 227 |
let value = Value.string_utf8 (_attribute "fixed" n) in
|
| 228 |
let value = validate_value value in
|
| 229 |
Some (`Fixed value)
|
| 230 |
else
|
| 231 |
None
|
| 232 |
|
| 233 |
(* look for a simple type def, try "simpleType" child, try "type" attribute,
|
| 234 |
* return anySimpleType *)
|
| 235 |
let find_simple_type (resolver: resolver) n =
|
| 236 |
if _has_element "xsd:simpleType" n then
|
| 237 |
parse_simple_type resolver (_element "xsd:simpleType" n)
|
| 238 |
else if _has_attribute "type" n then
|
| 239 |
resolver#resolve_simple_typ (_attribute "type" n)
|
| 240 |
else
|
| 241 |
anySimpleType
|
| 242 |
|
| 243 |
let parse_att_decl (resolver: resolver) n =
|
| 244 |
debug_print ~n "Schema_parser.parse_att_decl";
|
| 245 |
resolver#see n;
|
| 246 |
let name = _attribute "name" n in
|
| 247 |
let type_def = find_simple_type resolver n in
|
| 248 |
let value_constr = parse_att_value_constraint type_def n in
|
| 249 |
name, type_def, value_constr
|
| 250 |
|
| 251 |
let parse_attribute_use (resolver: resolver) n =
|
| 252 |
debug_print ~n "Schema_parser.parse_attribute_use";
|
| 253 |
let required =
|
| 254 |
(_has_attribute "use" n) && (_attribute "use" n = Utf8.mk "required")
|
| 255 |
in
|
| 256 |
let (name, type_def, value_constr) as att_decl =
|
| 257 |
if _has_attribute "ref" n then
|
| 258 |
resolver#resolve_att (_attribute "ref" n)
|
| 259 |
else
|
| 260 |
let (name, type_def, constr) = parse_att_decl resolver n in
|
| 261 |
(name, type_def, None) (* forget attribute value constraint *)
|
| 262 |
in
|
| 263 |
let value_constr = parse_att_value_constraint type_def n in
|
| 264 |
required, att_decl, value_constr
|
| 265 |
|
| 266 |
let parse_attribute_uses (resolver: resolver) derivation_type base n =
|
| 267 |
debug_print ~n "Schema_parser.parse_attribute_uses";
|
| 268 |
let uses1 = (* attribute uses from "attribute" children *)
|
| 269 |
List.map (parse_attribute_use resolver) (_elements "xsd:attribute" n)
|
| 270 |
in
|
| 271 |
let uses2 = (* attribute uses from "attributeGroup" children ref *)
|
| 272 |
List.concat (List.map
|
| 273 |
(fun att_group ->
|
| 274 |
if _has_attribute "ref" att_group then
|
| 275 |
snd (resolver#resolve_att_group (_attribute "ref" att_group))
|
| 276 |
else [])
|
| 277 |
(_elements "xsd:attributeGroup" n))
|
| 278 |
in
|
| 279 |
let uses3 = (* attribute uses from base type *)
|
| 280 |
match base with
|
| 281 |
| Complex (_, _, _, _, uses, _) ->
|
| 282 |
(match derivation_type with
|
| 283 |
| `Extension -> uses
|
| 284 |
| `Restriction ->
|
| 285 |
let ( &= ) u1 u2 = (* by name equality over attribute uses *)
|
| 286 |
(name_of_attribute_use u1 = name_of_attribute_use u2)
|
| 287 |
in
|
| 288 |
let defined_uses = uses1 @ uses2 in
|
| 289 |
List.filter
|
| 290 |
(fun use -> not (List.exists (fun u -> u &= use) defined_uses))
|
| 291 |
(* && not (List.mem name prohibited_uses1) *) (* TODO prohibited attribute uses *)
|
| 292 |
uses)
|
| 293 |
| _ -> []
|
| 294 |
in
|
| 295 |
uses1 @ uses2 @ uses3
|
| 296 |
|
| 297 |
let parse_min_max n =
|
| 298 |
((if _has_attribute "minOccurs" n then
|
| 299 |
Intervals.V.mk (Utf8.get_str (_attribute "minOccurs" n))
|
| 300 |
else
|
| 301 |
Intervals.V.one),
|
| 302 |
(if _has_attribute "maxOccurs" n then
|
| 303 |
match Utf8.get_str (_attribute "maxOccurs" n) with
|
| 304 |
| "unbounded" -> None
|
| 305 |
| s -> Some (Intervals.V.mk s)
|
| 306 |
else
|
| 307 |
Some Intervals.V.one))
|
| 308 |
|
| 309 |
let find_particles =
|
| 310 |
_elements' ["xsd:element"; "xsd:group"; "xsd:choice"; "xsd:sequence"]
|
| 311 |
|
| 312 |
let rec parse_complex_type (resolver: resolver) n =
|
| 313 |
let find_particle n =
|
| 314 |
try
|
| 315 |
Some (_element' ["xsd:all"; "xsd:choice"; "xsd:group"; "xsd:sequence"] n)
|
| 316 |
with Not_found -> None
|
| 317 |
in
|
| 318 |
debug_print ~n "Schema_parser.parse_complex_type";
|
| 319 |
resolver#see n;
|
| 320 |
let name =
|
| 321 |
if _has_attribute "name" n then Some (_attribute "name" n) else None
|
| 322 |
in
|
| 323 |
if _has_element "xsd:simpleContent" n then
|
| 324 |
let content = _element "xsd:simpleContent" n in
|
| 325 |
let derivation, derivation_type =
|
| 326 |
if _has_element "xsd:restriction" content then
|
| 327 |
(_element "xsd:restriction" content, `Restriction)
|
| 328 |
else (* _has_element "xsd:extension" *)
|
| 329 |
(_element "xsd:extension" content, `Extension)
|
| 330 |
in
|
| 331 |
let base = resolver#resolve_typ ~now:true (_attribute "base" derivation) in
|
| 332 |
let uses = parse_attribute_uses resolver derivation_type !base derivation in
|
| 333 |
let content_type =
|
| 334 |
match derivation_type with
|
| 335 |
| `Restriction ->
|
| 336 |
(match !base with
|
| 337 |
| Complex (_, _, _, _, _, (CT_simple base)) ->
|
| 338 |
let base =
|
| 339 |
if _has_element "xsd:simpleType" derivation then
|
| 340 |
parse_simple_type resolver
|
| 341 |
(_element "xsd:simpleType" derivation)
|
| 342 |
else
|
| 343 |
base
|
| 344 |
in
|
| 345 |
let new_facets = merge_facets' base (parse_facets base n) in
|
| 346 |
let restricted_simple_type_def =
|
| 347 |
(match base with
|
| 348 |
| Primitive name ->
|
| 349 |
Derived (None, variety_of_simple_type_definition base,
|
| 350 |
new_facets, base)
|
| 351 |
| Derived (_, variety, _, _) ->
|
| 352 |
Derived (None, variety, new_facets, base))
|
| 353 |
in
|
| 354 |
CT_simple restricted_simple_type_def
|
| 355 |
| _ -> assert false)
|
| 356 |
| `Extension ->
|
| 357 |
(match !base with
|
| 358 |
| Complex (_, _, _, _, _, (CT_simple base)) -> CT_simple base
|
| 359 |
| Simple simple_type_def -> CT_simple simple_type_def
|
| 360 |
| _ -> assert false)
|
| 361 |
in
|
| 362 |
complex name !base derivation_type uses content_type
|
| 363 |
else if _has_element "xsd:complexContent" n then
|
| 364 |
let content = _element "xsd:complexContent" n in
|
| 365 |
let derivation, derivation_type =
|
| 366 |
if _has_element "xsd:restriction" content then
|
| 367 |
(_element "xsd:restriction" content, `Restriction)
|
| 368 |
else (* _has_element "xsd:extension" *)
|
| 369 |
(_element "xsd:extension" content, `Extension)
|
| 370 |
in
|
| 371 |
let base = resolver#resolve_typ ~now:true (_attribute "base" derivation) in
|
| 372 |
let uses = parse_attribute_uses resolver derivation_type !base derivation in
|
| 373 |
let mixed =
|
| 374 |
(_has_attribute "mixed" content &&
|
| 375 |
(_attribute "mixed" content = Utf8.mk "true"))
|
| 376 |
|| (_has_attribute "mixed" n && (_attribute "mixed" n = Utf8.mk "true"))
|
| 377 |
in
|
| 378 |
let particle_node = find_particle derivation in
|
| 379 |
let content_type =
|
| 380 |
match derivation_type with
|
| 381 |
| `Restriction ->
|
| 382 |
(match particle_node with
|
| 383 |
| None -> CT_empty
|
| 384 |
| Some p_node ->
|
| 385 |
let particle = parse_particle resolver p_node in
|
| 386 |
CT_model (particle, mixed))
|
| 387 |
| `Extension ->
|
| 388 |
let base_ct = content_type_of_type !base in (* TODO BUG HERE if base =
|
| 389 |
AnyType *)
|
| 390 |
(match particle_node with
|
| 391 |
| None -> base_ct
|
| 392 |
| Some pnode ->
|
| 393 |
let particle = parse_particle resolver pnode in
|
| 394 |
(match base_ct with
|
| 395 |
| CT_empty -> CT_model (particle, mixed)
|
| 396 |
| CT_model (p, _) ->
|
| 397 |
let model = Sequence (p::[particle]) in
|
| 398 |
CT_model
|
| 399 |
((Intervals.V.one, Some (Intervals.V.one), Model model,
|
| 400 |
first_of_model_group model),
|
| 401 |
mixed)
|
| 402 |
| CT_simple _ -> assert false))
|
| 403 |
in
|
| 404 |
complex name !base derivation_type uses content_type
|
| 405 |
else (* neither simpleContent nor complexContent *)
|
| 406 |
let base = anyType in
|
| 407 |
let uses = parse_attribute_uses resolver `Restriction base n in
|
| 408 |
let mixed =
|
| 409 |
_has_attribute "mixed" n && (_attribute "mixed" n = Utf8.mk "true")
|
| 410 |
in
|
| 411 |
let content_type =
|
| 412 |
match find_particle n with
|
| 413 |
| None -> CT_empty
|
| 414 |
| Some pnode ->
|
| 415 |
let particle = parse_particle resolver pnode in
|
| 416 |
CT_model (particle, mixed)
|
| 417 |
in
|
| 418 |
complex name anyType `Restriction uses content_type
|
| 419 |
|
| 420 |
and parse_elt_decl (resolver: resolver) n: element_declaration =
|
| 421 |
debug_print ~n "Schema_parser.parse_elt_decl";
|
| 422 |
resolver#see n;
|
| 423 |
if not (_has_attribute "name" n) then
|
| 424 |
raise (XSD_validation_error "missing element name");
|
| 425 |
let name = _attribute "name" n in
|
| 426 |
let type_def = find_element_type resolver n in
|
| 427 |
let value_constr = parse_elt_value_constraint type_def n in
|
| 428 |
element name (ref type_def) value_constr
|
| 429 |
|
| 430 |
(* look for a type definition, try "simpleType" child, try "complexType"
|
| 431 |
* child, try "type" attribute, return anyType *)
|
| 432 |
and find_element_type (resolver: resolver) n =
|
| 433 |
if _has_element "xsd:simpleType" n then
|
| 434 |
Simple (parse_simple_type resolver (_element "xsd:simpleType" n))
|
| 435 |
else if _has_element "xsd:complexType" n then
|
| 436 |
Complex (parse_complex_type resolver (_element "xsd:complexType" n))
|
| 437 |
else if _has_attribute "type" n then
|
| 438 |
!(resolver#resolve_typ ~now:true (_attribute "type" n))
|
| 439 |
else
|
| 440 |
anyType
|
| 441 |
|
| 442 |
and parse_particle (resolver: resolver) n =
|
| 443 |
debug_print ~n "Schema_parser.parse_particle";
|
| 444 |
let min, max = parse_min_max n in
|
| 445 |
match n#node_type with
|
| 446 |
| T_element "xsd:element" ->
|
| 447 |
let elt_decl, first =
|
| 448 |
if _has_attribute "ref" n then
|
| 449 |
let ref = _attribute "ref" n in
|
| 450 |
(resolver#resolve_elt ~now:false ref, [ Some ref ])
|
| 451 |
else (* no "ref" attribute *)
|
| 452 |
let decl = parse_elt_decl resolver n in
|
| 453 |
(ref decl, [ Some (name_of_element_declaration decl) ])
|
| 454 |
in
|
| 455 |
(min, max, Elt elt_decl, first)
|
| 456 |
| T_element "xsd:group" ->
|
| 457 |
let model_group =
|
| 458 |
snd (resolver#resolve_model_group (_attribute "ref" n))
|
| 459 |
in
|
| 460 |
(min, max, Model model_group, first_of_model_group model_group)
|
| 461 |
| T_element "xsd:all" | T_element "xsd:sequence" | T_element "xsd:choice" ->
|
| 462 |
let model_group = parse_model_group resolver n in
|
| 463 |
(min, max, Model model_group, first_of_model_group model_group)
|
| 464 |
| _ -> assert false
|
| 465 |
|
| 466 |
and parse_model_group (resolver: resolver) n =
|
| 467 |
debug_print ~n "Schema_parser.parse_model_group";
|
| 468 |
match n#node_type with
|
| 469 |
| T_element "xsd:all" ->
|
| 470 |
All (List.map (parse_particle resolver) (_elements "xsd:element" n))
|
| 471 |
| T_element "xsd:sequence" ->
|
| 472 |
Sequence (List.map (parse_particle resolver) (find_particles n))
|
| 473 |
| T_element "xsd:choice" ->
|
| 474 |
Choice (List.map (parse_particle resolver) (find_particles n))
|
| 475 |
| _ -> assert false
|
| 476 |
|
| 477 |
and parse_att_group (resolver: resolver) n =
|
| 478 |
debug_print ~n "Schema_parser.parse_att_group";
|
| 479 |
resolver#see n;
|
| 480 |
let name = _attribute "name" n in
|
| 481 |
let uses1 =
|
| 482 |
List.map (parse_attribute_use resolver) (_elements "xsd:attribute" n)
|
| 483 |
in
|
| 484 |
let uses2 =
|
| 485 |
List.concat (List.map (fun name -> snd (resolver#resolve_att_group name))
|
| 486 |
(List.map (_attribute "ref") (_elements "xsd:attributeGroup" n)))
|
| 487 |
in
|
| 488 |
name, (uses1 @ uses2)
|
| 489 |
|
| 490 |
let parse_model_group_def (resolver: resolver) n =
|
| 491 |
debug_print ~n "Schema_parser.parse_model_group_def";
|
| 492 |
resolver#see n;
|
| 493 |
let name = _attribute "name" n in
|
| 494 |
let model_group_node =
|
| 495 |
_element' ["xsd:all"; "xsd:choice"; "xsd:sequence"] n
|
| 496 |
in
|
| 497 |
let model_group = parse_model_group resolver model_group_node in
|
| 498 |
name, model_group
|
| 499 |
|
| 500 |
(** @param root schema document root node *)
|
| 501 |
class lazy_resolver =
|
| 502 |
let fake_type_def =
|
| 503 |
Complex (~-1, Some (Utf8.mk " FAKE TYP "), AnyType, `Restriction, [],
|
| 504 |
CT_empty)
|
| 505 |
in
|
| 506 |
let fake_elt_decl = ~-2, Utf8.mk " FAKE ELT ", ref fake_type_def, None in
|
| 507 |
let is_fake_type_def = (==) fake_type_def in
|
| 508 |
let is_fake_elt_decl = (==) fake_elt_decl in
|
| 509 |
let validation_error s = raise (XSD_validation_error s) in
|
| 510 |
let get_ns_prefix n =
|
| 511 |
match n#node_type with T_namespace p -> p | _ -> assert false
|
| 512 |
in
|
| 513 |
let (^^) x y = Utf8.concat x y in
|
| 514 |
fun root ->
|
| 515 |
object (self)
|
| 516 |
|
| 517 |
val typs: (Utf8.t, type_definition ref) Hashtbl.t =
|
| 518 |
Hashtbl.create 17
|
| 519 |
val attrs: (Utf8.t, attribute_declaration) Hashtbl.t =
|
| 520 |
Hashtbl.create 17
|
| 521 |
val elts: (Utf8.t, element_declaration ref) Hashtbl.t =
|
| 522 |
Hashtbl.create 17
|
| 523 |
val attr_groups: (Utf8.t, attribute_group_definition) Hashtbl.t =
|
| 524 |
Hashtbl.create 17
|
| 525 |
val model_groups: (Utf8.t, model_group_definition) Hashtbl.t =
|
| 526 |
Hashtbl.create 17
|
| 527 |
|
| 528 |
val mutable seen_nodes = NodeSet.empty
|
| 529 |
|
| 530 |
val mutable targetNamespace = None
|
| 531 |
val mutable targetNamespace_prefix = "0TARGET0"
|
| 532 |
val namespace_manager = new Pxp_dtd.namespace_manager
|
| 533 |
val orig_ns_prefixes = Hashtbl.create 17
|
| 534 |
|
| 535 |
initializer
|
| 536 |
Schema_builtin.iter_builtin (* register built-in types *)
|
| 537 |
(fun st_def ->
|
| 538 |
let type_def = Simple st_def in
|
| 539 |
let name = name_of_type_definition type_def in
|
| 540 |
Hashtbl.replace typs name (ref type_def));
|
| 541 |
Hashtbl.replace typs (Utf8.mk "xsd:anyType") (ref AnyType);
|
| 542 |
List.iter (* fill namespace manager *)
|
| 543 |
(fun (p, ns) ->
|
| 544 |
namespace_manager#add_namespace (Utf8.get_str p) (Utf8.get_str ns))
|
| 545 |
Schema_xml.schema_ns_prefixes;
|
| 546 |
List.iter
|
| 547 |
(fun n ->
|
| 548 |
let prefix = get_ns_prefix n in
|
| 549 |
let uri = n#data in
|
| 550 |
if prefix <> "" then begin
|
| 551 |
Hashtbl.add orig_ns_prefixes prefix uri;
|
| 552 |
ignore (namespace_manager#lookup_or_add_namespace prefix uri)
|
| 553 |
end)
|
| 554 |
root#namespace_info#declaration;
|
| 555 |
if _has_attribute "targetNamespace" root then begin
|
| 556 |
let ns = _attribute "targetNamespace" root in
|
| 557 |
targetNamespace <- Some ns;
|
| 558 |
targetNamespace_prefix <-
|
| 559 |
namespace_manager#lookup_or_add_namespace
|
| 560 |
targetNamespace_prefix (Utf8.get_str ns)
|
| 561 |
end;
|
| 562 |
|
| 563 |
(** schemas namespaces handling *)
|
| 564 |
|
| 565 |
method targetNamespace =
|
| 566 |
match targetNamespace with
|
| 567 |
| None -> Ns.empty
|
| 568 |
| Some s -> Ns.mk s
|
| 569 |
|
| 570 |
(* qualify names of entities before registering them with defined
|
| 571 |
* targetNamespace, if any *)
|
| 572 |
method private qualify_name name =
|
| 573 |
match targetNamespace with
|
| 574 |
| None -> name
|
| 575 |
| Some _ -> (Utf8.mk (targetNamespace_prefix ^ ":")) ^^ name
|
| 576 |
|
| 577 |
(* resolve user references using our namespace manager *)
|
| 578 |
method private fix_namespace s =
|
| 579 |
match Ns.split_qname s with
|
| 580 |
| "", base ->
|
| 581 |
(match targetNamespace with
|
| 582 |
| None -> base
|
| 583 |
| Some _ -> (Utf8.mk targetNamespace_prefix) ^^ (Utf8.mk ":") ^^ base)
|
| 584 |
| prefix, base ->
|
| 585 |
(try
|
| 586 |
let orig_uri = Hashtbl.find orig_ns_prefixes prefix in
|
| 587 |
let new_prefix = namespace_manager#get_normprefix orig_uri in
|
| 588 |
(Utf8.mk new_prefix) ^^ (Utf8.mk ":") ^^ base
|
| 589 |
with Not_found ->
|
| 590 |
validation_error ("Can't resolve: " ^ Utf8.get_str s))
|
| 591 |
|
| 592 |
(** seen nodes accounting *)
|
| 593 |
|
| 594 |
method already_seen n = NodeSet.mem n seen_nodes
|
| 595 |
method see (n: pxp_node) =
|
| 596 |
debug_print "lazy_resolver.see";
|
| 597 |
if NodeSet.mem n seen_nodes then
|
| 598 |
validation_error "Types/Elements loop";
|
| 599 |
seen_nodes <- NodeSet.add n seen_nodes
|
| 600 |
|
| 601 |
method private find_global_component tag_pred name =
|
| 602 |
let basename = snd (Ns.split_qname name) in
|
| 603 |
find (fun n -> match n#node_type with
|
| 604 |
| T_element tag when tag_pred tag ->
|
| 605 |
(_has_attribute "name" n) && (_attribute "name" n = basename)
|
| 606 |
| _ -> false) root
|
| 607 |
|
| 608 |
(** registration of global entities *)
|
| 609 |
|
| 610 |
method register_typ name def =
|
| 611 |
debug_print "lazy_resolver.register_typ";
|
| 612 |
let name = self#qualify_name name in
|
| 613 |
if (Hashtbl.mem typs name) &&
|
| 614 |
(not (is_fake_type_def !(Hashtbl.find typs name))) then
|
| 615 |
validation_error ("Redefinition of type: " ^ Utf8.get_str name);
|
| 616 |
debug_print (sprintf "Osv_parser: registering TYPE %s"
|
| 617 |
(Utf8.get_str name));
|
| 618 |
let type_def_ref = self#resolve_typ ~fix_ns:false ~now:false name in
|
| 619 |
type_def_ref := def
|
| 620 |
|
| 621 |
method register_elt name decl =
|
| 622 |
debug_print "lazy_resolver.register_elt";
|
| 623 |
let name = self#qualify_name name in
|
| 624 |
if (Hashtbl.mem elts name) &&
|
| 625 |
(not (is_fake_elt_decl !(Hashtbl.find elts name))) then
|
| 626 |
validation_error ("Redefinition of element: " ^ Utf8.get_str name);
|
| 627 |
debug_print (sprintf "Osv_parser: registering ELEMENT %s"
|
| 628 |
(Utf8.get_str name));
|
| 629 |
let elt_decl_ref = self#resolve_elt ~fix_ns:false ~now:false name in
|
| 630 |
elt_decl_ref := decl
|
| 631 |
|
| 632 |
method register_att name decl =
|
| 633 |
debug_print "lazy_resolver.register_att";
|
| 634 |
let name = self#qualify_name name in
|
| 635 |
if Hashtbl.mem attrs name then
|
| 636 |
validation_error ("Redefinition of attribute: " ^ Utf8.get_str name);
|
| 637 |
debug_print (sprintf "Osv_parser: registering ATTRIBUTE %s"
|
| 638 |
(Utf8.get_str name));
|
| 639 |
Hashtbl.replace attrs name decl
|
| 640 |
|
| 641 |
method register_att_group name def =
|
| 642 |
debug_print "lazy_resolver.register_att_group";
|
| 643 |
let name = self#qualify_name name in
|
| 644 |
if Hashtbl.mem attr_groups name then
|
| 645 |
validation_error ("Redefinition of attribute group: " ^
|
| 646 |
Utf8.get_str name);
|
| 647 |
debug_print (sprintf "Osv_parser: registering ATTRIBUTE GROUP %s"
|
| 648 |
(Utf8.get_str name));
|
| 649 |
Hashtbl.replace attr_groups name def
|
| 650 |
|
| 651 |
method register_model_group name def =
|
| 652 |
debug_print "lazy_resolver.register_model_group";
|
| 653 |
let name = self#qualify_name name in
|
| 654 |
if Hashtbl.mem model_groups name then
|
| 655 |
validation_error ("Redefinition of model group: " ^ Utf8.get_str name);
|
| 656 |
debug_print (sprintf "Osv_parser: registering MODEL GROUP %s"
|
| 657 |
(Utf8.get_str name));
|
| 658 |
Hashtbl.replace model_groups name def
|
| 659 |
|
| 660 |
(** entities lookup *)
|
| 661 |
|
| 662 |
method resolve_typ ?(fix_ns = true) ~now name =
|
| 663 |
debug_print "lazy_resolver.resolve_typ";
|
| 664 |
let name = if fix_ns then self#fix_namespace name else name in
|
| 665 |
try
|
| 666 |
Hashtbl.find typs name
|
| 667 |
with Not_found ->
|
| 668 |
let type_def =
|
| 669 |
if now then (* resolve now: look for global type definitions *)
|
| 670 |
let type_node =
|
| 671 |
try
|
| 672 |
self#find_global_component
|
| 673 |
(fun tag ->
|
| 674 |
(tag = "xsd:simpleType") || (tag = "xsd:complexType"))
|
| 675 |
name
|
| 676 |
with Not_found ->
|
| 677 |
validation_error ("Can't find definition of type: " ^
|
| 678 |
Utf8.get_str name)
|
| 679 |
in
|
| 680 |
if _tag_name type_node = Utf8.mk "xsd:simpleType" then
|
| 681 |
Simple (parse_simple_type (self :> resolver) type_node)
|
| 682 |
else (* _tag_name type_node = "xsd:complexType" *)
|
| 683 |
Complex (parse_complex_type (self :> resolver) type_node)
|
| 684 |
else (* resolve later: return a fake type ref *)
|
| 685 |
fake_type_def
|
| 686 |
in
|
| 687 |
let type_def_ref = ref type_def in
|
| 688 |
Hashtbl.replace typs name type_def_ref;
|
| 689 |
type_def_ref
|
| 690 |
|
| 691 |
method resolve_simple_typ ?(fix_ns = true) name =
|
| 692 |
match !(self#resolve_typ ~fix_ns ~now:true name) with
|
| 693 |
| AnyType -> Primitive (Utf8.mk "xsd:anySimpleType")
|
| 694 |
| Simple st -> st
|
| 695 |
| Complex _ -> assert false
|
| 696 |
|
| 697 |
method resolve_elt ?(fix_ns = true) ~now name =
|
| 698 |
debug_print "lazy_resolver.resolve_elt";
|
| 699 |
let name = if fix_ns then self#fix_namespace name else name in
|
| 700 |
try
|
| 701 |
Hashtbl.find elts name
|
| 702 |
with Not_found ->
|
| 703 |
let elt_decl =
|
| 704 |
if now then (* resolve now: look for global element declarations *)
|
| 705 |
let elt_node =
|
| 706 |
try
|
| 707 |
self#find_global_component ((=) "xsd:element") name
|
| 708 |
with Not_found ->
|
| 709 |
validation_error ("Can't find declaration of element: " ^
|
| 710 |
Utf8.get_str name)
|
| 711 |
in
|
| 712 |
parse_elt_decl (self :> resolver) elt_node
|
| 713 |
else (* resolve later: return a fake element declaration *)
|
| 714 |
fake_elt_decl
|
| 715 |
in
|
| 716 |
let elt_decl_ref = ref elt_decl in
|
| 717 |
Hashtbl.replace elts name elt_decl_ref;
|
| 718 |
elt_decl_ref
|
| 719 |
|
| 720 |
method resolve_att ?(fix_ns = true) name =
|
| 721 |
debug_print "lazy_resolver.resolve_att";
|
| 722 |
let name = if fix_ns then self#fix_namespace name else name in
|
| 723 |
try
|
| 724 |
Hashtbl.find attrs name
|
| 725 |
with Not_found ->
|
| 726 |
let node =
|
| 727 |
try
|
| 728 |
self#find_global_component ((=) "xsd:attribute") name
|
| 729 |
with Not_found ->
|
| 730 |
validation_error ("Can't find declaration of attribute: " ^
|
| 731 |
Utf8.get_str name)
|
| 732 |
in
|
| 733 |
let att_decl = parse_att_decl (self :> resolver) node in
|
| 734 |
Hashtbl.replace attrs name att_decl;
|
| 735 |
att_decl
|
| 736 |
|
| 737 |
method resolve_att_group ?(fix_ns = true) name =
|
| 738 |
debug_print "lazy_resolver.resolve_att_group";
|
| 739 |
let name = if fix_ns then self#fix_namespace name else name in
|
| 740 |
try
|
| 741 |
Hashtbl.find attr_groups name
|
| 742 |
with Not_found ->
|
| 743 |
let node =
|
| 744 |
try
|
| 745 |
self#find_global_component ((=) "xsd:attributeGroup") name
|
| 746 |
with Not_found ->
|
| 747 |
validation_error
|
| 748 |
("Can't find definition of attribute group: " ^ Utf8.get_str name)
|
| 749 |
in
|
| 750 |
let att_group_decl = parse_att_group (self :> resolver) node in
|
| 751 |
Hashtbl.replace attr_groups name att_group_decl;
|
| 752 |
att_group_decl
|
| 753 |
|
| 754 |
method resolve_model_group ?(fix_ns = true) name =
|
| 755 |
debug_print "lazy_resolver.resolve_model_group";
|
| 756 |
let name = if fix_ns then self#fix_namespace name else name in
|
| 757 |
try
|
| 758 |
Hashtbl.find model_groups name
|
| 759 |
with Not_found ->
|
| 760 |
let node =
|
| 761 |
try
|
| 762 |
self#find_global_component ((=) "xsd:group") name
|
| 763 |
with Not_found ->
|
| 764 |
validation_error
|
| 765 |
("Can't find definition of model group: " ^ Utf8.get_str name)
|
| 766 |
in
|
| 767 |
let model_group = parse_model_group_def (self :> resolver) node in
|
| 768 |
Hashtbl.replace model_groups name model_group;
|
| 769 |
model_group
|
| 770 |
|
| 771 |
(** acces to registered global entities *)
|
| 772 |
|
| 773 |
method elt_decls = hashtbl_values (hashtbl_deref elts)
|
| 774 |
method type_defs = hashtbl_values (hashtbl_deref typs)
|
| 775 |
method att_decls = hashtbl_values attrs
|
| 776 |
method att_groups = hashtbl_values attr_groups
|
| 777 |
method model_groups = hashtbl_values model_groups
|
| 778 |
|
| 779 |
end
|
| 780 |
|
| 781 |
(** {2 module's interface implementation} *)
|
| 782 |
|
| 783 |
let schema_of_node root =
|
| 784 |
let resolver = new lazy_resolver root in
|
| 785 |
let resolver' = (resolver :> resolver) in
|
| 786 |
root#iter_nodes (fun n ->
|
| 787 |
if not (resolver#already_seen n) then
|
| 788 |
match n#node_type with
|
| 789 |
| T_element "xsd:element" ->
|
| 790 |
let name = _attribute "name" n in
|
| 791 |
resolver#register_elt name (parse_elt_decl resolver' n)
|
| 792 |
| T_element "xsd:simpleType" ->
|
| 793 |
let name = _attribute "name" n in
|
| 794 |
resolver#register_typ name (Simple (parse_simple_type resolver' n))
|
| 795 |
| T_element "xsd:complexType" ->
|
| 796 |
let name = _attribute "name" n in
|
| 797 |
resolver#register_typ name (Complex (parse_complex_type resolver' n))
|
| 798 |
| T_element "xsd:attribute" ->
|
| 799 |
let name = _attribute "name" n in
|
| 800 |
resolver#register_att name (parse_att_decl resolver' n)
|
| 801 |
| T_element "xsd:attributeGroup" ->
|
| 802 |
let name = _attribute "name" n in
|
| 803 |
resolver#register_att_group name (parse_att_group resolver' n)
|
| 804 |
| T_element "xsd:group" ->
|
| 805 |
let name = _attribute "name" n in
|
| 806 |
resolver#register_model_group name (parse_model_group_def resolver' n)
|
| 807 |
| _ -> ());
|
| 808 |
{
|
| 809 |
targetNamespace = resolver#targetNamespace;
|
| 810 |
types = resolver#type_defs;
|
| 811 |
attributes = resolver#att_decls;
|
| 812 |
elements = resolver#elt_decls;
|
| 813 |
attribute_groups = resolver#att_groups;
|
| 814 |
model_groups = resolver#model_groups
|
| 815 |
}
|
| 816 |
|
| 817 |
let parse_schema source =
|
| 818 |
let config =
|
| 819 |
{ new_xsd_config () with Pxp_types.enable_namespace_info = true }
|
| 820 |
in
|
| 821 |
let schema = schema_of_node (pxp_node_of ~config source) in
|
| 822 |
debug_print "parse_schema completed successfully";
|
| 823 |
schema
|
| 824 |
|
| 825 |
let schema_of_file fname = parse_schema (Pxp_types.from_file fname)
|
| 826 |
|
| 827 |
let schema_of_string s = parse_schema (Pxp_types.from_string s)
|
| 828 |
|
| 829 |
|