]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/pxp/pxp/doc/manual/html/x738.html
- the mathql interpreter is not helm-dependent any more
[helm.git] / helm / DEVEL / pxp / pxp / doc / manual / html / x738.html
1 <HTML
2 ><HEAD
3 ><TITLE
4 >Example: An HTML backend for the readme
5 DTD</TITLE
6 ><META
7 NAME="GENERATOR"
8 CONTENT="Modular DocBook HTML Stylesheet Version 1.46"><LINK
9 REL="HOME"
10 TITLE="The PXP user's guide"
11 HREF="index.html"><LINK
12 REL="UP"
13 TITLE="Using PXP"
14 HREF="c533.html"><LINK
15 REL="PREVIOUS"
16 TITLE="Class-based processing of the node tree"
17 HREF="x675.html"><LINK
18 REL="NEXT"
19 TITLE="The objects representing the document"
20 HREF="c893.html"><LINK
21 REL="STYLESHEET"
22 TYPE="text/css"
23 HREF="markup.css"></HEAD
24 ><BODY
25 CLASS="SECT1"
26 BGCOLOR="#FFFFFF"
27 TEXT="#000000"
28 LINK="#0000FF"
29 VLINK="#840084"
30 ALINK="#0000FF"
31 ><DIV
32 CLASS="NAVHEADER"
33 ><TABLE
34 WIDTH="100%"
35 BORDER="0"
36 CELLPADDING="0"
37 CELLSPACING="0"
38 ><TR
39 ><TH
40 COLSPAN="3"
41 ALIGN="center"
42 >The PXP user's guide</TH
43 ></TR
44 ><TR
45 ><TD
46 WIDTH="10%"
47 ALIGN="left"
48 VALIGN="bottom"
49 ><A
50 HREF="x675.html"
51 >Prev</A
52 ></TD
53 ><TD
54 WIDTH="80%"
55 ALIGN="center"
56 VALIGN="bottom"
57 >Chapter 2. Using <SPAN
58 CLASS="ACRONYM"
59 >PXP</SPAN
60 ></TD
61 ><TD
62 WIDTH="10%"
63 ALIGN="right"
64 VALIGN="bottom"
65 ><A
66 HREF="c893.html"
67 >Next</A
68 ></TD
69 ></TR
70 ></TABLE
71 ><HR
72 ALIGN="LEFT"
73 WIDTH="100%"></DIV
74 ><DIV
75 CLASS="SECT1"
76 ><H1
77 CLASS="SECT1"
78 ><A
79 NAME="SECT.README.TO-HTML"
80 >2.4. Example: An HTML backend for the <I
81 CLASS="EMPHASIS"
82 >readme</I
83 >
84 DTD</A
85 ></H1
86 ><P
87 >The converter from <I
88 CLASS="EMPHASIS"
89 >readme</I
90 > documents to HTML
91 documents follows strictly the approach to define one class per element
92 type. The HTML code is similar to the <I
93 CLASS="EMPHASIS"
94 >readme</I
95 > source,
96 because of this most elements can be converted in the following way: Given the
97 input element 
98
99 <PRE
100 CLASS="PROGRAMLISTING"
101 >&#60;e&#62;content&#60;/e&#62;</PRE
102 >
103
104 the conversion text is the concatenation of a computed prefix, the recursively
105 converted content, and a computed suffix. </P
106 ><P
107 >Only one element type cannot be handled by this scheme:
108 <TT
109 CLASS="LITERAL"
110 >footnote</TT
111 >. Footnotes are collected while they are found in
112 the input text, and they are printed after the main text has been converted and
113 printed. </P
114 ><DIV
115 CLASS="SECT2"
116 ><H2
117 CLASS="SECT2"
118 ><A
119 NAME="AEN747"
120 >2.4.1. Header</A
121 ></H2
122 ><P
123 ><PRE
124 CLASS="PROGRAMLISTING"
125 >open Pxp_types
126 open Pxp_document</PRE
127 ></P
128 ></DIV
129 ><DIV
130 CLASS="SECT2"
131 ><H2
132 CLASS="SECT2"
133 ><A
134 NAME="AEN751"
135 >2.4.2. Type declarations</A
136 ></H2
137 ><P
138 ><PRE
139 CLASS="PROGRAMLISTING"
140 >class type footnote_printer =
141   object
142     method footnote_to_html : store_type -&gt; out_channel -&gt; unit
143   end
144
145 and store_type =
146   object
147     method alloc_footnote : footnote_printer -&gt; int
148     method print_footnotes : out_channel -&gt; unit
149   end
150 ;;</PRE
151 ></P
152 ></DIV
153 ><DIV
154 CLASS="SECT2"
155 ><H2
156 CLASS="SECT2"
157 ><A
158 NAME="AEN755"
159 >2.4.3. Class <TT
160 CLASS="LITERAL"
161 >store</TT
162 ></A
163 ></H2
164 ><P
165 >The <TT
166 CLASS="LITERAL"
167 >store</TT
168 > is a container for footnotes. You can add a
169 footnote by invoking <TT
170 CLASS="LITERAL"
171 >alloc_footnote</TT
172 >; the argument is an
173 object of the class <TT
174 CLASS="LITERAL"
175 >footnote_printer</TT
176 >, the method returns the
177 number of the footnote. The interesting property of a footnote is that it can
178 be converted to HTML, so a <TT
179 CLASS="LITERAL"
180 >footnote_printer</TT
181 > is an object
182 with a method <TT
183 CLASS="LITERAL"
184 >footnote_to_html</TT
185 >. The class
186 <TT
187 CLASS="LITERAL"
188 >footnote</TT
189 > which is defined below has a compatible method
190 <TT
191 CLASS="LITERAL"
192 >footnote_to_html</TT
193 > such that objects created from it can be
194 used as <TT
195 CLASS="LITERAL"
196 >footnote_printer</TT
197 >s.</P
198 ><P
199 >The other method, <TT
200 CLASS="LITERAL"
201 >print_footnotes</TT
202 > prints the footnotes as
203 definition list, and is typically invoked after the main material of the page
204 has already been printed. Every item of the list is printed by
205 <TT
206 CLASS="LITERAL"
207 >footnote_to_html</TT
208 >.</P
209 ><P
210 ><PRE
211 CLASS="PROGRAMLISTING"
212 >class store =
213   object (self)
214
215     val mutable footnotes = ( [] : (int * footnote_printer) list )
216     val mutable next_footnote_number = 1
217
218     method alloc_footnote n =
219       let number = next_footnote_number in
220       next_footnote_number &lt;- number+1;
221       footnotes &lt;- footnotes @ [ number, n ];
222       number
223
224     method print_footnotes ch =
225       if footnotes &lt;&gt; [] then begin
226         output_string ch "&lt;hr align=left noshade=noshade width=\"30%\"&gt;\n";
227         output_string ch "&lt;dl&gt;\n";
228         List.iter
229           (fun (_,n) -&gt; 
230              n # footnote_to_html (self : #store_type :&gt; store_type) ch)
231           footnotes;
232         output_string ch "&lt;/dl&gt;\n";
233       end
234
235   end
236 ;;</PRE
237 ></P
238 ></DIV
239 ><DIV
240 CLASS="SECT2"
241 ><H2
242 CLASS="SECT2"
243 ><A
244 NAME="AEN772"
245 >2.4.4. Function <TT
246 CLASS="LITERAL"
247 >escape_html</TT
248 ></A
249 ></H2
250 ><P
251 >This function converts the characters &lt;, &gt;, &amp;, and " to their HTML
252 representation. For example, 
253 <TT
254 CLASS="LITERAL"
255 >escape_html "&lt;&gt;" = "&amp;lt;&amp;gt;"</TT
256 >. Other
257 characters are left unchanged.
258
259 <PRE
260 CLASS="PROGRAMLISTING"
261 >let escape_html s =
262   Str.global_substitute
263     (Str.regexp "&lt;\\|&gt;\\|&amp;\\|\"")
264     (fun s -&gt;
265       match Str.matched_string s with
266         "&lt;" -&gt; "&amp;lt;"
267       | "&gt;" -&gt; "&amp;gt;"
268       | "&amp;" -&gt; "&amp;amp;"
269       | "\"" -&gt; "&amp;quot;"
270       | _ -&gt; assert false)
271     s
272 ;;</PRE
273 ></P
274 ></DIV
275 ><DIV
276 CLASS="SECT2"
277 ><H2
278 CLASS="SECT2"
279 ><A
280 NAME="AEN778"
281 >2.4.5. Virtual class <TT
282 CLASS="LITERAL"
283 >shared</TT
284 ></A
285 ></H2
286 ><P
287 >This virtual class is the abstract superclass of the extension classes shown
288 below. It defines the standard methods <TT
289 CLASS="LITERAL"
290 >clone</TT
291 >,
292 <TT
293 CLASS="LITERAL"
294 >node</TT
295 >, and <TT
296 CLASS="LITERAL"
297 >set_node</TT
298 >, and declares the type
299 of the virtual method <TT
300 CLASS="LITERAL"
301 >to_html</TT
302 >. This method recursively
303 traverses the whole element tree, and prints the converted HTML code to the
304 output channel passed as second argument. The first argument is the reference
305 to the global <TT
306 CLASS="LITERAL"
307 >store</TT
308 > object which collects the footnotes.
309
310 <PRE
311 CLASS="PROGRAMLISTING"
312 >class virtual shared =
313   object (self)
314
315     (* --- default_ext --- *)
316
317     val mutable node = (None : shared node option)
318
319     method clone = {&lt; &gt;} 
320     method node =
321       match node with
322           None -&gt;
323             assert false
324         | Some n -&gt; n
325     method set_node n =
326       node &lt;- Some n
327
328     (* --- virtual --- *)
329
330     method virtual to_html : store -&gt; out_channel -&gt; unit
331
332   end
333 ;;</PRE
334 ></P
335 ></DIV
336 ><DIV
337 CLASS="SECT2"
338 ><H2
339 CLASS="SECT2"
340 ><A
341 NAME="AEN788"
342 >2.4.6. Class <TT
343 CLASS="LITERAL"
344 >only_data</TT
345 ></A
346 ></H2
347 ><P
348 >This class defines <TT
349 CLASS="LITERAL"
350 >to_html</TT
351 > such that the character data of
352 the current node is converted to HTML. Note that <TT
353 CLASS="LITERAL"
354 >self</TT
355 > is an
356 extension object, <TT
357 CLASS="LITERAL"
358 >self # node</TT
359 > is the node object, and
360 <TT
361 CLASS="LITERAL"
362 >self # node # data</TT
363 > returns the character data of the node. 
364
365 <PRE
366 CLASS="PROGRAMLISTING"
367 >class only_data =
368   object (self)
369     inherit shared
370
371     method to_html store ch =
372       output_string ch (escape_html (self # node # data))
373   end
374 ;;</PRE
375 ></P
376 ></DIV
377 ><DIV
378 CLASS="SECT2"
379 ><H2
380 CLASS="SECT2"
381 ><A
382 NAME="AEN797"
383 >2.4.7. Class <TT
384 CLASS="LITERAL"
385 >readme</TT
386 ></A
387 ></H2
388 ><P
389 >This class converts elements of type <TT
390 CLASS="LITERAL"
391 >readme</TT
392 > to HTML. Such an
393 element is (by definition) always the root element of the document. First, the
394 HTML header is printed; the <TT
395 CLASS="LITERAL"
396 >title</TT
397 > attribute of the element
398 determines the title of the HTML page. Some aspects of the HTML page can be
399 configured by setting certain parameter entities, for example the background
400 color, the text color, and link colors. After the header, the
401 <TT
402 CLASS="LITERAL"
403 >body</TT
404 > tag, and the headline have been printed, the contents
405 of the page are converted by invoking <TT
406 CLASS="LITERAL"
407 >to_html</TT
408 > on all
409 children of the current node (which is the root node). Then, the footnotes are
410 appended to this by telling the global <TT
411 CLASS="LITERAL"
412 >store</TT
413 > object to print
414 the footnotes. Finally, the end tags of the HTML pages are printed.</P
415 ><P
416 >This class is an example how to access the value of an attribute: The value is
417 determined by invoking <TT
418 CLASS="LITERAL"
419 >self # node # attribute "title"</TT
420 >. As
421 this attribute has been declared as CDATA and as being required, the value has
422 always the form <TT
423 CLASS="LITERAL"
424 >Value s</TT
425 > where <TT
426 CLASS="LITERAL"
427 >s</TT
428 > is the
429 string value of the attribute. </P
430 ><P
431 >You can also see how entity contents can be accessed. A parameter entity object
432 can be looked up by <TT
433 CLASS="LITERAL"
434 >self # node # dtd # par_entity "name"</TT
435 >,
436 and by invoking <TT
437 CLASS="LITERAL"
438 >replacement_text</TT
439 > the value of the entity
440 is returned after inner parameter and character entities have been
441 processed. Note that you must use <TT
442 CLASS="LITERAL"
443 >gen_entity</TT
444 > instead of
445 <TT
446 CLASS="LITERAL"
447 >par_entity</TT
448 > to access general entities.</P
449 ><P
450 ><PRE
451 CLASS="PROGRAMLISTING"
452 >class readme =
453   object (self)
454     inherit shared
455
456     method to_html store ch =
457       (* output header *)
458       output_string 
459         ch "&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\"&gt;";
460       output_string
461         ch "&lt;!-- WARNING! This is a generated file, do not edit! --&gt;\n";
462       let title = 
463         match self # node # attribute "title" with
464             Value s -&gt; s
465           | _ -&gt; assert false
466       in
467       let html_header, _ =
468         try (self # node # dtd # par_entity "readme:html:header") 
469             # replacement_text
470         with WF_error _ -&gt; "", false in
471       let html_trailer, _ =
472         try (self # node # dtd # par_entity "readme:html:trailer")
473             # replacement_text
474         with WF_error _ -&gt; "", false in
475       let html_bgcolor, _ =
476         try (self # node # dtd # par_entity "readme:html:bgcolor")
477             # replacement_text
478         with WF_error _ -&gt; "white", false in
479       let html_textcolor, _ =
480         try (self # node # dtd # par_entity "readme:html:textcolor")
481             # replacement_text
482         with WF_error _ -&gt; "", false in
483       let html_alinkcolor, _ =
484         try (self # node # dtd # par_entity "readme:html:alinkcolor")
485             # replacement_text
486         with WF_error _ -&gt; "", false in
487       let html_vlinkcolor, _ =
488         try (self # node # dtd # par_entity "readme:html:vlinkcolor")
489             # replacement_text
490         with WF_error _ -&gt; "", false in
491       let html_linkcolor, _ =
492         try (self # node # dtd # par_entity "readme:html:linkcolor")
493             # replacement_text
494         with WF_error _ -&gt; "", false in
495       let html_background, _ =
496         try (self # node # dtd # par_entity "readme:html:background")
497             # replacement_text
498         with WF_error _ -&gt; "", false in
499
500       output_string ch "&lt;html&gt;&lt;header&gt;&lt;title&gt;\n";
501       output_string ch (escape_html title);
502       output_string ch "&lt;/title&gt;&lt;/header&gt;\n";
503       output_string ch "&lt;body ";
504       List.iter
505         (fun (name,value) -&gt;
506            if value &lt;&gt; "" then 
507              output_string ch (name ^ "=\"" ^ escape_html value ^ "\" "))
508         [ "bgcolor",    html_bgcolor;
509           "text",       html_textcolor;
510           "link",       html_linkcolor;
511           "alink",      html_alinkcolor;
512           "vlink",      html_vlinkcolor;
513         ];
514       output_string ch "&gt;\n";
515       output_string ch html_header;
516       output_string ch "&lt;h1&gt;";
517       output_string ch (escape_html title);
518       output_string ch "&lt;/h1&gt;\n";
519       (* process main content: *)
520       List.iter
521         (fun n -&gt; n # extension # to_html store ch)
522         (self # node # sub_nodes);
523       (* now process footnotes *)
524       store # print_footnotes ch;
525       (* trailer *)
526       output_string ch html_trailer;
527       output_string ch "&lt;/html&gt;\n";
528
529   end
530 ;;</PRE
531 ></P
532 ></DIV
533 ><DIV
534 CLASS="SECT2"
535 ><H2
536 CLASS="SECT2"
537 ><A
538 NAME="AEN817"
539 >2.4.8. Classes <TT
540 CLASS="LITERAL"
541 >section</TT
542 >, <TT
543 CLASS="LITERAL"
544 >sect1</TT
545 >,
546 <TT
547 CLASS="LITERAL"
548 >sect2</TT
549 >, and <TT
550 CLASS="LITERAL"
551 >sect3</TT
552 ></A
553 ></H2
554 ><P
555 >As the conversion process is very similar, the conversion classes of the three
556 section levels are derived from the more general <TT
557 CLASS="LITERAL"
558 >section</TT
559 >
560 class. The HTML code of the section levels only differs in the type of the
561 headline, and because of this the classes describing the section levels can be
562 computed by replacing the class argument <TT
563 CLASS="LITERAL"
564 >the_tag</TT
565 > of
566 <TT
567 CLASS="LITERAL"
568 >section</TT
569 > by the HTML name of the headline tag.</P
570 ><P
571 >Section elements are converted to HTML by printing a headline and then
572 converting the contents of the element recursively. More precisely, the first
573 sub-element is always a <TT
574 CLASS="LITERAL"
575 >title</TT
576 > element, and the other
577 elements are the contents of the section. This structure is declared in the
578 DTD, and it is guaranteed that the document matches the DTD. Because of this
579 the title node can be separated from the rest without any checks.</P
580 ><P
581 >Both the title node, and the body nodes are then converted to HTML by calling
582 <TT
583 CLASS="LITERAL"
584 >to_html</TT
585 > on them.</P
586 ><P
587 ><PRE
588 CLASS="PROGRAMLISTING"
589 >class section the_tag =
590   object (self)
591     inherit shared
592
593     val tag = the_tag
594
595     method to_html store ch =
596       let sub_nodes = self # node # sub_nodes in
597       match sub_nodes with
598           title_node :: rest -&gt;
599             output_string ch ("&lt;" ^ tag ^ "&gt;\n");
600             title_node # extension # to_html store ch;
601             output_string ch ("\n&lt;/" ^ tag ^ "&gt;");
602             List.iter
603               (fun n -&gt; n # extension # to_html store ch)
604               rest
605         | _ -&gt;
606             assert false
607   end
608 ;;
609
610 class sect1 = section "h1";;
611 class sect2 = section "h3";;
612 class sect3 = section "h4";;</PRE
613 ></P
614 ></DIV
615 ><DIV
616 CLASS="SECT2"
617 ><H2
618 CLASS="SECT2"
619 ><A
620 NAME="AEN833"
621 >2.4.9. Classes <TT
622 CLASS="LITERAL"
623 >map_tag</TT
624 >, <TT
625 CLASS="LITERAL"
626 >p</TT
627 >,
628 <TT
629 CLASS="LITERAL"
630 >em</TT
631 >, <TT
632 CLASS="LITERAL"
633 >ul</TT
634 >, <TT
635 CLASS="LITERAL"
636 >li</TT
637 ></A
638 ></H2
639 ><P
640 >Several element types are converted to HTML by simply mapping them to
641 corresponding HTML element types. The class <TT
642 CLASS="LITERAL"
643 >map_tag</TT
644 >
645 implements this, and the class argument <TT
646 CLASS="LITERAL"
647 >the_target_tag</TT
648 >
649 determines the tag name to map to. The output consists of the start tag, the
650 recursively converted inner elements, and the end tag.
651
652 <PRE
653 CLASS="PROGRAMLISTING"
654 >class map_tag the_target_tag =
655   object (self)
656     inherit shared
657
658     val target_tag = the_target_tag
659
660     method to_html store ch =
661       output_string ch ("&lt;" ^ target_tag ^ "&gt;\n");
662       List.iter
663         (fun n -&gt; n # extension # to_html store ch)
664         (self # node # sub_nodes);
665       output_string ch ("\n&lt;/" ^ target_tag ^ "&gt;");
666   end
667 ;;
668
669 class p = map_tag "p";;
670 class em = map_tag "b";;
671 class ul = map_tag "ul";;
672 class li = map_tag "li";;</PRE
673 ></P
674 ></DIV
675 ><DIV
676 CLASS="SECT2"
677 ><H2
678 CLASS="SECT2"
679 ><A
680 NAME="AEN844"
681 >2.4.10. Class <TT
682 CLASS="LITERAL"
683 >br</TT
684 ></A
685 ></H2
686 ><P
687 >Element of type <TT
688 CLASS="LITERAL"
689 >br</TT
690 > are mapped to the same HTML type. Note
691 that HTML forbids the end tag of <TT
692 CLASS="LITERAL"
693 >br</TT
694 >.
695
696 <PRE
697 CLASS="PROGRAMLISTING"
698 >class br =
699   object (self)
700     inherit shared
701
702     method to_html store ch =
703       output_string ch "&lt;br&gt;\n";
704       List.iter
705         (fun n -&gt; n # extension # to_html store ch)
706         (self # node # sub_nodes);
707   end
708 ;;</PRE
709 ></P
710 ></DIV
711 ><DIV
712 CLASS="SECT2"
713 ><H2
714 CLASS="SECT2"
715 ><A
716 NAME="AEN851"
717 >2.4.11. Class <TT
718 CLASS="LITERAL"
719 >code</TT
720 ></A
721 ></H2
722 ><P
723 >The <TT
724 CLASS="LITERAL"
725 >code</TT
726 > type is converted to a <TT
727 CLASS="LITERAL"
728 >pre</TT
729 >
730 section (preformatted text). As the meaning of tabs is unspecified in HTML,
731 tabs are expanded to spaces.
732
733 <PRE
734 CLASS="PROGRAMLISTING"
735 >class code =
736   object (self)
737     inherit shared
738
739     method to_html store ch =
740       let data = self # node # data in
741       (* convert tabs *)
742       let l = String.length data in
743       let rec preprocess i column =
744         (* this is very ineffective but comprehensive: *)
745         if i &lt; l then
746           match data.[i] with
747               '\t' -&gt;
748                 let n = 8 - (column mod 8) in
749                 String.make n ' ' ^ preprocess (i+1) (column + n)
750             | '\n' -&gt;
751                 "\n" ^ preprocess (i+1) 0
752             | c -&gt;
753                 String.make 1 c ^ preprocess (i+1) (column + 1)
754         else
755           ""
756       in
757       output_string ch "&lt;p&gt;&lt;pre&gt;";
758       output_string ch (escape_html (preprocess 0 0));
759       output_string ch "&lt;/pre&gt;&lt;/p&gt;";
760
761   end
762 ;;</PRE
763 ></P
764 ></DIV
765 ><DIV
766 CLASS="SECT2"
767 ><H2
768 CLASS="SECT2"
769 ><A
770 NAME="AEN858"
771 >2.4.12. Class <TT
772 CLASS="LITERAL"
773 >a</TT
774 ></A
775 ></H2
776 ><P
777 >Hyperlinks, expressed by the <TT
778 CLASS="LITERAL"
779 >a</TT
780 > element type, are converted
781 to the HTML <TT
782 CLASS="LITERAL"
783 >a</TT
784 > type. If the target of the hyperlink is given
785 by <TT
786 CLASS="LITERAL"
787 >href</TT
788 >, the URL of this attribute can be used
789 directly. Alternatively, the target can be given by
790 <TT
791 CLASS="LITERAL"
792 >readmeref</TT
793 > in which case the ".html" suffix must be added to
794 the file name. </P
795 ><P
796 >Note that within <TT
797 CLASS="LITERAL"
798 >a</TT
799 > only #PCDATA is allowed, so the contents
800 can be converted directly by applying <TT
801 CLASS="LITERAL"
802 >escape_html</TT
803 > to the
804 character data contents.
805
806 <PRE
807 CLASS="PROGRAMLISTING"
808 >class a =
809   object (self)
810     inherit shared
811
812     method to_html store ch =
813       output_string ch "&lt;a ";
814       let href =
815         match self # node # attribute "href" with
816             Value v -&gt; escape_html v
817           | Valuelist _ -&gt; assert false
818           | Implied_value -&gt;
819               begin match self # node # attribute "readmeref" with
820                   Value v -&gt; escape_html v ^ ".html"
821                 | Valuelist _ -&gt; assert false
822                 | Implied_value -&gt;
823                     ""
824               end
825       in
826       if href &lt;&gt; "" then
827         output_string ch ("href=\""  ^ href ^ "\"");
828       output_string ch "&gt;";
829       output_string ch (escape_html (self # node # data));
830       output_string ch "&lt;/a&gt;";
831         
832   end
833 ;;</PRE
834 ></P
835 ></DIV
836 ><DIV
837 CLASS="SECT2"
838 ><H2
839 CLASS="SECT2"
840 ><A
841 NAME="AEN870"
842 >2.4.13. Class <TT
843 CLASS="LITERAL"
844 >footnote</TT
845 ></A
846 ></H2
847 ><P
848 >The <TT
849 CLASS="LITERAL"
850 >footnote</TT
851 > class has two methods:
852 <TT
853 CLASS="LITERAL"
854 >to_html</TT
855 > to convert the footnote reference to HTML, and
856 <TT
857 CLASS="LITERAL"
858 >footnote_to_html</TT
859 > to convert the footnote text itself.</P
860 ><P
861 >The footnote reference is converted to a local hyperlink; more precisely, to
862 two anchor tags which are connected with each other. The text anchor points to
863 the footnote anchor, and the footnote anchor points to the text anchor.</P
864 ><P
865 >The footnote must be allocated in the <TT
866 CLASS="LITERAL"
867 >store</TT
868 > object. By
869 allocating the footnote, you get the number of the footnote, and the text of
870 the footnote is stored until the end of the HTML page is reached when the
871 footnotes can be printed. The <TT
872 CLASS="LITERAL"
873 >to_html</TT
874 > method stores simply
875 the object itself, such that the <TT
876 CLASS="LITERAL"
877 >footnote_to_html</TT
878 > method is
879 invoked on the same object that encountered the footnote.</P
880 ><P
881 >The <TT
882 CLASS="LITERAL"
883 >to_html</TT
884 > only allocates the footnote, and prints the
885 reference anchor, but it does not print nor convert the contents of the
886 note. This is deferred until the footnotes actually get printed, i.e. the
887 recursive call of <TT
888 CLASS="LITERAL"
889 >to_html</TT
890 > on the sub nodes is done by
891 <TT
892 CLASS="LITERAL"
893 >footnote_to_html</TT
894 >. </P
895 ><P
896 >Note that this technique does not work if you make another footnote within a
897 footnote; the second footnote gets allocated but not printed.</P
898 ><P
899 ><PRE
900 CLASS="PROGRAMLISTING"
901 >class footnote =
902   object (self)
903     inherit shared
904
905     val mutable footnote_number = 0
906
907     method to_html store ch =
908       let number = 
909         store # alloc_footnote (self : #shared :&gt; footnote_printer) in
910       let foot_anchor = 
911         "footnote" ^ string_of_int number in
912       let text_anchor =
913         "textnote" ^ string_of_int number in
914       footnote_number &lt;- number;
915       output_string ch ( "&lt;a name=\"" ^ text_anchor ^ "\" href=\"#" ^ 
916                          foot_anchor ^ "\"&gt;[" ^ string_of_int number ^ 
917                          "]&lt;/a&gt;" )
918
919     method footnote_to_html store ch =
920       (* prerequisite: we are in a definition list &lt;dl&gt;...&lt;/dl&gt; *)
921       let foot_anchor = 
922         "footnote" ^ string_of_int footnote_number in
923       let text_anchor =
924         "textnote" ^ string_of_int footnote_number in
925       output_string ch ("&lt;dt&gt;&lt;a name=\"" ^ foot_anchor ^ "\" href=\"#" ^ 
926                         text_anchor ^ "\"&gt;[" ^ string_of_int footnote_number ^ 
927                         "]&lt;/a&gt;&lt;/dt&gt;\n&lt;dd&gt;");
928       List.iter
929         (fun n -&gt; n # extension # to_html store ch)
930         (self # node # sub_nodes);
931       output_string ch ("\n&lt;/dd&gt;")
932  
933   end
934 ;;</PRE
935 ></P
936 ></DIV
937 ><DIV
938 CLASS="SECT2"
939 ><H2
940 CLASS="SECT2"
941 ><A
942 NAME="AEN889"
943 >2.4.14. The specification of the document model</A
944 ></H2
945 ><P
946 >This code sets up the hash table that connects element types with the exemplars
947 of the extension classes that convert the elements to HTML.
948
949 <PRE
950 CLASS="PROGRAMLISTING"
951 >open Pxp_yacc
952
953 let tag_map =
954   make_spec_from_alist
955     ~data_exemplar:(new data_impl (new only_data))
956     ~default_element_exemplar:(new element_impl (new no_markup))
957     ~element_alist:
958       [ "readme", (new element_impl (new readme));
959         "sect1",  (new element_impl (new sect1));
960         "sect2",  (new element_impl (new sect2));
961         "sect3",  (new element_impl (new sect3));
962         "title",  (new element_impl (new no_markup));
963         "p",      (new element_impl (new p));
964         "br",     (new element_impl (new br));
965         "code",   (new element_impl (new code));
966         "em",     (new element_impl (new em));
967         "ul",     (new element_impl (new ul));
968         "li",     (new element_impl (new li));
969         "footnote", (new element_impl (new footnote : #shared :&gt; shared));
970         "a",      (new element_impl (new a));
971       ]
972     ()
973 ;;</PRE
974 ></P
975 ></DIV
976 ></DIV
977 ><DIV
978 CLASS="NAVFOOTER"
979 ><HR
980 ALIGN="LEFT"
981 WIDTH="100%"><TABLE
982 WIDTH="100%"
983 BORDER="0"
984 CELLPADDING="0"
985 CELLSPACING="0"
986 ><TR
987 ><TD
988 WIDTH="33%"
989 ALIGN="left"
990 VALIGN="top"
991 ><A
992 HREF="x675.html"
993 >Prev</A
994 ></TD
995 ><TD
996 WIDTH="34%"
997 ALIGN="center"
998 VALIGN="top"
999 ><A
1000 HREF="index.html"
1001 >Home</A
1002 ></TD
1003 ><TD
1004 WIDTH="33%"
1005 ALIGN="right"
1006 VALIGN="top"
1007 ><A
1008 HREF="c893.html"
1009 >Next</A
1010 ></TD
1011 ></TR
1012 ><TR
1013 ><TD
1014 WIDTH="33%"
1015 ALIGN="left"
1016 VALIGN="top"
1017 >Class-based processing of the node tree</TD
1018 ><TD
1019 WIDTH="34%"
1020 ALIGN="center"
1021 VALIGN="top"
1022 ><A
1023 HREF="c533.html"
1024 >Up</A
1025 ></TD
1026 ><TD
1027 WIDTH="33%"
1028 ALIGN="right"
1029 VALIGN="top"
1030 >The objects representing the document</TD
1031 ></TR
1032 ></TABLE
1033 ></DIV
1034 ></BODY
1035 ></HTML
1036 >