diff options
Diffstat (limited to 'lib/xmerl/src/xmerl_simple.erl')
-rw-r--r-- | lib/xmerl/src/xmerl_simple.erl | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/xmerl/src/xmerl_simple.erl b/lib/xmerl/src/xmerl_simple.erl new file mode 100644 index 0000000000..573dcd2a62 --- /dev/null +++ b/lib/xmerl/src/xmerl_simple.erl @@ -0,0 +1,109 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% 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. +%% +%% %CopyrightEnd% +%% + + +%% Description : Simple event-based processor (front-end to xmerl_scanner) + + +-module(xmerl_simple). + +-export([file/2, + string/2]). + +-include("xmerl.hrl"). + +-record(state, {content_acc = [], + attr_acc = [], + content_stack = [], + attr_stack = []}). + +file(Fname, Opts) -> + Opts1 = scanner_options(Opts), + xmerl_scan:file(Fname, Opts1). + +string(Str, Opts) -> + Opts1 = scanner_options(Opts), + xmerl_scan:string(Str, Opts1). + +scanner_options(Opts) -> + EventS = #state{}, + scanner_options(Opts, + [{event_fun, fun event/2, EventS}, + {acc_fun, fun(_, Acc, S) -> {Acc,S} end}, + {close_fun, fun close/1}]). + +scanner_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(_X, _Pos, []) -> + throw(false). + + +close(S) -> + ES = xmerl_scan:event_state(S), + #state{attr_stack = [], + content_stack = [], + %% attr_acc may contain document attributes + content_acc = Content} = ES, + lists:reverse(Content). + +event(#xmerl_event{event = started, data = #xmlElement{}}, S) -> + #state{content_acc = CAcc, + attr_acc = AAcc, + content_stack = CSt, + attr_stack = ASt} = ES = xmerl_scan:event_state(S), + xmerl_scan:event_state(ES#state{content_acc = [], + attr_acc = [], + content_stack = [CAcc | CSt], + attr_stack = [AAcc | ASt]}, S); + +event(#xmerl_event{event = ended, data = #xmlElement{name = Name}}, S) -> + #state{content_acc = CAcc, + attr_acc = AAcc, + content_stack = [PrevCAcc | CSt], + attr_stack = [PrevAAcc | ASt]} = ES = xmerl_scan:event_state(S), + Simple = {Name, lists:reverse(AAcc), lists:reverse(CAcc)}, + xmerl_scan:event_state(ES#state{content_acc = [Simple|PrevCAcc], + attr_acc = PrevAAcc, + content_stack = CSt, + attr_stack = ASt}, S); + +event(#xmerl_event{event = ended, data = #xmlAttribute{name = Name, + value = Value}}, S) -> + #state{attr_acc = AAcc} = ES = xmerl_scan:event_state(S), + Simple = {Name, Value}, + xmerl_scan:event_state(ES#state{attr_acc = [Simple|AAcc]}, S); + +event(#xmerl_event{event = ended, data = #xmlText{value = Text}}, S) -> + #state{content_acc = CAcc} = ES = xmerl_scan:event_state(S), + xmerl_scan:event_state(ES#state{content_acc = [Text|CAcc]}, S); + +event(_E, S) -> + S. |