xmerl_validate.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 659 行 · 第 1/2 页

ERL
659
字号
%%% The contents of this file are subject to the Erlang Public License,%%% Version 1.0, (the "License"); you may not use this file except in%%% compliance with the License. You may obtain a copy of the License at%%% http://www.erlang.org/license/EPL1_0.txt%%%%%% Software distributed under the License is distributed on an "AS IS"%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%%% the License for the specific language governing rights and limitations%%% under the License.%%%%%% The Original Code is xmerl-0.19%%%%%% The Initial Developer of the Original Code is Ericsson Telecom%%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson%%% Telecom AB. All Rights Reserved.%%%%%%%%%----------------------------------------------------------------------%%% #0.    BASIC INFORMATION%%%----------------------------------------------------------------------%%% @private%%% File:       xmerl_validate.erl%%% Author       : Sebastien Becuwe <sebastien.becuwe@cellicium.com>%%% Description  : XML validation hooks for xmerl%%% %%% Modules used : lists, ets, xmerl_lib%%% %%%-----------------------------------------------------------------------module(xmerl_validate).-vsn('0.1').-date('27-11-02').-author('sebastien.becuwe@cellicium.com').-export([validate/2]).%%%%%%%%%%%%% TODOO%%%% Atributes data type id , idrefs, FIXED, ...-include("xmerl.hrl").		% record def, macros%% +type validate(xmerl_scanner(),xmlElement())->%%              xmlElment() | {error,tuple()}.validate(#xmerl_scanner{doctype_name=DTName,doctype_DTD=OpProv},	 #xmlElement{name=Name})  when DTName=/=Name,OpProv=/=option_provided->    {error, {mismatched_root_element,Name,DTName}};validate(#xmerl_scanner{rules=Rules}=S,	 XML=#xmlElement{name=Name})->    catch do_validation(read_rules(Rules,Name),XML,Rules,S);validate(_, XML) ->    {error, {no_xml_element, XML}}.%% +type validate(rules(),xmlElement())->%%              {ok,xmlElement()} | {error,tuple()}.do_validation(undefined,#xmlElement{name=Name}, _Rules,_S) ->    {error,{unknown_element,Name}};do_validation(El_Rule,XML,Rules,S)->    case catch valid_attributes(El_Rule#xmlElement.attributes,			  XML#xmlElement.attributes,S) of	{'EXIT',Reason} ->	    {error,Reason};	{error,Reason} ->	    {error,Reason};	Attr_2->%	    XML_=XML#xmlElement{attributes=Attr_2},	    El_Rule_Cont = El_Rule#xmlElement.content,	    WSActionMode = ws_action_mode(El_Rule#xmlElement.elementdef,					  El_Rule_Cont,S),	    XML_Cont = XML#xmlElement.content,	    check_direct_ws_SDD(XML_Cont,WSActionMode),	    case valid_contents(El_Rule_Cont,				XML_Cont,Rules,S,WSActionMode) of		{error,Reason}->		    {error,Reason};		{error,Reason,N}->		    {error,Reason,N};		XMLS ->		    XML#xmlElement{attributes=Attr_2,content=XMLS}	    end    end.check_direct_ws_SDD(XML,always_preserve) ->    case XML of	[#xmlText{}|_Rest] ->	    exit({error,{illegal_whitespace_standalone_doc,XML}});	_ -> ok    end,    case lists:reverse(XML) of	[#xmlText{}|_Rest2] ->	    exit({error,{illegal_whitespace_standalone_doc,XML}});	_ -> ok    end;check_direct_ws_SDD(_,_) -> ok.ws_action_mode({external,_},Content,#xmerl_scanner{standalone=yes}) ->    case element_content(Content) of	children ->	    always_preserve;	_ ->	    preserve    end;ws_action_mode(_,_,_) ->    preserve.element_content(A) when atom(A),A /= any, A /= empty ->    children;element_content({choice,L}) when list(L) ->    element_content(L);element_content({seq,L}) when list(L) ->    element_content(L);element_content(['#PCDATA'|_T]) ->    mixed;element_content('#PCDATA') ->    mixed;element_content({'*',Rest}) ->     element_content(Rest);element_content(_) -> children.%% +type read_rules(DTD::atom(),Element_Name::atom())->%%              undefined | xmlElement().read_rules(_, pcdata) ->    pcdata;read_rules(T, Name) ->    case ets:lookup(T, {elem_def, Name}) of	[] ->	    undefined;	[{_K, V}] ->	    V    end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Attributes Validation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +deftype attribute_rule() = {Attr_Name::atom(),attribute_type(),%%                              attribute_priority()}.%% +type valid_attributes([attribute_rule()],[xmlAttribute()])->%%              [xmlAttribute()] | {error,attribute_unknow}.valid_attributes(All_Attr,[#xmlAttribute{}|_T]=Attr,S)->    single_ID_definition(All_Attr),    vc_Name_Token_IDREFS(All_Attr,Attr),    lists:foreach(fun(#xmlAttribute{name=Name})->			  case is_attribute_exist(Name,All_Attr) of			      true ->				  ok;			      false ->				  exit({error,{attribute_unknown,Name}})			  end		  end,		  Attr),    lists:flatten(lists:foldl(fun({Name,DataType,IF,DefDecl,Env},Attr_2)->				      Attr_2++					  [valid_attribute(Name,DataType,IF,							   DefDecl,Attr,Env,S)] 			      end,[],All_Attr));valid_attributes([],[],_) ->    [];valid_attributes(All_Attr,[],S) ->    single_ID_definition(All_Attr),    lists:flatten(lists:foldl(fun({Name,DataType,IF,DefDecl,Env},Attr_2)->				      Attr_2++[valid_attribute(Name,							       DataType,IF,							       DefDecl,							       [],							       Env,S)] 			      end,[],All_Attr)).%%%%  [60]      DefaultDecl::=   %%%%                              '#REQUIRED' | '#IMPLIED' %%%%                            | (('#FIXED' S)? AttValue)%% +deftype attribute_priority = '#REQUIRED'|'#FIXED'|'#IMPLIED'.%% +type valid_attribute(Name::atom(),DataType::attribute_value(),%%                       IF::attribute_priority(),[xmlAttribute()])->%%         [xmlAttribute()] | exit().valid_attribute(Name,DataType,IF,DefaultDecl,List_of_Attributes,Env,S)->    SA = S#xmerl_scanner.standalone,    Attr=search_attr(Name,List_of_Attributes),    check_SDD_validity(SA,Env,Attr,IF),    case {DefaultDecl,IF,Attr} of	{'#REQUIRED',_,no_attribute}->	    exit({error,{Name,is_required}});	{'#IMPLIED',_,no_attribute}->	    []; %% and no default value	{'#FIXED',DefVal,#xmlAttribute{value=DefVal}=Attr} ->	    Attr;	{'#FIXED',A,no_attribute} ->	    #xmlAttribute{name=Name,value=A}; % FIXED declare value becomes default.	{'#FIXED',A,B} ->	    exit({error,{fixed_default_value_missmatch,A,B}});	{_,Value,no_attribute} when list(Value)->	    #xmlAttribute{name=Name,value=Value};	{_,_,#xmlAttribute{}=Attr}->	    %% do test data value, and default_value	    test_attribute_value(DataType,Attr,IF,S);	{DefDecl,Else,XML} ->	    exit({error,{unknow_attribute_type,DefDecl,Else,XML}})    end.vc_Name_Token_IDREFS([{Name,Type,_,_,_}|Rest],Attrs)   when Type=='NMTOKEN';Type=='NMTOKENS'->    case lists:keysearch(Name,#xmlAttribute.name,Attrs) of	{value,A} ->	    valid_nmtoken_value(A#xmlAttribute.value,Type);	_ -> ok    end,    vc_Name_Token_IDREFS(Rest,Attrs);vc_Name_Token_IDREFS([{Name,Type,_,_,_}|Rest],Attrs)   when Type=='IDREFS'->    case lists:keysearch(Name,#xmlAttribute.name,Attrs) of	{value,A} ->	    valid_IDREFS(A#xmlAttribute.value,Type);	_ -> ok    end,    vc_Name_Token_IDREFS(Rest,Attrs);vc_Name_Token_IDREFS([_H|Rest],Attrs) ->    vc_Name_Token_IDREFS(Rest,Attrs);vc_Name_Token_IDREFS([],_) -> ok.valid_nmtoken_value([],'NMTOKENS') ->    exit({error,{at_least_one_Nmtoken_required}});% valid_nmtoken_value([H|_T] = L,'NMTOKENS') when list(H) ->%     ValidChar =% 	fun(X) ->% 		case xmerl_lib:is_namechar(X) of% 		    false ->% 			exit({error,{invalid_character_in_Nmtoken,X}});% 		    _ -> ok% 		end% 	end,%     ValidCharList =% 	fun([Nmtok|T],F) -> % 		lists:foreach(ValidChar,Nmtok),% 		F(T,F);% 	   ([],_) -> ok% 	end,%     ValidCharList(L,ValidChar);valid_nmtoken_value(Nmtok,_) ->    ValidChar =	fun(X) when ?whitespace(X),Nmtok=='NMTOKENS' ->		ok;	   (X) ->		case xmerl_lib:is_namechar(X) of		    false ->			exit({error,{invalid_character_in_Nmtoken,X}});		    _ -> ok		end	end,    lists:foreach(ValidChar,Nmtok).valid_IDREFS([],'IDREFS') ->    exit({error,{at_least_one_IDREF_Name_required}});valid_IDREFS(_Str,'IDREFS') ->    ok.    single_ID_definition([{_,'ID',_,_,_}=Att1|Rest]) ->    case lists:keysearch('ID',2,Rest) of	{value,Att2} ->	    exit({error,{just_one_ID_definition_allowed,Att1,Att2}});	_ -> ok    end;single_ID_definition([_H|T]) ->    single_ID_definition(T);single_ID_definition([]) ->    ok.    check_SDD_validity(yes,{external,_},#xmlAttribute{name=Name,normalized=true},_) ->    exit({error,{externally_defed_attribute_normalized_in_standalone_doc,Name}});check_SDD_validity(yes,{external,_},no_attribute,V) when V /= no_value->    exit({error,{externally_defed_attribute_with_default_value_missing_in_standalone_doc}});check_SDD_validity(_,_,_,_) ->    ok.    search_attr(Name,[#xmlAttribute{name=Name}=H|_T])->    H;search_attr(Name,[#xmlAttribute{}|T])->     search_attr(Name,T);search_attr(_Name,_T) ->    no_attribute.is_attribute_exist(Name,[{Name,_,_,_,_}|_T])->    true;is_attribute_exist(Name,[{_Attr,_,_,_,_}|T]) ->    is_attribute_exist(Name,T);is_attribute_exist(_Name,[]) ->    false.%%%%[54] AttType::=     StringType | TokenizedType | EnumeratedType %%%%[55] StringType::=  'CDATA'%%%%[56] TokenizedType::= 'ID'|'IDREF'| 'IDREFS'|'ENTITY'| 'ENTITIES'%%%%                     | 'NMTOKEN'| 'NMTOKENS'%%%%[57] EnumeratedType::= NotationType | Enumeration %%%%[58] NotationType::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' %%%%[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'%% +deftype attribute_type()-> 'CDATA' | 'ID'|'IDREF'| 'IDREFS'|'ENTITY'| %%                             'ENTITIES'| 'NMTOKEN'| 'NMTOKENS'%%                             {enumeration,[List_of_value::atom()]}.%% +type test_attribute_value(attribute_type(),xmlAttribute())->%%             xmlAttribute()| exit.%%%% test the constraint validity of Attribute value.test_attribute_value('CDATA',#xmlAttribute{}=Attr,_,_) ->    Attr;test_attribute_value('NMTOKEN',#xmlAttribute{name=Name,value=V}=Attr,		     Default,_S) ->    Fun =	fun (X)->		case xmerl_lib:is_namechar(X) of		    true->			ok;		    false->			%%io:format("Warning*** nmtoken,value_incorrect:  ~p~n",[V]),			exit({error,{invalid_value_nmtoken,Name,V}})		end	end,    lists:foreach(Fun,V),    if 	list(Default) ->	    lists:foreach(Fun,Default);	true -> ok    end,    Attr;test_attribute_value('NMTOKENS',#xmlAttribute{name=Name,value=V}=Attr,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?