⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmerl_eventp.erl

📁 OTP是开放电信平台的简称
💻 ERL
字号:
%%% 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.%%%%%% Contributor(s): ______________________________________.%%%%%%----------------------------------------------------------------------%%% #0.    BASIC INFORMATION%%%----------------------------------------------------------------------%%% File:       xmerl_eventp.erl%%% Author       : Ulf Wiger <ulf.wiger@ericsson.com>%%%                Johan Blom <Johan.Blom@mobilearts.se>%%% Description  : Simple event-based processor (front-end to xmerl_scan)%%% %%% Modules used : %%% %%%----------------------------------------------------------------------%% @doc Simple event-based front-ends to xmerl_scan for processing%% of XML documents in streams and for parsing in SAX style.%% Each contain more elaborate settings of xmerl_scan that makes usage of%% the customization functions.%% -module(xmerl_eventp).-vsn('0.19').-date('03-09-17').-export([stream/2,stream_sax/4, file_sax/4, string_sax/4]).% -export([cont/3, rules_read/3,rules_write/4,fetch/2,close/1]).-include("xmerl.hrl").-include_lib("kernel/include/file.hrl").%% @spec stream(Fname::string(), Options::option_list()) -> xmlElement()%%%% @doc Parse file containing an XML document as a stream, DOM style.%% Wrapper for a call to the XML parser <code>xmerl_scan</code> with a%% <code>continuation_fun</code> for handling streams of XML data.%% Note that the <code>continuation_fun</code>, <code>acc_fun</code>,%% <code>fetch_fun</code>, <code>rules</code> and <code>close_fun</code>%% options cannot be user defined using this parser.stream(Fname, Options) ->    AccF = fun(X, Acc, S) -> acc(X,Acc,S) end,    case file:open(Fname, [read, raw, binary]) of	{ok, Fd} ->	    B0 = list_to_binary([]),	    ContS = [{B0, Fname, Fd}],	    Opts=scanner_options(Options,				 [{continuation_fun, fun cont/3, ContS},				  {acc_fun, AccF},				  {fetch_fun, fun fetch/2},				  {rules,fun rules_read/3,fun rules_write/4,""},				  {close_fun, fun close/1}]),	    xmerl_scan:string([], Opts);	Error ->	    Error    end.%% @spec stream_sax(Fname,CallBackModule,UserState,Options) -> xmlElement()%%       Fname = string()%%       CallBackModule = atom()%%       Options = option_list()%%%% @doc Parse file containing an XML document as a stream, SAX style.%% Wrapper for a call to the XML parser <code>xmerl_scan</code> with a%% <code>continuation_fun</code> for handling streams of XML data.%% Note that the <code>continuation_fun</code>, <code>acc_fun</code>,%% <code>fetch_fun</code>, <code>rules</code>, <code>hook_fun</code>,%% <code>close_fun</code> and <code>user_state</code> options cannot be user%% defined using this parser.stream_sax(Fname, CallBack, UserState,Options) ->    US={xmerl:callbacks(CallBack), UserState},    AccF = fun(X, Acc, S) -> acc(X,Acc,S) end,    HookF=	fun(ParsedEntity, S) ->		{CBs,Arg}=xmerl_scan:user_state(S),%		io:format("stream_sax Arg=~p~n",[Arg]),		case ParsedEntity of		    #xmlComment{} -> % Toss away comments...			{[],S};		    _ ->  % Use callback module for the rest%		io:format("stream_sax ParsedEntity=~p~n",[ParsedEntity]),			case xmerl:export_element(ParsedEntity,CBs,Arg) of			    {error,Reason} ->				throw({error,Reason});			    Resp ->%		io:format("stream_sax Resp=~p~n",[Resp]),				{Resp,xmerl_scan:user_state({CBs,Resp},S)}			end		end	end,    case file:open(Fname, [read, raw, binary]) of	{ok, Fd} ->	    B0 = list_to_binary([]),	    ContS = [{B0, Fname, Fd}],	    Opts=scanner_options(Options,				 [{acc_fun, AccF},				  {close_fun, fun close/1},				  {continuation_fun, fun cont/3, ContS},				  {fetch_fun, fun fetch/2},				  {hook_fun,HookF},				  {rules,fun rules_read/3,fun rules_write/4,""},				  {user_state,US}]),	    xmerl_scan:string([], Opts);	Error ->	    Error    end.%% @spec file_sax(Fname::string(), CallBackModule::atom(), UserState,%%        Options::option_list()) -> NewUserState%%%% @doc Parse file containing an XML document, SAX style.%% Wrapper for a call to the XML parser <code>xmerl_scan</code> with a%% <code>hook_fun</code> for using xmerl export functionality directly after%% an entity is parsed.file_sax(Fname,CallBack, UserState, Options) ->    US={xmerl:callbacks(CallBack), UserState},    AccF=fun(X,Acc,S) -> {[X|Acc], S} end,    HookF=	fun(ParsedEntity, S) ->		{CBs,Arg}=xmerl_scan:user_state(S),		case ParsedEntity of		    #xmlComment{} -> % Toss away comments...			{[],S};		    _ ->  % Use callback module for the rest			case xmerl:export_element(ParsedEntity,CBs,Arg) of			    {error,Reason} ->				throw({error,Reason});			    Resp ->				{Resp,xmerl_scan:user_state({CBs,Resp},S)}			end		end	end,        Opts=scanner_options(Options,[{acc_fun, AccF},				  {hook_fun,HookF},				  {user_state,US}]),    xmerl_scan:file(Fname,Opts).%% @spec string_sax(String::list(), CallBackModule::atom(), UserState,%%        Options::option_list()) ->%%      xmlElement()%%%% @doc Parse file containing an XML document, SAX style.%% Wrapper for a call to the XML parser <code>xmerl_scan</code> with a%% <code>hook_fun</code> for using xmerl export functionality directly after%% an entity is parsed.string_sax(String,CallBack, UserState, Options) ->    US={xmerl:callbacks(CallBack), UserState},    AccF=fun(X,Acc,S) -> {[X|Acc], S} end,    HookF=	fun(ParsedEntity, S) ->		{CBs,Arg}=xmerl_scan:user_state(S),		case ParsedEntity of		    #xmlComment{} -> % Toss away comments...			{[],S};		    _ ->  % Use callback module for the rest			case xmerl:export_element(ParsedEntity,CBs,Arg) of			    {error,Reason} ->				throw({error,Reason});			    Resp ->				{Resp,xmerl_scan:user_state({CBs,Resp},S)}			end		end	end,        Opts=scanner_options(Options,[{acc_fun, AccF},				  {hook_fun,HookF},				  {user_state,US}]),    xmerl_scan:string(String,Opts).%%% ----------------------------------------------------------------------------%%% Streaming support functions%%% Continuation callback function for xmerl_scancont(F, Exception, S) ->    case xmerl_scan:cont_state(S) of	[{_Fname, eof}|_] ->	    Exception(S);	[{Sofar, Fname, Fd}|T] ->	    cont2(F, Exception, Sofar, Fd, Fname, T, S)    end.cont2(F, Exception, Sofar, Fd, Fname, T, S) ->    case catch read_chunk(Fd, Fname, Sofar) of	{ok, Bin} ->	    find_good_split(list_to_binary([Sofar,Bin]),			    F,Exception,Fd,Fname,T,S);	eof ->	    file:close(Fd),	    NewS = xmerl_scan:cont_state([{Fname, eof}|T], S),	    F(binary_to_list(Sofar), NewS);	Error ->	    exit(Error)    end.    read_chunk(Fd, _Fname, _Sofar) ->    file:read(Fd, 8192).-ifndef(no_bitsyntax).find_good_split(Bin, F, Exception, Fd, Fname, T, S) ->    find_good_split(size(Bin)-1, Bin, F, Exception, Fd, Fname, T, S).find_good_split(0, B, F, Exception, Fd, Fname, T, S) ->    cont2(F, Exception, B, Fd, Fname, T, S);find_good_split(Size, B, F, Exception, Fd, Fname, T, S) ->    case B of	<<_Bytes:Size/binary, H/integer, Tail/binary>> when ?whitespace(H) ->	    {SubB,_} = split_binary(B, Size+1),	    NewS = xmerl_scan:cont_state([{Tail, Fname, Fd}|T], S),	    F(binary_to_list(SubB), NewS);	_ ->	    find_good_split(Size-1, B, F, Exception, Fd, Fname, T, S)    end.-else.find_good_split(Bin, F, Exception, Fd, Fname, T, S) ->    find_good_split(size(Bin), Bin, F, Exception, Fd, Fname, T, S).find_good_split(0, B, F, Exception, Fd, Fname, T, S) ->    cont2(F, Exception, B, Fd, Fname, T, S);find_good_split(Size, B, F, Exception, Fd, Fname, T, S) ->    case binary_to_list(B, Size, Size) of	[H] when ?whitespace(H) ->	    {SubB,Tail} = split_binary(B, Size),	    NewS = xmerl_scan:cont_state([{Tail, Fname, Fd}|T], S),	    F(binary_to_list(SubB), NewS);	_ ->	    find_good_split(Size-1, B, F, Exception, Fd, Fname, T, S)    end.-endif.%%% Accumulator callback function for xmerl_scanacc(X = #xmlText{value = Text}, Acc, S) ->    case detect_nul_text(Text) of 	ok->	    {[X#xmlText{value = lists:flatten(Text)}|Acc], S};   	nok->	    {Acc,S}    end;acc(X, Acc, S) ->    {[X|Acc], S}.%%% don't acc xmlText when text contains only " " , "\n" and "\t".detect_nul_text([H|T]) when H==10; H==32; H==9->    detect_nul_text(T);detect_nul_text([]) ->    nok;detect_nul_text(_)->    ok.%%% Fetch callback function for xmerl_scanfetch({system, URI}, S) ->    fetch_URI(URI, S);fetch({public, _PublicID, URI}, S) ->    fetch_URI(URI, S).fetch_URI(URI, S) ->    %% assume URI is a filename    Split = filename:split(URI),    Filename = lists:last(Split),    Fullname = 	case Split of	    ["/", _|_] ->		%% absolute path name		URI;	    ["file:",Name]->		%% file:/dtd_name 		filename:join(S#xmerl_scanner.xmlbase, Name);	    _ ->		filename:join(S#xmerl_scanner.xmlbase, URI)	end,    File = path_locate(S#xmerl_scanner.fetch_path, Filename, Fullname),    ?dbg("fetch(~p) -> {file, ~p}.~n", [URI, File]),    case file:open(File, [read, raw, binary]) of	{ok, Fd} ->	    ContS=xmerl_scan:cont_state(S),	    NewS=xmerl_scan:cont_state([{list_to_binary([]),File,Fd}|ContS],S),	    {ok, {string, []}, NewS};	_Error ->	    ?dbg("ERROR fetch(~p) -> ~p~n", [URI, _Error]),	    {ok, not_fetched, S}    end.path_locate([Dir|Dirs], FN, FullName) ->    F = filename:join(Dir, FN),    case file:read_file_info(F) of	{ok, #file_info{type = regular}} ->	    F;	_ ->	    path_locate(Dirs, FN, FullName)    end;path_locate([], _FN, FullName) ->    FullName.%%% Close callback function for xmerl_scanclose(S) ->    ContS = xmerl_scan:cont_state(S),    case ContS of	[{_Fname, eof}|T] ->	    xmerl_scan:cont_state(T, S);	[{_Sofar, _Fname, Fd}|T] ->	    file:close(Fd),	    xmerl_scan:cont_state(T, S)    end.%%% Rules callback functions for xmerl_scanrules_write(Context, Name, Value, #xmerl_scanner{rules = undefined}=S) ->    Tab = ets:new(rules, [set, public]),    rules_write(Context, Name, Value, S#xmerl_scanner{rules = Tab});rules_write(Context, Name, Value, #xmerl_scanner{rules = T} = S) ->    ets:insert(T, {{Context, Name}, Value}),    S.rules_read(_Context, _Name, #xmerl_scanner{rules = undefined}) ->    undefined;rules_read(Context, Name, #xmerl_scanner{rules = T}) ->    case ets:lookup(T, {Context, Name}) of	[] ->	    undefined;	[{_K, V}] ->	    V    end.%%% ----------------------------------------------------------------------------%%% Generic helper functionsscanner_options([H|T], Opts) ->    case catch keyreplace(H, 1, Opts) of	false ->	    scanner_options(T, [H|Opts]);	NewOpts ->	    scanner_options(T, NewOpts)    end;scanner_options([], Opts) ->    Opts.keyreplace(X, Pos, [H|T]) when element(Pos, X) == element(Pos, H) ->    [X|T];keyreplace(X, Pos, [H|T]) ->    [H|keyreplace(X, Pos, T)];keyreplace(_, _Pos, []) ->    throw(false).

⌨️ 快捷键说明

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