Skip to content

Instantly share code, notes, and snippets.

@ngerakines
Created July 17, 2009 05:26
Show Gist options
  • Select an option

  • Save ngerakines/148903 to your computer and use it in GitHub Desktop.

Select an option

Save ngerakines/148903 to your computer and use it in GitHub Desktop.
-module(sax).
-compile(export_all).
-record(node, {name, attributes = [], content = [], children = [], depth}).
-record(state, {depth = 0, tree = []}).
%% xmerl_sax_parser:file("simple.xml", [{event_fun, fun sax:parser/3}, {event_state, sax:new_state()}]).
new_state() ->
#state{ depth = 0, tree = []}.
parser({startElement, _NS, Name, _, Attributes} = Elem, _, #state{ tree = Tree } = State) ->
%% io:format("'~p'Starting ~p: ~p~n", [State#state.depth, Name, Elem]),
State#state{
tree = [#node{
name = Name,
attributes = [{AttribName, AttribVal} || {_, _, AttribName, AttribVal} <- Attributes],
depth = State#state.depth
} | Tree],
depth = State#state.depth + 1
};
parser({characters, MoreData}, _, #state{ tree = [This | Tree]} = State) ->
State#state{
tree = [ This#node{ content = [MoreData | This#node.content]} | Tree]
};
parser({endElement, _, Name, _} = Elem, _, State) ->
%% io:format("'~p'Ending ~p: ~p~n", [State#state.depth, Name, Elem]),
State#state{
depth = State#state.depth - 1
};
parser(endDocument, _, State) ->
{[Parent | Children], []} = compose_tree(0, lists:reverse(State#state.tree), []),
Parent#node{ children = Children};
parser({ignorableWhitespace, _}, _, State) ->
State;
parser(Other, _, State) ->
%% io:format("'~p' Other ~p~n", [State#state.depth, Other]),
State.
compose_tree(_I, [], Acc) -> {lists:reverse(Acc), []};
compose_tree(Indent, [#node{ depth = Indent } = Node | Rest], Acc) ->
io:format("A '~p' - '~p' ~p~n", [Indent, Node#node.name, length(Acc)]),
io:format("Rest ~p~n", [Rest]),
compose_tree(Indent, Rest, [ Node | Acc ]);
compose_tree(Indent, [ #node{ depth = Ind } = Node | Rest], Acc) when Ind > Indent ->
io:format("B '~p' - '~p' ~p~n", [Ind, Node#node.name, length(Acc)]),
{Tree, Remains} = compose_tree(Ind, Rest, [Node]),
compose_tree(Indent, Remains, [Tree | Acc]);
compose_tree(Indent, [ #node{ depth = Ind } = Node | Rest], Acc) when Ind < Indent ->
io:format("C '~p' - '~p' ~p~n", [Ind, Node#node.name, length(Acc)]),
{lists:reverse(Acc), [Node | Rest]}.
<bodyparts>
<heads/>
<arms>
<hands>
<fingers/>
</hands>
</arms>
<shoulders/>
<knees>
<toes/>
</knees>
</bodyparts>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment