2
%%--------------------------------------------------------------------
5
%% Copyright Ericsson AB 2009. All Rights Reserved.
7
%% The contents of this file are subject to the Erlang Public License,
8
%% Version 1.1, (the "License"); you may not use this file except in
9
%% compliance with the License. You should have received a copy of the
10
%% Erlang Public License along with this software. If not, it can be
11
%% retrieved online at http://www.erlang.org/.
13
%% Software distributed under the License is distributed on an "AS IS"
14
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15
%% the License for the specific language governing rights and limitations
19
%%----------------------------------------------------------------------
20
%% File : xmerl_sax_old_dom.erl
23
%% Created : 02 Oct 2008
24
%%----------------------------------------------------------------------
25
-module(xmerl_sax_old_dom).
27
%%----------------------------------------------------------------------
29
%%----------------------------------------------------------------------
30
-include("xmerl_sax_old_dom.hrl").
32
%%----------------------------------------------------------------------
34
%%----------------------------------------------------------------------
41
%%----------------------------------------------------------------------
43
%%----------------------------------------------------------------------
47
%%======================================================================
49
%%======================================================================
50
%%----------------------------------------------------------------------
52
%%----------------------------------------------------------------------
53
-define(error(Reason),
54
throw({xmerl_sax_old_dom_error, Reason})).
56
%%======================================================================
58
%%======================================================================
60
%%----------------------------------------------------------------------
61
%% State record for the validator
62
%%----------------------------------------------------------------------
63
-record(xmerl_sax_old_dom_state, {
65
cno=[], %% Current node number
66
namespaces = [], %% NameSpace stack
67
dom=[] %% DOM structure
70
%%======================================================================
72
%%======================================================================
73
%%----------------------------------------------------------------------
74
%% Function: initial_state() -> Result
78
%%----------------------------------------------------------------------
80
#xmerl_sax_old_dom_state{}.
82
%%----------------------------------------------------------------------
83
%% Function: get_dom(State) -> Result
87
%%----------------------------------------------------------------------
88
get_dom(#xmerl_sax_old_dom_state{dom=Dom}) ->
91
%%----------------------------------------------------------------------
92
%% Function: event(Event, LineNo, State) -> Result
96
%%----------------------------------------------------------------------
97
event(Event, _LineNo, State) ->
98
build_dom(Event, State).
101
%%======================================================================
102
%% Internal functions
103
%%======================================================================
105
%%----------------------------------------------------------------------
106
%% Function : build_dom(Event, State) -> Result
107
%% Parameters: Event = term()
108
%% State = #xmerl_sax_old_dom_state{}
109
%% Result : #xmerl_sax_old_dom_state{} |
111
%%----------------------------------------------------------------------
114
%%----------------------------------------------------------------------
115
build_dom(startDocument, State) ->
116
State#xmerl_sax_old_dom_state{dom=[startDocument]};
117
build_dom(endDocument,
118
#xmerl_sax_old_dom_state{dom=[#xmlElement{content=C} = Current |D]} = State) ->
121
State#xmerl_sax_old_dom_state{dom=[Current#xmlElement{
122
content=lists:reverse(C)
124
[#xmlDecl{} = Decl, startDocument] ->
125
State#xmerl_sax_old_dom_state{dom=[Decl, Current#xmlElement{
126
content=lists:reverse(C)
129
io:format("~p\n", [D]),
130
?error("we're not at end the document when endDocument event is encountered.")
134
%%----------------------------------------------------------------------
135
build_dom({startElement, Uri, LocalName, QName, Attributes},
136
#xmerl_sax_old_dom_state{tags=T, cno=CN, namespaces=NS, dom=D} = State) ->
138
A = parse_attributes(LocalName, Attributes),
152
NameAsAtom = convert_qname_to_atom(QName),
154
State#xmerl_sax_old_dom_state{tags=[{NameAsAtom, Num} |T],
156
dom=[#xmlElement{name=NameAsAtom,
157
expanded_name=NameAsAtom,
159
namespace=#xmlNamespace{default=list_to_atom(Uri),
163
attributes=lists:reverse(A),
166
build_dom({endElement, _Uri, LocalName, QName},
167
#xmerl_sax_old_dom_state{tags=[_ |T],
169
dom=[#xmlElement{name=CName, content=C} = Current,
170
#xmlElement{content=PC} = Parent | D]} = State) ->
171
case convert_qname_to_atom(QName) of
173
State#xmerl_sax_old_dom_state{tags=T,
175
dom=[Parent#xmlElement{
176
content=[Current#xmlElement{
177
content=lists:reverse(C)
182
?error("Got end of element: " ++ LocalName ++ " but expected: " ++
183
Current#xmlElement.name)
187
%%----------------------------------------------------------------------
188
build_dom({characters, String},
189
#xmerl_sax_old_dom_state{tags=T,
191
dom=[#xmlElement{content=C} = Current| D]} = State) ->
192
State#xmerl_sax_old_dom_state{cno=[Num+1 |CN],
193
dom=[Current#xmlElement{content=[#xmlText{value=String, parents=T, pos=Num, type=text}
195
build_dom({ignorableWhitespace, String},
196
#xmerl_sax_old_dom_state{tags=T,
198
dom=[#xmlElement{content=C} = Current| D]} = State) ->
199
State#xmerl_sax_old_dom_state{cno=[Num+1 |CN],
200
dom=[Current#xmlElement{content=[#xmlText{value=String,
206
%%----------------------------------------------------------------------
207
build_dom({comment, String},
208
#xmerl_sax_old_dom_state{tags=T,
210
dom=[#xmlElement{content=C} = Current| D]} = State) ->
211
State#xmerl_sax_old_dom_state{cno=[Num+1 |CN],
212
dom=[Current#xmlElement{content=[#xmlComment{parents=T, pos=Num, value=String}|C]} | D]};
215
%%----------------------------------------------------------------------
216
build_dom({startPrefixMapping, [], _Uri}, State) ->
218
build_dom({startPrefixMapping, Prefix, Uri},
219
#xmerl_sax_old_dom_state{namespaces=NS} = State) ->
220
State#xmerl_sax_old_dom_state{namespaces=[{Prefix, list_to_atom(Uri)} |NS]};
221
build_dom({endPrefixMapping, Prefix},
222
#xmerl_sax_old_dom_state{namespaces=[{Prefix, _} |NS]} = State) ->
223
State#xmerl_sax_old_dom_state{namespaces=NS};
225
%% Processing instructions
226
%%----------------------------------------------------------------------
227
build_dom({processingInstruction,"xml", PiData},
228
#xmerl_sax_old_dom_state{dom=D} = State) ->
229
{Vsn, PiData1} = find_and_remove_attribute("version", PiData, []),
230
{Enc, PiData2} = find_and_remove_attribute("encoding", PiData1, []),
231
{Standalone, PiData3} = find_and_remove_attribute("standalone", PiData2, yes),
232
State#xmerl_sax_old_dom_state{dom=[#xmlDecl{vsn=Vsn, encoding=Enc, standalone=Standalone, attributes=PiData3}| D]};
233
build_dom({processingInstruction, PiTarget, PiData},
234
#xmerl_sax_old_dom_state{cno=[Num |CN],
235
dom=[#xmlElement{content=C} = Current| D]} = State) ->
236
State#xmerl_sax_old_dom_state{cno=[Num+1 |CN],
237
dom=[Current#xmlElement{content=[#xmlPI{name=PiTarget,pos=Num, value=PiData}
240
%%----------------------------------------------------------------------
241
build_dom(_E, State) ->
245
%%----------------------------------------------------------------------
246
%% Function : parse_attributes(ElName, Attributes) -> Result
250
%%----------------------------------------------------------------------
251
parse_attributes(ElName, Attributes) ->
252
parse_attributes(ElName, Attributes, 1, []).
254
parse_attributes(_, [], _, Acc) ->
256
parse_attributes(ElName, [{_Uri, Prefix, LocalName, AttrValue} |As], N, Acc) ->
257
Name = convert_qname_to_atom({Prefix,LocalName}),
263
parse_attributes(ElName, As, N+1, [#xmlAttribute{name=Name,
267
normalized=false} |Acc]).
269
%%----------------------------------------------------------------------
270
%% Function : convert_qname_to_atom(QName) -> Result
274
%%----------------------------------------------------------------------
275
convert_qname_to_atom({[], N}) ->
277
convert_qname_to_atom({P,N}) ->
278
list_to_atom(P ++ ":" ++ N).
280
%%----------------------------------------------------------------------
281
%% Function : find_and_remove_attribute(Key, Data, Default) -> Result
285
%%----------------------------------------------------------------------
286
find_and_remove_attribute(Key, Data, Default) ->
287
case lists:keysearch(Key, 1, Data) of
288
{value, {Key, Value}} ->
289
Data2 = lists:keydelete(Key, 1, Data),