📄 xmerl_xsd.erl
字号:
{{simpleType,Name},S6};element_content({restriction,S},R,Env) -> %% If complexContent, all element definitions of base type must be %% repeated. However, attributes are inherited. %% possible parents are simpleType or complexType (grand parent) %% If parent is simpleType the base type is either the attribute %% base (resolved by base_type/1) or the type defined in content. {CM,S2} = type(R#xmlElement.content,S,[restriction|Env]), S3 = check_cm(restriction,allowed_content(restriction,Env),CM,S2), {BaseTypeName,CM2,S4} = restriction_base_type(R,CM,S3), %% a QName%% S5 = add_circularity_mark(BaseTypeName,S4), BaseTypeType = base_type_type(Env), {{restriction,{BaseTypeName,remove_annotation(CM2)}}, add_ref(S4,{BaseTypeType,BaseTypeName})}; %% Does not return name but content modelelement_content({list,S=#xsd_state{scope=Scope}},L,Env) -> {Type,S2} = list_type(L,S,[list|Env]), S3 = check_cm(list,allowed_content(list,Scope),Type,S2), {{list,remove_annotation(Type)},S3};element_content({union,S=#xsd_state{scope=Scope}},U,Env) -> {Types,S2} = union_types(U,S,[union|Env]), S3 = check_cm(union,allowed_content(union,Scope),Types,S2), {{union,Types},S3};element_content({include,S=#xsd_state{schema_name=ThisSchema, targetNamespace=TNS}},I,_Env) -> S2 = process_external_schema_once(I,S#xsd_state.targetNamespace,S), {{include,[]},S2#xsd_state{schema_name=ThisSchema,targetNamespace=TNS}};element_content({import,S=#xsd_state{schema_name=ThisSchema, targetNamespace=ThisNameS}},I,_Env) -> %% import unlike include and redefine may include definitions from %% other namespaces than the target namespace of the including %% schema. %% namespace and schemaLocation Namespace = case get_attribute_value(namespace,I,undefined) of L when is_list(L) -> list_to_atom(L); A -> A end, %% If Namespace is absent, then the import allows unqualified %% reference to components with no target namespace. SchemaLocation = get_attribute_value(schemaLocation,I,absent), %% If SchemaLocation is absent, the identification of that schema %% is leaved to the instance, application or user, via the %% mechanisms described 仹4.3 in XML Schema Part 1. S2 = process_external_schema_once(SchemaLocation,Namespace,S), {{import,[]},S2#xsd_state{schema_name=ThisSchema, targetNamespace=ThisNameS}};element_content({redefine,S=#xsd_state{schema_name=ThisSchema}},RD,Env) -> %% Must be a child of "schema" element %% redefine of simple and complex types, groups and attribute %% groups obtained from external files. %% Brings in all definitions of external schema and redefines one. %% External schema must be in same namespace as current schema or %% no namespace. S2 = process_external_schema_once(RD,S#xsd_state.targetNamespace, S#xsd_state{errors=[]}), case S2#xsd_state.errors of [] ->%% RedefSource = S2#xsd_state.schema_name, S3 = S2#xsd_state{schema_name=ThisSchema,%% global_element_source=add_once({ThisSchema,RedefSource},GES), errors=S#xsd_state.errors}, {CM,S4} = type(RD#xmlElement.content, S3#xsd_state{redefine=true},[redefine|Env]), S5 = S4#xsd_state{redefine=false}, S6 = check_cm(redefine,allowed_content(redefine,Env),CM,S5), S7 = redefine(CM,S6), {{redefine,[]},S7}; Errs -> S3 = S2#xsd_state{schema_name=ThisSchema, errors=Errs++S#xsd_state.errors}, {{redefine,[]},S3} end;element_content({anyAttribute,S},AA,_Env) -> %% has attributes processContents = (lax | skip | strict) : strict %% namespace = ((##any | ##other) | %% List of (anyURI | (##targetNamespace | ##local)) ) : ##any NameSpace = wildcard_namespace(AA,S), PC = processor_contents(AA), Pred = fun(E=#xmlElement{}) -> case kind(E) of annotation -> false; _ -> true end; (_) -> false end, S2 = case filter(Pred,AA#xmlElement.content) of [] -> S; Err -> %% report error acc_errs(S,{error_path(AA,AA#xmlElement.name),?MODULE, {content_in_anyAttribute,Err}}) end, {{anyAttribute,{NameSpace,PC}},S2};element_content({simpleContent,S},SC,Env) -> %% only as child of complexType. %% allowed content: (annotation?, (restriction | extension)) S2 = pre_check_cm(simpleContent,SC#xmlElement.content,mk_name(S#xsd_state.scope),S), case filter(fun(X=#xmlElement{}) -> case kind(X) of restriction -> true; extension -> true; _ -> false end; (_) -> false end, SC#xmlElement.content) of [E] -> element_content(kind(E,S2),E,[simpleContent|Env]); Err -> {[],acc_errs(S2,{error_path(SC,SC#xmlElement.name),?MODULE, {content_in_simpleContent,Err}})} end;element_content({complexContent,S},CC,Env) -> S2 = pre_check_cm(complexContent,CC#xmlElement.content, mk_name(S#xsd_state.scope),S), %% the mixed attribute was fetched in the complexType element that %% held this complexContent case filter(fun(X=#xmlElement{}) -> case kind(X) of restriction -> true; extension -> true; _ -> false end; (_) -> false end,CC#xmlElement.content) of [E] -> element_content(kind(E,S2),E,[complexContent|Env]); Err -> {[],acc_errs(S2,{error_path(CC,CC#xmlElement.name),?MODULE, {complexContent_content_failure,Err}})} end;element_content({extension,S},Ext,Env) -> %% may be used in both simple and complex content with different %% content allowed. %% this should be returned and checked for allowed content in %% parent, but we don't know if base type is a forward reference. BaseType = base_type(Ext), {CM,S2} = type(Ext#xmlElement.content,S,[extension|Env]), S3 = check_cm(extension,allowed_content(extension,S#xsd_state.scope),CM,S2), BaseTypeName = get_QName(BaseType,Ext#xmlElement.namespace,reset_scope(S)),%%QQQ BaseTypeType = base_type_type(Env), {{extension,{BaseTypeName,CM}},add_ref(S3,{BaseTypeType,BaseTypeName})};%% The following are facetselement_content({minExclusive,S},CF,_Env) -> Value = get_value(CF), {{minExclusive,Value},S};element_content({minInclusive,S},CF,_Env) -> Value = get_value(CF), {{minInclusive,Value},S};element_content({maxExclusive,S},CF,_Env) -> Value = get_value(CF), {{maxExclusive,Value},S};element_content({maxInclusive,S},CF,_Env) -> Value = get_value(CF), {{maxInclusive,Value},S};element_content({totalDigits,S},CF,_Env) -> Value = get_value(CF), {{totalDigits,Value},S};element_content({fractionDigits,S},CF,_Env) -> Value = get_value(CF), {{fractionDigits,Value},S};element_content({length,S},CF,_Env) -> Value = get_value(CF), {{length,Value},S};element_content({minLength,S},CF,_Env) -> Value = get_value(CF), {{minLength,Value},S};element_content({maxLength,S},CF,_Env) -> Value = get_value(CF), {{maxLength,Value},S};element_content({enumeration,S},CF,_Env) -> Value = get_value(CF), {{enumeration,Value},S};element_content({whiteSpace,S},CF,_Env) -> Value = get_value(CF), {{whiteSpace,Value},S};element_content({pattern,S},CF,_Env) -> Value = get_value(CF), {{pattern,Value},S};element_content({Other,S=#xsd_state{errors=Errs}},C,_Env) -> case Errs of [] -> {[],acc_errs(S,{error_path(C,C#xmlElement.name),?MODULE, {unknown_content,Other}})}; _ -> {[],S} end.type(C,S,Env) -> type(C,S,Env,[]).type([E=#xmlElement{}|Els],S,Env,Acc) -> {CM,S2} = element_content(kind(E,S),E,Env), type(Els,set_scope(S#xsd_state.scope,S2), Env,[CM|Acc]);type([_H|Els],S,Env,Acc) -> type(Els,S,Env,Acc);type([],S,_Env,Acc) -> {flatten(reverse(Acc)),S}. simpleUrType() -> {anySimpleType,[]}.%% simpleUrTypeRef() ->%% {anySimpleType,[],'http://www.w3.org/2001/XMLSchema'}.urType() -> {anyType,[]}.attribute_type(Att,Env=[Name|_],S) -> %% The attribute type may be referenced by the type attribute or %% explicitly defined as a simpleType inside the attribute %% element. In the latter case the type must be saved with the %% unique name of the scope and name attribute combined. {CM,S2} = type(Att#xmlElement.content,in_scope(Name,S),Env), case remove_annotation(CM) of [] -> case keyNsearch(type,#xmlAttribute.name, Att#xmlElement.attributes,[]) of #xmlAttribute{value=SimpleTypeName} -> %% a QName as string %% This name may be a forward reference to a simple type. TypeRef = {simpleType,get_QName(SimpleTypeName, %%QQQ Att#xmlElement.namespace, reset_scope(S))}, {[TypeRef], set_scope(S#xsd_state.scope,add_ref(S2,TypeRef))}; _ -> {[{simpleType,simpleUrType()}], set_scope(S#xsd_state.scope,S2)} end; Type -> {Type,set_scope(S#xsd_state.scope,S2)} end.element_type(El,Env=[Name|_],S) -> %% In the top environment of the schema there may exist: global %% element declarations, substitution group members. %% Other element declarations are local {CM,S2} = type(El#xmlElement.content,in_scope(Name,S),Env), case remove_annotation(CM) of [] -> %% no simple or complex type definition case {get_attribute_value(type,El,no_name), get_attribute_value(substitutionGroup,El,undefined)} of {no_name,SGName} when is_list(SGName) -> QN = get_QName(SGName,El#xmlElement.namespace,reset_scope(S)),%%QQQ case is_simple_type(QN,S2) of true -> exit(this_can_never_happen), %% A substitutionGroup is an element, and %% the type of this element is the %% resolved type of the referenced %% element. TRef = {simpleType,QN}, {[TRef], add_ref(set_scope(S#xsd_state.scope,S2),TRef)}; _ -> {[{substitutionGroup,QN}], set_scope(S#xsd_state.scope,S2)} end; {TName,_} when is_list(TName) -> QN = get_QName(TName,El#xmlElement.namespace,reset_scope(S2)),%%QQQ case is_simple_type(QN,S2) of true -> TRef={simpleType,QN}, {[TRef], add_ref(set_scope(S#xsd_state.scope,S2),TRef)}; _ -> TRef = {simple_or_complex_Type,QN}, {[TRef], add_ref(set_scope(S#xsd_state.scope,S2),TRef)} end; _ -> case {get_attribute_value(ref,El,no_name), is_global_env(Env)} of {Ref,false} when is_list(Ref) -> %% a ref attribute references an element {[{element, get_QName(Ref,El#xmlElement.namespace,%%QQQ reset_scope(S))}], set_scope(S#xsd_state.scope,S2)}; _ -> {[urType()], set_scope(S#xsd_state.scope,S2)} end end;%% Type ->%% {Type,set_scope(S#xsd_state.scope,S2)} _Type -> {CM,set_scope(S#xsd_state.scope,S2)} end.%% list_type/3 -> list() | name()list_type(L,S,Env) -> case keyNsearch(itemType,#xmlAttribute.name,L#xmlElement.attributes,[]) of [] ->%% {element(1,type(L#xmlElement.content,S,Env)),S}; type(L#xmlElement.content,S,Env); #xmlAttribute{value=V} -> %% this type should be preliminary saved and checked after %% the parsing of the schema. TypeRef ={simpleType, get_QName(V,L#xmlElement.namespace,reset_scope(S))}, {[TypeRef],add_ref(S,TypeRef)} end.union_types(U,S,Env) -> {MemberTypes,S2} = case keyNsearch(memberTypes,#xmlAttribute.name,U#xmlElement.attributes,[]) of [] -> {[],S}; #xmlAttribute{value = NameString} -> Names = namestring2namelist(NameString), UTypeRefs = [{simpleType,get_QName(X,U#xmlElement.namespace, reset_scope(S))}||X<-Names], {UTypeRefs,foldl(fun(X,S_in) -> add_ref(S_in,X) end,S,UTypeRefs)} end, {DefinedTypes,S3} = union_types1(U#xmlElement.content,S2,Env), {MemberTypes++DefinedTypes,S3}.union_types1(C,S,Env) -> union_types1(C,S,Env,[]).union_types1([],S,_Env,Acc) -> {Acc,S};union_types1([C=#xmlElement{}|Cs],S,Env,Acc) -> case element_content(kind(C,S),C,Env) of {ST={simpleType,_},S2} -> union_types1(Cs,S2,Env,[ST|Acc]); {{annotation,_},S2} -> union_types1(Cs,S2,Env,Acc); {IllegalType,S2} -> Err = {error_path(C,C#xmlElement.name),?MODULE, {union_member_type_not_simpleType,IllegalType}}, union_types1(Cs,acc_errs(S2,Err),Env,Acc) end;union_types1([_H|T],S,Env,Acc) -> union_types1(T,S,Env,Acc).add_ref(S=#xsd_state{unchecked_references=UR},STRef={simpleType,Ref}) -> case {is_builtin_simple_type(Ref),Ref} of {true,_} -> S; {_,{'',_,_}} -> S; _ -> S2 = S#xsd_state{unchecked_references=add_once(STRef,UR)}, add_circularity_ref(STRef,S2) end;add_ref(S=#xsd_state{unchecked_references=UR},STRef={simple_or_complex_Type,Ref}) -> case {is_builtin_simple_type(Ref),Ref} of {true,_} -> S; {_,{'',_,_}} -> S; {_,{anyType,_,?XSD_NAMESPACE}} -> S; {_,{anySimpleType,_,?XSD_NAMESPACE}} -> S; _ -> S2 = S#xsd_state{unchecked_references=add_once(STRef,UR)}, add_circularity_ref(STRef,S2) end;add_ref(S,{complexType,{anyType,_,?XSD_NAMESPACE}}) -> S;add_ref(S=#xsd_state{unchecked_references=UR},Ref) -> S2 = S#xsd_state{unchecked_references=add_once(Ref,UR)}, add_circularity_ref(Ref,S2).%% add_ref(S=#xsd_state{unchecked_references=UR},Ref) ->%% S#xsd_state{unchecked_references=add_once(Ref,UR)}.%% Name of simpleType/complexType is unique within the whole%% environment, which is checked elsewhere, so ignore the kind of type%% for simplicity.add_circularity_ref(Ref={Kind,To},S=#xsd_state{circularity_disallowed=CD, redefine=false}) when Kind==simpleType;Kind==simple_or_complex_Type;Kind==complexType -> case get_circularity_mark(Ref,S) of [] -> S; From -> %% This is the node from which the graph reaches Ref S#xsd_state{circularity_disallowed=add_once({From,{typeDef,To}},CD)} end;add_circularity_ref(_,S) ->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -