aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xmerl/src/xmerl_sax_old_dom.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xmerl/src/xmerl_sax_old_dom.erl')
-rw-r--r--lib/xmerl/src/xmerl_sax_old_dom.erl293
1 files changed, 293 insertions, 0 deletions
diff --git a/lib/xmerl/src/xmerl_sax_old_dom.erl b/lib/xmerl/src/xmerl_sax_old_dom.erl
new file mode 100644
index 0000000000..c357816a1e
--- /dev/null
+++ b/lib/xmerl/src/xmerl_sax_old_dom.erl
@@ -0,0 +1,293 @@
+%%-*-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_old_dom.erl
+%% Description :
+%%
+%% Created : 02 Oct 2008
+%%----------------------------------------------------------------------
+-module(xmerl_sax_old_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({xmerl_sax_old_dom_error, Reason})).
+
+%%======================================================================
+%% Records
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% State record for the validator
+%%----------------------------------------------------------------------
+-record(xmerl_sax_old_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_old_dom_state{}.
+
+%%----------------------------------------------------------------------
+%% Function: get_dom(State) -> Result
+%% Parameters:
+%% Result:
+%% Description:
+%%----------------------------------------------------------------------
+get_dom(#xmerl_sax_old_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_old_dom_state{}
+%% Result : #xmerl_sax_old_dom_state{} |
+%% Description:
+%%----------------------------------------------------------------------
+
+%% Document
+%%----------------------------------------------------------------------
+build_dom(startDocument, State) ->
+ State#xmerl_sax_old_dom_state{dom=[startDocument]};
+build_dom(endDocument,
+ #xmerl_sax_old_dom_state{dom=[#xmlElement{content=C} = Current |D]} = State) ->
+ case D of
+ [startDocument] ->
+ State#xmerl_sax_old_dom_state{dom=[Current#xmlElement{
+ content=lists:reverse(C)
+ }]};
+ [#xmlDecl{} = Decl, startDocument] ->
+ State#xmerl_sax_old_dom_state{dom=[Decl, Current#xmlElement{
+ content=lists:reverse(C)
+ }]};
+ _ ->
+ 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_old_dom_state{tags=T, cno=CN, namespaces=NS, dom=D} = State) ->
+
+ A = parse_attributes(LocalName, Attributes),
+ {Num, NewCN} =
+ case CN of
+ [] ->
+ {1, [1]};
+ [ N |CNs] ->
+ {N, [1, N+1 |CNs]}
+ end,
+
+ NsInfo =
+ case QName of
+ {[], _} -> [];
+ QN -> QN
+ end,
+ NameAsAtom = convert_qname_to_atom(QName),
+
+ State#xmerl_sax_old_dom_state{tags=[{NameAsAtom, Num} |T],
+ cno=NewCN,
+ dom=[#xmlElement{name=NameAsAtom,
+ expanded_name=NameAsAtom,
+ nsinfo=NsInfo,
+ namespace=#xmlNamespace{default=list_to_atom(Uri),
+ nodes=NS},
+ pos=Num,
+ parents=T,
+ attributes=lists:reverse(A),
+ xmlbase="."
+ } | D]};
+build_dom({endElement, _Uri, LocalName, QName},
+ #xmerl_sax_old_dom_state{tags=[_ |T],
+ cno=[_ |CN],
+ dom=[#xmlElement{name=CName, content=C} = Current,
+ #xmlElement{content=PC} = Parent | D]} = State) ->
+ case convert_qname_to_atom(QName) of
+ CName ->
+ State#xmerl_sax_old_dom_state{tags=T,
+ cno=CN,
+ dom=[Parent#xmlElement{
+ content=[Current#xmlElement{
+ content=lists:reverse(C)
+ }
+ |PC]
+ } | D]};
+ _ ->
+ ?error("Got end of element: " ++ LocalName ++ " but expected: " ++
+ Current#xmlElement.name)
+ end;
+
+%% Text
+%%----------------------------------------------------------------------
+build_dom({characters, String},
+ #xmerl_sax_old_dom_state{tags=T,
+ cno=[Num |CN],
+ dom=[#xmlElement{content=C} = Current| D]} = State) ->
+ State#xmerl_sax_old_dom_state{cno=[Num+1 |CN],
+ dom=[Current#xmlElement{content=[#xmlText{value=String, parents=T, pos=Num, type=text}
+ |C]} | D]};
+build_dom({ignorableWhitespace, String},
+ #xmerl_sax_old_dom_state{tags=T,
+ cno=[Num |CN],
+ dom=[#xmlElement{content=C} = Current| D]} = State) ->
+ State#xmerl_sax_old_dom_state{cno=[Num+1 |CN],
+ dom=[Current#xmlElement{content=[#xmlText{value=String,
+ parents=T, pos=Num,
+ type=text}
+ |C]} | D]};
+
+%% Comments
+%%----------------------------------------------------------------------
+build_dom({comment, String},
+ #xmerl_sax_old_dom_state{tags=T,
+ cno=[Num |CN],
+ dom=[#xmlElement{content=C} = Current| D]} = State) ->
+ State#xmerl_sax_old_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_old_dom_state{namespaces=NS} = State) ->
+ State#xmerl_sax_old_dom_state{namespaces=[{Prefix, list_to_atom(Uri)} |NS]};
+build_dom({endPrefixMapping, Prefix},
+ #xmerl_sax_old_dom_state{namespaces=[{Prefix, _} |NS]} = State) ->
+ State#xmerl_sax_old_dom_state{namespaces=NS};
+
+%% Processing instructions
+%%----------------------------------------------------------------------
+build_dom({processingInstruction,"xml", PiData},
+ #xmerl_sax_old_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_old_dom_state{dom=[#xmlDecl{vsn=Vsn, encoding=Enc, standalone=Standalone, attributes=PiData3}| D]};
+build_dom({processingInstruction, PiTarget, PiData},
+ #xmerl_sax_old_dom_state{cno=[Num |CN],
+ dom=[#xmlElement{content=C} = Current| D]} = State) ->
+ State#xmerl_sax_old_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) ->
+ Name = convert_qname_to_atom({Prefix,LocalName}),
+ NsInfo =
+ case Prefix of
+ [] -> [];
+ P -> {P,LocalName}
+ end,
+ parse_attributes(ElName, As, N+1, [#xmlAttribute{name=Name,
+ pos=N,
+ nsinfo=NsInfo,
+ value=AttrValue,
+ normalized=false} |Acc]).
+
+%%----------------------------------------------------------------------
+%% Function : convert_qname_to_atom(QName) -> Result
+%% Parameters:
+%% Result :
+%% Description:
+%%----------------------------------------------------------------------
+convert_qname_to_atom({[], N}) ->
+ list_to_atom(N);
+convert_qname_to_atom({P,N}) ->
+ list_to_atom(P ++ ":" ++ N).
+
+%%----------------------------------------------------------------------
+%% 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.