📄 xmerl_xsd.erl
字号:
save_schema_element(CM,S3), S3 end.validate_schema_ph2(S=#xsd_state{derived_types=[]}) -> S;validate_schema_ph2(S=#xsd_state{derived_types=DT}) -> deduce_derived_types(DT,S). %% traverse_content/2 creates the content model of the schema.%% content model depends on (1) the type: %% complex type:%% sequence, choice, all%% simple type: no content other than characters%% (2) minOccurs/maxOccurs attributes.%% The schema for schemas content model is:%% schema: ((include | import | redefine | annotation)*, %% (((simpleType | complexType | group | attributeGroup)%% | element | attribute | notation), annotation*)*)%% attribute: (annotation?, simpleType?)%% element: (annotation?, ((simpleType | complexType)?, (unique |%% key | keyref)*))%% complexType: (annotation?, (simpleContent | complexContent |%% ((group | all | choice | sequence)?,%% ((attribute | attributeGroup)*,anyAttribute?))))%% attributeGroup:(annotation?,%% ((attribute | attributeGroup)*, anyAttribute?))%% group: (annotation?, (all | choice | sequence)?)%% all: (annotation?, element*)%% sequence: (annotation?,%% (element | group | choice | sequence | any)*)%% choice: (annotation?, (element | group | choice | sequence |%% any)*)%% any: (annotation?) any wellformed xml inside "any"%% unique: (annotation?, (selector, field+))%% key: (annotation?, (selector, field+))%% keyref: (annotation?, (selector, field+))%% selector: (annotation?)%% field: (annotation?)%% notation: (annotation?)%% annotation: (appinfo | documentation)*%% appinfo: ({any})*%% documentation: ({any})*%% simpleType: (annotation?, (restriction | list | union))%% restriction: (annotation?, (simpleType?, (minExclusive | %% minInclusive | maxExclusive | maxInclusive | %% totalDigits | fractionDigits | length | minLength | %% maxLength | enumeration | whiteSpace | pattern)*))%% list: (annotation?, simpleType?)%% union: (annotation?, simpleType*)%% include: (annotation?)%% import: (annotation?)%% redefine: (annotation | (simpleType | complexType | group |%% attributeGroup))*traverse_content(E=#xmlElement{name=Name},S) -> case local_name(Name) of schema -> Content = E#xmlElement.content,%% S1 = S#xsd_state{targetNamespace=target_namespace(E)}, ThisNS = {"#this#",S#xsd_state.schema_name, S#xsd_state.targetNamespace}, S2 = S#xsd_state{checked_namespace_nodes= add_once(ThisNS,S#xsd_state.checked_namespace_nodes)}, S3 = namespace_nodes(E,S2), S4 = element_form_default(E,S3), S5 = attribute_form_default(E,S4), S6 = substitution_default(finalDefault,E,S5), S7 = substitution_default(blockDefault,E,S6), traverse_content2(Content,S7,[]); Err -> exit({error,{[],?MODULE,{schema_error,Err}}}) end. traverse_content2([],S,Acc) -> {reverse(remove_annotation(Acc)),reset_scope(S)};traverse_content2([El|Els],S,Acc) when is_record(El,xmlElement) -> %% element declaration: save name, type, scope. {Object,S2} = element_content(kind(El,S),El,S#xsd_state.scope),%% Object={Kind,Obj} traverse_content2(Els,S2,[Object|Acc]);traverse_content2([_T|Els],S,Acc) -> %% xmlText,xmlPI ... traverse_content2(Els,S,Acc).target_namespace(E) -> case get_attribute_value(targetNamespace,E,undefined) of URI when is_list(URI) -> list_to_atom(URI); URI -> URI end.%% namespace_nodes/2 ->%% NS.namespace_nodes(#xmlElement{namespace=#xmlNamespace{nodes=NS}}, S=#xsd_state{namespace_nodes=NSN, global_namespace_nodes=GNSN}) -> S2 =S#xsd_state{namespace_nodes=foldl(fun add_once/2,NSN,NS)}, S2#xsd_state{global_namespace_nodes= add_key_once(S#xsd_state.targetNamespace,1, {S#xsd_state.targetNamespace,NS}, GNSN)}.attribute_form_default(#xmlElement{attributes=Atts},S)-> Def=form_default(attributeFormDefault,Atts,S), S#xsd_state{attributeFormDefault=Def}.element_form_default(#xmlElement{attributes=Atts},S) -> Def=form_default(elementFormDefault,Atts,S), S#xsd_state{elementFormDefault=Def}.form_default(Key,Atts,_S) -> case keyNsearch(Key,#xmlAttribute.name,Atts,unqualified) of #xmlAttribute{value=V} when is_list(V) -> list_to_atom(V); #xmlAttribute{value=V} ->V; _-> unqualified end.substitution_default(Subst = finalDefault,El,S) -> S#xsd_state{finalDefault = substitution(Subst,El,S)};substitution_default(Subst = blockDefault,El,S) -> S#xsd_state{blockDefault = substitution(Subst,El,S)}.substitution(Subst,El,_S) -> split_by_whitespace(get_attribute_value(Subst,El,[]),[]). %% element_content may be one of: annotation, type def(simple or%% complex), import, unique, key, keyref, attribute def, attribute%% group, all, group, complexContent, simpleContent, choice, sequenceelement_content({attribute,S=#xsd_state{scope=Scope}},Att,Env) -> case qualify_NCName(Att,S) of no_name -> Ref = attribute_ref(Att), AttRef = {attribute,get_QName(Ref,Att#xmlElement.namespace, %%QQQ reset_scope(S))}, {AttRef,add_ref(S,AttRef)}; Name -> {AttrType,S2} = attribute_type(Att,[Name|Env],S), S3 = check_cm(attribute,allowed_content(attribute,Env),AttrType,S2), {Attr,S4} = attribute_properties(Att#xmlElement.attributes, #schema_attribute{type=AttrType},S3), Object = {attribute, Attr#schema_attribute{name=Name,scope=Scope}}, S5 = save_object(Object,S4), {{attribute,Name},S5} end;element_content({element,S},El,Env) -> %% The type of an element may be a simple or complex type (named %% or anonymous), a referenced name or member of a substitution group. case qualify_NCName(El,S) of no_name -> Ref = particle_ref(El), {Occ,S2} = occurance(El,{1,1},S), %% 3.3.3 bullet 2.2 S3 = element_forbidden_properties(El,S2), S4 = element_forbidden_content(El#xmlElement.content,S3), ElRef = {element, {get_QName(Ref,El#xmlElement.namespace,reset_scope(S)), Occ}}, {ElRef,add_ref(S4,ElRef)}; Name -> {Type,S2} = element_type(El,[Name|Env],S), S3 = check_cm(element,allowed_content(element,Env),Type,S2), Type2 = remove_annotation(Type), Unique = [X||X={unique,_} <- Type2], Key = [X||X={K,_} <- Type2,K == key orelse K==keyref], {Occur,S4} = occurance(El,{1,1},S3), {SE,S5} = element_properties(El#xmlElement.attributes, #schema_element{},El,S4), CM = remove_attributes([X||X={Y,_}<-Type2, unique=/=Y,key=/=Y, keyref=/=Y,annotation=/=Y]), %% take care of key/keyref later SE2 = SE#schema_element{name=Name,type=CM,uniqueness=Unique, key=Key, occurance=Occur, scope=S5#xsd_state.scope}, S6 = insert_substitutionGroup(SE2,S5), S7 = save_object({element,SE2},S6), {{element,{Name,Occur}},S7} end;element_content({complexType,S},CT,Env) -> %% complex type definition without a name is returnd and added to %% the content model at this level. A complex type may also contain %% attributes or attribute group references in the end of its content. %%?debug("complexType content: ~p~nenv: ~p~n",[CT,Env]), {SCT,S1} = c_t_properties(CT,#schema_complex_type{},S), {Mixed,S2} = mixed(CT,S1), Complexity = complexity(CT#xmlElement.content), {Object,Name,S7} = case qualify_NCName(CT,S2) of no_name -> {CM,S3} = type(CT#xmlElement.content, in_scope(anonymous,S2),[complexType|Env]), S4 = check_cm(complexType,allowed_content(complexType,Env),CM,S3), Name1 = get_QName('_xmerl_no_name_',CT#xmlElement.namespace,S4), S5 = set_scope(S#xsd_state.scope,S4), {Content,Attributes}=split_content(remove_annotation(CM)), SCT2 = base_type(Content,SCT), CTObj = {complexType, SCT2#schema_complex_type{name=Name1, scope=S5#xsd_state.scope, attributes=Attributes, complexity=Complexity, content=mixify(Mixed,Content)}}, {CTObj,Name1,S5}; Name2 -> S3 = in_scope(Name2,S2), S3a = push_circularity_mark({typeDef,Name2},S3), {CM,S4} = type(CT#xmlElement.content,S3a, [complexType|Env]), S4a = pop_circularity_mark({typeDef,Name2},S4), S5 = check_cm(complexType,allowed_content(complexType,Env), CM,S4a), S6 = set_scope(S#xsd_state.scope,S5), {Content,Attributes}=split_content(remove_annotation(CM)), SCT2 = base_type(Content,SCT), {{complexType, SCT2#schema_complex_type{name=Name2, scope=S6#xsd_state.scope, attributes=Attributes, complexity=Complexity, content=mixify(Mixed,Content)}}, Name2,S6} end, S8 = save_object(Object,S7), S9 = derived_type(Object,S8), {{complexType,Name},S9};element_content({attributeGroup,S},AG,Env) -> %% an attribute group always have a name or a ref, the content is %% (annotation?,(attribute | attributGroup)*, anyAttribute?). case qualify_NCName(AG,S) of no_name -> %% an attribute group ref inside complex type def or attr %% group def ( XSD1:3.6.2). Ref = attributeGroup_ref(AG), AGRef = {attributeGroup,get_QName(Ref,AG#xmlElement.namespace,%%QQQ reset_scope(S))}, {AGRef,add_ref(S,AGRef)}; Name -> %% must occur on top level of schema( XSD1:3.6.2). The %% only thing needed in content are the names of all %% attributes or referenced attribute groups. {CM,S2} = type(AG#xmlElement.content,in_scope(Name,S), [attributeGroup|Env]), S2_1 = out_scope(Name,S2), S3 = check_cm(attributeGroup,allowed_content(attributeGroup,Env),CM,S2_1), S4 = save_object({attributeGroup, #schema_attribute_group{name=Name, content=keep_attributes(CM)}},S3), {{attributeGroup,Name},S4} end;element_content({group,S},G,Env) -> %% a model group associates a name with a content model. It can be %% a reference or a definition. %% content is one of all, choice or sequence. case qualify_NCName(G,S) of no_name -> % reference Ref = particle_ref(G), {Occur,S2} = occurance(G,{1,1},S), GRef = {group, {get_QName(Ref,G#xmlElement.namespace,reset_scope(S2)),%%QQQ Occur}}, {GRef,add_ref(S2,GRef)}; Name -> % definition, always schema or redefine as parent {CM,S2} = type(G#xmlElement.content,in_scope(Name,S),[group|Env]), S2_1 = out_scope(Name,S2), S3 = check_cm(group,allowed_content(group,Env),CM,S2_1), S4 = save_object({group,#schema_group{name=Name, content=remove_annotation(CM)}},S3), {{group,Name},S4} end;element_content({all,S},All,Env) -> %% each element occurs 0 or 1 times in any order %% {all,[{element_name,occurance}]}%% CM = content_model(Seq#xmlElement.content,S,[all|Env]), {Occur,S1} = occurance(All,{1,1},S), {CM,S2} = type(All#xmlElement.content,S1,[all|Env]), S3 = check_cm(all,allowed_content(all,Env),CM,S2), {{all,{[X||X = {element,_} <- CM],Occur}},S3};element_content({sequence,S},Seq,Env) -> %% {sequence,[{element_name,occurance}]}%% CM = content_model(Seq#xmlElement.content,S,[sequence|Env]), {Occur,S1} = occurance(Seq,{1,1},S), {CM,S2} = type(Seq#xmlElement.content,S1,[sequence|Env]), S3 = check_cm(sequence,allowed_content(sequence,Env),CM,S2), {{sequence,{remove_annotation(CM),Occur}},S3};element_content({choice,S},Choice,Env) -> %% allowed content: (annotation?, %% (element | group | choice | sequence | any)*) %% returns: {choice,[element_name]}%% CM = content_model(Choice#xmlElement.content,S,[choice|Env]), {Occur,S1} = occurance(Choice,{1,1},S), {CM,S2} = type(Choice#xmlElement.content,S1,[choice|Env]), S3 = check_cm(choice,allowed_content(choice,Env),CM,S2), {{choice,{remove_annotation(CM),Occur}},S3};element_content({any,S},Any,_Env) -> {Occur,S1} = occurance(Any,{1,1},S), NameSpace = wildcard_namespace(Any,S1), PC = processor_contents(Any), ?debug("element_content, any: Any content:~p~n",[Any#xmlElement.content]), Pred = fun(E=#xmlElement{}) -> case kind(E) of annotation -> false; _ -> true end; (_) -> false end, S2 = case filter(Pred,Any#xmlElement.content) of [] -> S1; Err -> %% report error acc_errs(S1,{error_path(Any,Any#xmlElement.name),?MODULE, {unexpected_content_in_any,Err}}) end, {{any,{NameSpace,Occur,PC}},S2};element_content({IDC,S},El,Env) when IDC==unique;IDC==key;IDC==keyref-> QName = qualify_NCName(El,reset_scope(S)), Ref = keyrefer(IDC,El,S), {SelField,S2} = type(El#xmlElement.content,S,[IDC|Env]), case {[X||X={selector,_} <- SelField],[X||X={field,_} <- SelField]} of {[Sel],Fields=[_H|_T]} -> IDConstr = #id_constraint{category=IDC,name=QName,refer=Ref, selector=Sel,fields=Fields}, S3=save_idc(IDC,IDConstr,S2), {{IDC,IDConstr},S3}; Err -> S3 = acc_errs(S2,{error_path(El,El#xmlElement.name),?MODULE, {erronous_content_in_identity_constraint,IDC,Err}}), {{IDC,[]},S3} end;element_content({selector,S},Sel,_Env) -> case get_attribute_value(xpath,Sel,error) of error -> S2 = acc_errs(S,{error_path(Sel,Sel#xmlElement.name),?MODULE, {missing_xpath_attribute,selector}}), {{selector,[]},S2}; XPath -> {{selector,XPath},S} end;element_content({field,S},F,_Env) -> case get_attribute_value(xpath,F,error) of error -> S2 = acc_errs(S,{error_path(F,F#xmlElement.name),?MODULE, {missing_xpath_attribute,field}}), {{field,[]},S2}; XPath -> {{field,XPath},S} end;element_content({notation,S},_N,_Env) -> {{notation,[]},S};element_content({annotation,S},_Ann,_Env) -> {{annotation,[]},S};element_content({appinfo,S},_AI,_Env) -> {{appinfo,[]},S};element_content({documentation,S},_D,_Env) -> {{documentation,[]},S};element_content({simpleType,S},ST,Env) -> Name = case qualify_NCName(ST,S) of no_name -> get_QName('_xmerl_no_name_',ST#xmlElement.namespace, in_scope('_xmerl_no_name_',S));%%--- QName -> QName end, {Type,S2} = type(ST#xmlElement.content, push_circularity_mark({typeDef,Name},in_scope(Name,S)), [simpleType|Env]), S2_1 = pop_circularity_mark({typeDef,Name},S2), S3 = set_scope(S#xsd_state.scope,S2_1), S4 = check_cm(simpleType,allowed_content(simpleType,Env),Type,S3), {BaseType,Facets} = facets(Type,S4), Variety = variety(Type), Final = simpleType_final(ST,S4), Object = {simpleType,#schema_simple_type{name=Name, base_type=BaseType, final=Final, facets=Facets, variety=Variety, content=remove_annotation(Type), scope=S4#xsd_state.scope}}, S5 = save_object(Object,S4), S6 = derived_type(Object,S5),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -