aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xmerl/src/xmerl_sax_simple_dom.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xmerl/src/xmerl_sax_simple_dom.erl')
-rw-r--r--lib/xmerl/src/xmerl_sax_simple_dom.erl263
1 files changed, 263 insertions, 0 deletions
diff --git a/lib/xmerl/src/xmerl_sax_simple_dom.erl b/lib/xmerl/src/xmerl_sax_simple_dom.erl
new file mode 100644
index 0000000000..58a11f70fe
--- /dev/null
+++ b/lib/xmerl/src/xmerl_sax_simple_dom.erl
@@ -0,0 +1,263 @@
+%%-*-erlang-*-
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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%
+%%----------------------------------------------------------------------
+%% File : xmerl_sax_simple_dom.erl
+%% Description :
+%%
+%% Created : 17 Apr 2009
+%%----------------------------------------------------------------------
+-module(xmerl_sax_simple_dom).
+
+%%----------------------------------------------------------------------
+%% Include files
+%%----------------------------------------------------------------------
+-include("xmerl_sax_old_dom.hrl").
+
+%%----------------------------------------------------------------------
+%% External exports
+%%----------------------------------------------------------------------
+-export([
+ initial_state/0,
+ get_dom/1,
+ event/3
+ ]).
+
+%%----------------------------------------------------------------------
+%% Internal exports
+%%----------------------------------------------------------------------
+-export([
+ ]).
+
+%%======================================================================
+%% Macros
+%%======================================================================
+%%----------------------------------------------------------------------
+%% Error handling
+%%----------------------------------------------------------------------
+-define(error(Reason),
+ throw({sax_simple_dom_error, Reason})).
+
+%%----------------------------------------------------------------------
+
+%%======================================================================
+%% Records
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% State record for the validator
+%%----------------------------------------------------------------------
+-record(xmerl_sax_simple_dom_state, {
+ tags=[], %% Tag stack
+ cno=[], %% Current node number
+ namespaces = [], %% NameSpace stack
+ dom=[] %% DOM structure
+ }).
+
+%%======================================================================
+%% External functions
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% Function: initial_state() -> Result
+%% Parameters:
+%% Result:
+%% Description:
+%%----------------------------------------------------------------------
+initial_state() ->
+ #xmerl_sax_simple_dom_state{}.
+
+%%----------------------------------------------------------------------
+%% Function: get_dom(State) -> Result
+%% Parameters:
+%% Result:
+%% Description:
+%%----------------------------------------------------------------------
+get_dom(#xmerl_sax_simple_dom_state{dom=Dom}) ->
+ Dom.
+
+%%----------------------------------------------------------------------
+%% Function: event(Event, LineNo, State) -> Result
+%% Parameters:
+%% Result:
+%% Description:
+%%----------------------------------------------------------------------
+event(Event, _LineNo, State) ->
+ build_dom(Event, State).
+
+
+%%======================================================================
+%% Internal functions
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% Function : build_dom(Event, State) -> Result
+%% Parameters: Event = term()
+%% State = #xmerl_sax_simple_dom_state{}
+%% Result : #xmerl_sax_simple_dom_state{} |
+%% Description:
+%%----------------------------------------------------------------------
+
+%% Document
+%%----------------------------------------------------------------------
+build_dom(startDocument, State) ->
+ State#xmerl_sax_simple_dom_state{dom=[startDocument]};
+build_dom(endDocument,
+ #xmerl_sax_simple_dom_state{dom=[{Tag, Attributes, Content} |D]} = State) ->
+ case D of
+ [startDocument] ->
+ State#xmerl_sax_simple_dom_state{dom=[{Tag, Attributes,
+ lists:reverse(Content)}]};
+ [#xmlDecl{} = Decl, startDocument] ->
+ State#xmerl_sax_simple_dom_state{dom=[Decl, {Tag, Attributes,
+ lists:reverse(Content)}]};
+ _ ->
+ io:format("~p\n", [D]),
+ ?error("we're not at end the document when endDocument event is encountered.")
+ end;
+
+%% Element
+%%----------------------------------------------------------------------
+build_dom({startElement, _Uri, LocalName, _QName, Attributes},
+ #xmerl_sax_simple_dom_state{tags=T, cno=CN, dom=D} = State) ->
+
+ A = parse_attributes(LocalName, Attributes),
+ {Num, NewCN} =
+ case CN of
+ [] ->
+ {1, [1]};
+ [ N |CNs] ->
+ {N, [1, N+1 |CNs]}
+ end,
+
+ State#xmerl_sax_simple_dom_state{tags=[{list_to_atom(LocalName), Num} |T],
+ cno=NewCN,
+ dom=[{list_to_atom(LocalName),
+ lists:reverse(A),
+ []
+ } | D]};
+build_dom({endElement, _Uri, LocalName, _QName},
+ #xmerl_sax_simple_dom_state{tags=[_ |T],
+ cno=[_ |CN],
+ dom=[{CName, CAttributes, CContent},
+ {PName, PAttributes, PContent} | D]} = State) ->
+ case list_to_atom(LocalName) of
+ CName ->
+ State#xmerl_sax_simple_dom_state{tags=T,
+ cno=CN,
+ dom=[{PName, PAttributes,
+ [{CName, CAttributes,
+ lists:reverse(CContent)}
+ |PContent]
+ } | D]};
+ _ ->
+ ?error("Got end of element: " ++ LocalName ++ " but expected: " ++
+ CName)
+ end;
+
+%% Text
+%%----------------------------------------------------------------------
+build_dom({characters, String},
+ #xmerl_sax_simple_dom_state{tags=_T,
+ cno=[Num |CN],
+ dom=[{Name, Attributes, Content}| D]} = State) ->
+ State#xmerl_sax_simple_dom_state{cno=[Num+1 |CN],
+ dom=[{Name, Attributes, [String|Content]} | D]};
+
+build_dom({ignorableWhitespace, String},
+ #xmerl_sax_simple_dom_state{tags=T,
+ cno=[Num |CN],
+ dom=[{Name, Attributes, Content}| D]} = State) ->
+ State#xmerl_sax_simple_dom_state{cno=[Num+1 |CN],
+ dom=[{Name, Attributes, [#xmlText{value=String, parents=T, pos=Num, type=text}|Content]} | D]};
+
+%% Comments
+%%----------------------------------------------------------------------
+build_dom({comment, String},
+ #xmerl_sax_simple_dom_state{tags=T,
+ cno=[Num |CN],
+ dom=[#xmlElement{content=C} = Current| D]} = State) ->
+ State#xmerl_sax_simple_dom_state{cno=[Num+1 |CN],
+ dom=[Current#xmlElement{content=[#xmlComment{parents=T, pos=Num, value=String}|C]} | D]};
+
+%% NameSpaces
+%%----------------------------------------------------------------------
+build_dom({startPrefixMapping, [], _Uri}, State) ->
+ State;
+build_dom({startPrefixMapping, Prefix, Uri},
+ #xmerl_sax_simple_dom_state{namespaces=NS} = State) ->
+ State#xmerl_sax_simple_dom_state{namespaces=[{Prefix, list_to_atom(Uri)} |NS]};
+build_dom({endPrefixMapping, Prefix},
+ #xmerl_sax_simple_dom_state{namespaces=[{Prefix, _} |NS]} = State) ->
+ State#xmerl_sax_simple_dom_state{namespaces=NS};
+
+%% Processing instructions
+%%----------------------------------------------------------------------
+build_dom({processingInstruction,"xml", PiData},
+ #xmerl_sax_simple_dom_state{dom=D} = State) ->
+ {Vsn, PiData1} = find_and_remove_attribute("version", PiData, []),
+ {Enc, PiData2} = find_and_remove_attribute("encoding", PiData1, []),
+ {Standalone, PiData3} = find_and_remove_attribute("standalone", PiData2, yes),
+ State#xmerl_sax_simple_dom_state{dom=[#xmlDecl{vsn=Vsn, encoding=Enc, standalone=Standalone, attributes=PiData3}| D]};
+build_dom({processingInstruction, PiTarget, PiData},
+ #xmerl_sax_simple_dom_state{cno=[Num |CN],
+ dom=[#xmlElement{content=C} = Current| D]} = State) ->
+ State#xmerl_sax_simple_dom_state{cno=[Num+1 |CN],
+ dom=[Current#xmlElement{content=[#xmlPI{name=PiTarget,pos=Num, value=PiData}
+ |C]} | D]};
+
+
+%% Default
+%%----------------------------------------------------------------------
+build_dom(_E, State) ->
+ State.
+
+
+
+
+
+%%----------------------------------------------------------------------
+%% Function : parse_attributes(ElName, Attributes) -> Result
+%% Parameters:
+%% Result :
+%% Description:
+%%----------------------------------------------------------------------
+parse_attributes(ElName, Attributes) ->
+ parse_attributes(ElName, Attributes, 1, []).
+
+parse_attributes(_, [], _, Acc) ->
+ Acc;
+parse_attributes(ElName, [{_Uri, _Prefix, LocalName, AttrValue} |As], N, Acc) ->
+ parse_attributes(ElName, As, N+1, [{list_to_atom(LocalName), AttrValue} |Acc]).
+
+
+
+%%----------------------------------------------------------------------
+%% Function : find_and_remove_attribute(Key, Data, Default) -> Result
+%% Parameters:
+%% Result :
+%% Description:
+%%----------------------------------------------------------------------
+find_and_remove_attribute(Key, Data, Default) ->
+ case lists:keysearch(Key, 1, Data) of
+ {value, {Key, Value}} ->
+ Data2 = lists:keydelete(Key, 1, Data),
+ {Value, Data2};
+ false ->
+ {Default, Data}
+ end.