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 [ "© ", 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, " ® "]. 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 "  " ++ 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