1%%%-------------------------------------------------------------------
2%%% File    : motorcycles2html.erl
3%%% Author  : Bertil Karlsson <bertil@localhost.localdomain>
4%%% Description :
5%%%
6%%% Created :  2 Sep 2004 by Bertil Karlsson <bertil@localhost.localdomain>
7%%%-------------------------------------------------------------------
8-module(motorcycles2html).
9
10-include_lib("xmerl/include/xmerl.hrl").
11
12-import(xmerl_xs,
13	[ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).
14
15-export([process_xml/1,process_to_file/2,process_to_file/1]).
16
17process_xml(Doc) ->
18    template(Doc).
19
20process_to_file(FileName) ->
21    process_to_file(FileName,'motorcycles.xml').
22
23process_to_file(FileName,XMLDoc) ->
24    case file:open(FileName,[write]) of
25	{ok,IOF} ->
26	    {XMLContent,_} = xmerl_scan:file(XMLDoc),
27	    TransformedXML=process_xml(XMLContent),
28	    io:format(IOF,"~s",[TransformedXML]),
29	    file:close(IOF);
30	{error,Reason} ->
31	    io:format("could not open file due to ~p.~n",[Reason])
32    end.
33
34%%% templates
35template(E = #xmlElement{name='motorcycles'}) ->
36    [    "<head>\n<title>motorcycles</title>\n</head>\n",
37         "<body>\n",
38	 "<h1>Used Motorcycles</h1>\n",
39	 "<ul>\n",
40	 remove_duplicates(value_of(select("bike/name/manufacturer",E))),
41	 "\n</ul>\n",
42	 sort_by_manufacturer(xslapply(fun template/1, E)),
43         "</body>\n",
44	 "</html>\n"];
45template(E = #xmlElement{name='bike'}) ->
46    {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>",
47    "<dd><ul>\n",
48    "<li style=\"color:green\">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\n",
49    "<li style=\"color:red\">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\n",
50    "<li style=\"color:blue\">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\n",
51    "</ul></dd>\n"]};
52template(E) -> built_in_rules(fun template/1, E).
53
54
55%%%%%%%%%%% helper routines
56
57%% sorts on the bike name element, unwraps the bike information and
58%% inserts a line feed and indentation on each bike element.
59sort_by_manufacturer(L) ->
60    Tuples=[X1||X1={_,_} <- L],
61    SortedTS = lists:keysort(1,Tuples),
62    InsertRefName_UnWrap=
63	fun([{[Name],V}|Rest],Name,F)->
64		[V|F(Rest,Name,F)];
65	   ([{[Name],V}|Rest],_PreviousName,F) ->
66		[["<a name=\"",Name,"\"></>"],V|F(Rest,Name,F)];
67	   ([],_,_) -> []
68	end,
69    SortedRefed=InsertRefName_UnWrap(SortedTS,no_name,InsertRefName_UnWrap),
70%    SortedTs=[Y||{X,Y}<-lists:keysort(1,Tuples)],
71    WS = "\n    ",
72    Fun=fun([H|T],Acc,F)->
73		F(T,[H,WS|Acc],F);
74	   ([],Acc,_F)->
75		lists:reverse([WS|Acc])
76	end,
77    if length(SortedRefed) > 0 ->
78	    Fun(SortedRefed,[],Fun);
79       true -> []
80    end.
81
82
83%% removes all but the first of an element in L and inserts a html
84%% reference for each list element.
85remove_duplicates(L) ->
86    remove_duplicates(L,[]).
87
88remove_duplicates([],Acc) ->
89    make_ref(lists:sort(lists:reverse(Acc)));
90remove_duplicates([A|L],Acc) ->
91    case lists:delete(A,L) of
92	L ->
93	    remove_duplicates(L,[A|Acc]);
94	L1 ->
95	    remove_duplicates([A|L1],[Acc])
96    end.
97
98make_ref([]) -> [];
99make_ref([H]) when is_atom(H) ->
100    "<ul><a href=\"#"++atom_to_list(H)++"\">"++atom_to_list(H)++"</a></ul>";
101make_ref([H]) when is_list(H) ->
102    "<ul><a href=\"#"++H++"\">\s"++H++"</a></ul>";
103make_ref([H|T]) when is_atom(H) ->
104    ["<ul><a href=\"#"++atom_to_list(H)++"\">\s"++atom_to_list(H)++",\n</a></ul>"
105     |make_ref(T)];
106make_ref([H|T]) when is_list(H) ->
107    ["<ul><a href=\"#"++H++"\">\s"++H++",\n</a></ul>"|make_ref(T)].
108