1%%%----------------------------------------------------------------------
2%%% File         : sdocbook2xhtml.erl
3%%% Description  : Erlang XSLT like "stylesheet" for exporting
4%%%                Simplified Docbook XML to XHTML.
5%%%
6%%% Modules used : lists, io_lib, xmerl, xmerl_lib, xmerl_xs
7%%%
8%%%----------------------------------------------------------------------
9
10-module(sdocbook2xhtml).
11-author('mikael.karlsson@creado.com').
12
13
14-include("xmerl.hrl").
15-import(xmerl_lib, [markup/3,mapxml/2, foldxml/3, mapfoldxml/3]).
16-import(xmerl_xs, [ xslapply/2, value_of/1, select/2, built_in_rules/2]).
17
18-export([ process_xml/1 ]).
19
20-export([abbrev/4,
21	 abstract/4,
22	 acronym/4,
23	 address/4,
24	 anchor/4,
25	 appendix/4,
26	 appendixinfo/4,
27	 article/4,
28	 articleinfo/4,
29	 audiodata/4,
30	 audioobject/4,
31	 author/4,
32	 authorgroup/4,
33	 authorinitials/4,
34	 bibliography/4,
35	 bibliomixed/4,
36	 bibliomisc/4,
37	 bibliomset/4,
38	 biblioset/4,
39	 blockquote/4,
40	 caption/4,
41	 citetitle/4,
42	 city/4,
43	 colspec/4,
44	 command/4,
45	 computeroutput/4,
46	 copyright/4,
47	 corpauthor/4,
48	 country/4,
49	 date/4,
50	 edition/4,
51	 editor/4,
52	 email/4,
53	 emphasis/4,
54	 entry/4,
55	 example/4,
56	 fax/4,
57	 figure/4,
58	 filename/4,
59	 firstname/4,
60	 footnote/4,
61	 holder/4,
62	 honorific/4,
63	 imagedata/4,
64	 imageobject/4,
65	 informaltable/4,
66	 inlinemediaobject/4,
67	 isbn/4,
68	 issn/4,
69	 issuenum/4,
70	 legalnotice/4,
71	 lineage/4,
72	 link/4,
73	 literal/4,
74	 itemizedlist/4,
75	 listitem/4,
76	 mediaobject/4,
77	 member/4,
78	 note/4,
79	 orderedlist/4,
80	 othercredit/4,
81	 othername/4,
82	 para/4,
83	 phone/4,
84	 phrase/4,
85	 programlisting/4,
86	 publishername/4,
87	 quote/4,
88	 replaceable/4,
89	 revhistory/4,
90	 revision/4,
91	 revnumber/4,
92	 revremark/4,
93	 row/4,
94	 section/4,
95	 sectioninfo/4,
96	 simplelist/4,
97	 subtitle/4,
98	 surname/4,
99	 systemitem/4,
100	 table/4,
101	 tbody/4,
102	 term/4,
103	 tfoot/4,
104	 tgroup/4,
105	 thead/4,
106	 title/4,
107	 titleabbrev/4,
108	 trademark/4,
109	 ulink/4,
110	 userinput/4,
111	 variablelist/4,
112	 varlistentry/4,
113	 xref/4,
114	 year/4
115	 ]).
116
117
118xmlhead() -> "<\?xml version=\"1.0\" encoding=\"iso-8859-1\"\?>".
119doctype() ->"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
120 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \">\n".
121
122style() ->
123    "<style type=\"text/css\"> body {margin-left:10%; margin-right:5%;} \
124.logo{float:right;}
125.toc UL {
126    list-style-type:     none;
127    border:              solid;
128    border-width:        thin;
129    padding-left:        10px;
130    padding-right:       10px;
131    padding-top:         5px;
132    padding-bottom:      5px;
133    background:          #f0f0f0;
134    letter-spacing:      2px;
135    line-height:         20px;
136}
137</style>".
138
139process_xml(E)->
140%%    lists:flatten(template( E )).
141    template( E ).
142
143%% article is the root element
144template(E0 = #xmlElement{name=article})->
145
146    E = changetitle(E0), %% Add section numbering to titles
147
148    [ xmlhead(), doctype(),
149      "<html xmlns=\"http://www.w3.org/1999/xhtml\" >"
150      "<head>"
151      "<title>",
152      value_of(select("articleinfo/title",E)),
153      "</title>",
154      style(),
155      "</head>"
156     "<body>",
157%%  "<img src=\"/logo.png\" alt=\"no logo\" class=\"logo\" </img>",
158     xslapply( fun template/1, select("articleinfo",E)),
159     process_toc(E), %% Insert toc between info and main part of article
160     xslapply( fun template/1, select("section",E)),
161     xslapply( fun template/1, select("appendix",E)),
162     "</body></html>"];
163
164template(E = #xmlElement{name=Name})->
165    A = xslapply( fun template/1, E),
166    case catch
167	sdocbook2xhtml:Name(A, E#xmlElement.attributes, E#xmlElement.parents,E)
168	of
169	{'EXIT', {undef, _}} ->
170	    A;
171	{'EXIT', Reason} ->
172	    exit(Reason);
173	Res ->
174	    Res
175    end;
176
177template(E) ->
178    built_in_rules( fun template/1, E).
179
180%% -------------------------------------------------------------------
181%% simple serialize tags
182
183abbrev(Data, Attrs, [{bibliomset,_}|_], E)->
184    ["<dt><abbr>", Data, "</abbr></dt><dd>"];
185abbrev(Data, Attrs, Parents, E)->
186    markup("abbr",Attrs, Data).
187
188
189abstract(Data, Attrs, Parents, E)->
190    ["<h3>Abstract</h3><blockquote>", Data, "</blockquote>"].
191
192acronym(Data, Attrs, Parents, E)->
193    markup("acronym",Attrs, Data).
194
195address(Data, Attrs, Parents, E)->
196    markup("address", Attrs, Data).
197
198anchor(Data, Attrs, Parents, E)->
199    case find_attribute(id, Attrs) of
200	{value,ID} ->
201	    ["<a name=\"" ++ ID ++ "\">", Data, "</a>"];
202	false ->
203	    Data
204    end.
205
206appendix(Data, Attrs, Parents, E)->
207    ["<h1>Appendix</h1>", Data].
208
209appendixinfo(Data,_,_,_)->
210    Data.
211
212article(Data, Attrs, Parents, E)->
213    ["<body>"
214     "<img src=\"/logga2.jpg\" alt=\"no logo\" class=\"logo\"
215width=\"50\"</img>",
216     Data,
217     "</body>"].
218
219articleinfo(Data,_,_,_)->
220    Data.
221
222audiodata(Data, Attrs, Parents, E)->Data.
223
224audioobject(_,_,_,_)->
225    [].
226
227author(Data, Attrs, [{authorgroup,_} | _], E)->
228    markup("dd", Attrs, Data);
229author(Data, Attrs, Parents, E)->
230    Data.
231
232authorgroup(Data,_,_,_)->
233    ["<dl><dt>Author</dt>",Data,"</dl>"].
234
235authorinitials(Data,_,_,_)-> Data.
236
237bibliography(Data, Attrs, Parents, E)->
238    ["<h3>Bibliography</h3>" ,Data].
239
240bibliomisc(Data,_,_,_)-> Data.
241bibliomixed(Data,_,_,_)-> ["<dl>",Data, "</dl>"].
242bibliomset(Data,_,_,_)-> [Data, "</dd>"].
243
244biblioset(Data,_,_,_)-> Data.
245
246blockquote(Data, Attrs, Parents, E)->
247    markup("blockquote",Attrs, Data).
248
249caption(Data, Attrs, Parents, E)-> Data.
250
251citetitle(Data,_,_,_)-> ["<i>",Data,"</i>"].
252
253city(Data,_,_,_)->
254	    Data.
255
256%% Fix Me is it "col" element in html?
257colspec(_, Attrs,_,_)->
258    [].
259
260command(Data,_,_,_)->
261    ["<b><tt>", Data, "</tt></b>"].
262
263computeroutput(Data,_,_,_)->
264    ["<tt>", Data, "</tt>"].
265
266copyright(Data,_,_,_)->
267    [ "&copy; ", Data].
268
269corpauthor(Data,_,_,_)->
270    Data.
271
272country(Data,_,_,_)->
273    Data.
274
275date(Data,_,[{revision,_}|_],_)->
276    ["<td>", Data, "</td>"];
277date(Data,_,_,_)->
278    Data.
279
280edition(Data,_,_,_)->
281    Data.
282
283editor(Data,_,_,_)->
284    Data.
285
286email(Data,_,_,_)->
287    ["<i><a href=\"mailto:", Data,"\">",Data,"</a></i>"].
288
289emphasis(Data, Attrs, Parents, E)->
290    ["<em>", Data, "</em>"].
291
292%% Cell in a table
293entry(Data, Attrs, [{row,_}, {thead,_} | _], E)->
294    ["<th>", Data, "</th>"];
295entry(Data, Attrs, Parents, E)->
296    ["<td>", Data, "</td>"].
297
298example(Data, Attrs, Parents, E)->
299    ["<hr />", Data, "<hr />"].
300
301fax(Data, Attrs, Parents, E)->
302    ["<address>", Data, "</address>"].
303
304%% May contain ulink to image, resolved by ulink type
305figure(Data, _, _, _)->
306    Data.
307
308filename(Data, _, _, _)->
309    ["<i>", Data, "</i>"].
310
311firstname(Data, _, _, _)->
312    [Data , " " ].
313
314footnote(Data, _, _, _)->
315    Data.
316
317holder(Data, _, _, _)->
318    [" ",Data].
319
320honorific(Data, _, _, _)->
321    Data.
322
323imagedata(Data, Attrs, Parents, E)->
324    SRC =
325	case find_attribute(fileref, Attrs) of
326	    {value,AS} ->
327		" src=" ++  AS ++ " ";
328	    false ->
329		[]
330	end,
331    ALT =
332	case SRC of
333	    [] ->
334		" alt=\"No image!\" ";
335	    _ ->" alt=\"" ++ SRC ++ "\" "
336	end,
337    WIDTH =
338	case find_attribute(width, Attrs) of
339	    false ->
340		 [];
341	    {value,A} ->" width=" ++ A ++ " "
342	end,
343
344    ["<img " ++ SRC ++ ALT ++ WIDTH ++ "></img>"].
345
346
347imageobject(Data, Attrs, Parents, E)->
348    Data.
349
350informaltable(Data, Attrs, Parents, E)->
351    ["<table border=\"1\" >", Data, "</table>"].
352
353
354inlinemediaobject(Data, Attrs, Parents, E)->
355    Data.
356
357isbn(Data, Attrs, Parents, E)->
358    Data.
359
360issn(Data, Attrs, Parents, E)->
361    Data.
362
363issuenum(Data, Attrs, Parents, E)->
364    Data.
365
366itemizedlist(Data, Attrs, Parents, _)->
367    markup("ul", Attrs, Data).
368
369%keyword
370%{
371%  display: inline;
372%}
373
374%keywordset
375%{
376%  display: inline;
377%}
378
379legalnotice(Data, Attrs, Parents, _)->
380    markup("small", Attrs, Data).
381
382lineage(Data, Attrs, Parents, _)->
383    Data.
384
385%lineannotation
386%{
387%  display: inline;
388%}
389
390% Hypertext link
391link(Data, Attrs, Parents, _)->
392    case find_attribute(linkend, Attrs) of
393	{value,LINK} ->
394	    ["<a href=\"#" ++ LINK ++ "\">", Data, "</a>"];
395	false ->
396	    Data
397    end.
398
399listitem(Data, Attrs, [{varlistentry,_} | _], E) ->
400    markup("dd", Attrs, Data);
401listitem(Data, Attrs, Parents, _)->
402    markup("li", Attrs, Data).
403
404literal(Data, Attrs, Parents, _)->
405    markup("tt", Attrs, Data).
406
407%literallayout
408%{
409%  display: inline;
410%}
411
412mediaobject(Data, Attrs, Parents, _)->
413    Data.
414
415%% simplelist member
416member(Data, Attrs, Parents, _)->
417    [Data,"<br></br>"].
418
419note(Data, Attrs, Parents, _)->
420["<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\" width=\"80%\"
421bgcolor=\"#CCCCCC\"><tr><td>NOTE</td><td><i>", Data, "</i></td></tr></table>"].
422
423%objectinfo
424%{
425%  display: inline;
426%}
427
428%option
429%{
430%  display: inline;
431%}
432
433orderedlist(Data, Attrs, Parents, _)->
434    markup("ol",Attrs,Data).
435
436%% Hmm otheraddr not in DTD
437%otheraddr
438%{
439%  display: inline;
440%}
441
442othercredit(Data, Attrs, Parents, _)->Data.
443
444othername(Data, Attrs, Parents, E)->Data.
445
446%% IGNORE
447%pagenums
448%{
449%  display: inline;
450%}
451
452para(Data, Attrs, [{listitem,_}|_], E)->
453    Data;
454para(Data, Attrs, [{note,_}|_], E)->
455    Data;
456para(Data, Attrs, Parents, E)->
457    markup("p", Attrs, Data).
458
459phone(Data, Attrs, Parents, E)->Data.
460
461phrase(Data, Attrs, Parents, E)->Data.
462
463%pob
464%{
465%  display: inline;
466%}
467
468%postcode
469%{
470%  display: inline;
471%}
472
473%printhistory
474%{
475%  display: inline;
476%}
477
478%procedure
479%{
480%  display: inline;
481%}
482
483programlisting(Data, Attrs, Parents, E)->
484["<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\" width=\"100%\"
485bgcolor=\"#CCCCCC\"><tr><td><pre><code>", Data,
486"</code></pre></td></tr></table>"].
487
488%pubdate
489%{
490%  display: inline;
491%}
492
493%publisher
494%{
495%  display: inline;
496%}
497
498publishername(Data, Attrs, Parents, E)->
499    Data.
500
501quote(Data, Attrs, Parents, _)->
502    markup("q", Attrs, Data).
503
504replaceable(Data, Attrs, Parents,_)->
505    markup("i", Attrs, Data).
506
507revhistory(Data, Attrs, Parents,E)->
508      {A,B,C} = case E#xmlElement.language of
509	      "en" -> {"Revision history","Date","Comment"};
510	      "sv" -> {"Revisionshistoria","Datum","Kommentar"};
511	      _ ->{"lang is undefined","lang is undefined","lang is undefined"}
512	  end,
513
514    ["<h4>",A,"</h4>","<table><thead>"
515    "<tr><th>Rev.</th><th>",B,"</th><th>",C,"</th></tr></thead>", Data,
516    "</table>"].
517
518revision(Data, Attrs, Parents,_)->
519    markup("tr", Attrs, Data).
520
521revnumber(Data, Attrs, Parents,_)->
522    markup("td", Attrs, Data).
523
524revremark(Data, Attrs, Parents,_)->
525    markup("td", Attrs, Data).
526
527row(Data, Attrs, Parents, E)->
528    markup("tr", Attrs, Data).
529
530section(Data, Attrs, Parents, E)->
531    Data.
532
533sectioninfo(Data, Attrs, Parents, E)->Data.
534
535%sidebar
536%{
537%  display: block;
538%}
539
540simplelist(Data, Attrs, Parents, E)->
541    ["<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\"
542width=\"100%\"><tr><td>", Data, "</td></tr></table>"].
543
544
545%state
546%{
547%  display: inline;
548%}
549
550%step
551%{
552%  display: inline;
553%}
554
555%street
556%{
557%  display: inline;
558%}
559
560%substeps
561%{
562%  display: inline;
563%}
564
565subtitle(Data, Attrs, Parents, E)->
566    ["<h3>", Data, "</h3>"].
567
568surname(Data, Attrs, Parents, E)->Data.
569
570systemitem(Data, Attrs, Parents, E)->
571    markup("b", Attrs, Data).
572
573table(Data, Attrs, Parents, E)->
574    ["<table border=\"1\" cellspacing=\"0\" cellpadding=\"4\" >",
575     Data, "</table>"].
576
577%% Fix me alot
578tbody(Data, Attrs, Parents, E)->
579    markup("tbody", Attrs, Data).
580%{
581%  display: table-row-group;
582%}
583
584term(Data, Attrs, [{varlistentry,_} | _], E) ->
585    markup("dt", Attrs, Data).
586
587
588%textobject
589%{
590%  display: inline;
591%}
592
593tfoot(Data, Attrs, Parents, E)->
594    markup("tfoot",Attrs, Data).
595
596%% Fixme alot
597tgroup(Data, Attrs, Parents, E)->
598    markup("colgroup", Attrs, Data).
599%{
600%  display: table;
601%}
602
603thead(Data, Attrs, Parents, E)->
604    markup("thead",Attrs, Data).
605%{
606%  display: table-row-group;
607%}
608
609title(Data, Attrs, Parents, E)->
610%%    io:fwrite("Parents ~p~n", [Parents]),
611    title1(Data, Attrs, Parents, E).
612
613title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
614		    {section,_}, {section,_}, {appendix,_} | _], E) ->
615    ["<h6>", Data, "</h6>"];
616title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
617		    {section,_}, {appendix,_} | _], E) ->
618    ["<h5>", Data, "</h5>"];
619title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
620		    {apendix,_} | _], E) ->
621    ["<h4>", Data, "</h4>"];
622title1(Data, Attrs, [{section,_}, {section,_}, {appendix,_} | _], E) ->
623    ["<h3>", Data, "</h3>"];
624title1(Data, Attrs, [{section,_}, {appendix,_} | _], E) ->
625    ["<h2>", Data,  "</h2>"];
626title1(Data, Attrs, [{appendix,_} | _], E) ->
627    ["<h1>", Data, "</h1>"];
628
629title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
630		    {section,_}, {section,_}, {section,_} | _], E) ->
631    ["<h6>", Data, "</h6>"];
632title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
633		    {section,_}, {section,_} | _], E) ->
634    ["<h6>", Data, "</h6>"];
635title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
636		    {section,_} | _], E) ->
637    ["<h5>", Data, "</h5>"];
638title1(Data, Attrs, [{section,C}, {section,B}, {section,A} | _], E) ->
639    {value, Id} = find_attribute(id,Attrs),
640    ["<h4 id=\"", Id, "\">", Data, "</h4>"];
641title1(Data, Attrs, [{section,B}, {section,A} | _], E) ->
642    {value, Id} = find_attribute(id,Attrs),
643    ["<h3 id=\"", Id, "\">", Data,  "</h3>"];
644title1(Data, Attrs, [{section,A} | _], E) ->
645    {value, Id} = find_attribute(id,Attrs),
646    ["<h2 id=\"", Id, "\">", Data, "</h2>"];
647title1(Data, Attrs, [{articleinfo,_} | _], E) ->
648    ["<h1>", Data, "</h1>"];
649title1(Data, Attrs, [{table,_} | _], E) ->
650    ["<caption>", Data, "</caption>"];
651title1(Data, Attrs, [{bibliomset,_} | _], E) ->
652    ["<i><b>", Data, "</b></i>"];
653title1(Data, Attrs, Parents, E)->
654    ["<h4>", Data, "</h4>"].
655
656titleabbrev(Data, Attrs, Parents, E)->[].
657
658trademark(Data, Attrs, Parents, E)->
659    [ Data, " &reg; "].
660
661ulink(Data, Attrs, Parents, E)->
662    case find_attribute(url, Attrs) of
663	{value,LINK} ->
664	    ["<a href="++ LINK ++ ">", Data, "</a>"];
665	false ->
666	    Data
667    end.
668
669
670%% User input is Constant Bold
671userinput(Data, Attrs, Parents, E)->
672    ["<tt><b>", Data, "</b></tt>"].
673
674variablelist(Data, Attrs, Parents, E)->
675    markup("dl", Attrs, Data).
676
677varlistentry(Data, Attrs, Parents, E)->Data.
678
679%videodata
680%{
681%  display: inline;
682%}
683
684%videoobject
685%{
686%  display: inline;
687%}
688
689%volumenum
690%{
691%  display: inline;
692%}
693
694xref(Data, Attrs, Parents, E)->
695    case find_attribute(linkend, Attrs) of
696	{value,LINK} ->
697	    ["<a href=\"#" ++ LINK ++ "\" />"];
698	false ->
699	    Data
700    end.
701
702year(Data, Attrs, Parents, E)->Data.
703
704%% ----------------------------------------------------------
705%% Utils find_attribute copied from Ulf Wigers xmerl distribution
706
707find_attribute(Name, Attrs) ->
708    case lists:keysearch(Name, #xmlAttribute.name, Attrs) of
709	{value, #xmlAttribute{value = V}} ->
710	    {value, V};
711	false ->
712	    false
713    end.
714%% ------------
715
716changetitle(A) ->
717    Afun = fun changecount/2,
718    {E, Acc} = mapfoldxml(Afun, {0,0,0,0,0,0}, A),
719    E.
720
721changecount(#xmlElement{name=title}=E, {A,B,C,Ex,Fig,Tab})->
722    case E#xmlElement.parents of
723	[{example,_} |_] ->
724	    {addexhead(E,{A,Ex+1}), {A,B,C,Ex+1,Fig,Tab} };
725	[{figure,_} |_] ->
726	    {addfighead(E,{A,Fig+1}), {A,B,C,Ex,Fig+1,Tab} };
727	[{table,_} |_] ->
728	    {addtablehead(E,{A,Tab+1}), {A,B,C,Ex,Fig,Tab+1} };
729	[{section,_},{section,_},{section,_},{article,_} |_] ->
730	    {addheader(E,{A,B,C+1}), {A,B,C+1,Ex,Fig,Tab} };
731	[{section,_},{section,_},{article,_} |_] ->
732	    { addheader(E,{A,B+1,0}), {A,B+1,0,Ex,Fig,Tab} };
733	[{section,_},{article,_} |_] ->
734	    {addheader(E,{A+1,0,0}),{A+1,0,0,0,0,0}};
735	_ ->
736	    {E,{A,B,C,Ex,Fig,Tab}}
737    end;
738changecount(E, Acc)->{E,Acc}.
739
740addexhead(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, {Ch,No})->
741    NewHeader = "Example " ++
742	integer_to_list(Ch)++" - "++ integer_to_list(No) ++
743	" " ++ T1#xmlText.value,
744    E#xmlElement{content=[T1#xmlText{value=NewHeader}]}.
745addfighead(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, {Ch,No})->
746    NewHeader = "Figure " ++
747	integer_to_list(Ch)++" - "++ integer_to_list(No) ++
748	" " ++ T1#xmlText.value,
749    E#xmlElement{content=[T1#xmlText{value=NewHeader}]}.
750addtablehead(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, {Ch,No})->
751    NewHeader = "Table " ++
752	integer_to_list(Ch)++" - "++ integer_to_list(No) ++
753	" " ++ T1#xmlText.value,
754    E#xmlElement{content=[T1#xmlText{value=NewHeader}]}.
755
756addheader(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, Chapters)->
757    NewHeader = chapterstring(Chapters)++ " " ++ T1#xmlText.value,
758    NewAtts = addid(E#xmlElement.attributes, Chapters),
759    E#xmlElement{content=[T1#xmlText{value=NewHeader}],
760		 attributes = NewAtts}.
761
762chapterstring({A,0,0})->integer_to_list(A);
763chapterstring({A,B,0})->integer_to_list(A)++"."++ integer_to_list(B);
764chapterstring({A,B,C})->integer_to_list(A) ++ "." ++
765			    integer_to_list(B) ++ "." ++
766			    integer_to_list(C).
767
768%% addid add id attribute if it not already exists
769addid(OldAtts, Chapters)->
770    case find_attribute(id, OldAtts) of
771	{value,_} ->
772	    OldAtts;
773	false ->
774	    add_attribute(id,"sect_"++ chapterstring(Chapters),
775			  OldAtts)
776    end.
777
778add_attribute(Name, Value, OldAtts)->
779    [#xmlAttribute{ name=Name, value = Value}| OldAtts ].
780
781
782process_toc(E)->
783    AFun = fun chapindex/2,
784    TOCR = foldxml(AFun, [], E),
785%    Str = case find_attribute(lang, E#xmlElement.attributes) of
786%	      {value,"en"} -> "Table of Contents";
787%	      {value,"sv"} -> "Inneh�llsf�rtecking";
788%	      _ ->"lang is undefined"
789%	  end,
790    Str = case E#xmlElement.language of
791	      "en" -> "Table of Contents";
792	      "sv" -> "Inneh�llsf�rtecking";
793	      _ ->"lang is undefined"
794	  end,
795    TOC = ["<div class=\"toc\"><h3>",Str,"</h3><ul>",
796lists:reverse(TOCR), "</ul></div>"].
797
798chapindex(#xmlElement{name=title}=E, Accu)->
799    case E#xmlElement.parents of
800	[{section,_},{section,_},{section,_},{article,_} |_] ->
801	    ["<li>"++spind(3)++ addlink(E,"toc_level_3") ++"</li>"| Accu];
802	[{section,_},{section,_},{article,_} |_] ->
803	    ["<li>"++spind(2)++ addlink(E,"toc_level_2") ++ "</li>"| Accu];
804	[{section,_},{article,_} |_] ->
805	    ["<li>"++spind(1)++ addlink(E,"toc_level_1") ++"</li>"| Accu];
806	_ ->
807	    Accu
808    end;
809chapindex(E, Accu) ->
810    Accu.
811
812spind(0) ->"";
813spind(X)->
814    "&#160;&#160;" ++ spind(X-1).
815
816addlink(E, TocLevel)->
817    {value,LINK} = find_attribute(id,E#xmlElement.attributes),
818    [#xmlText{value=Title}|_] = E#xmlElement.content, %% Pfuii
819    "<a href=\"#" ++ LINK ++
820	"\" class=\"" ++ TocLevel ++ "\">" ++
821    Title ++ "</a>".
822
823
824