--- /dev/null
+<HTML
+><HEAD
+><TITLE
+>Example: An HTML backend for the readme
+DTD</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.46"><LINK
+REL="HOME"
+TITLE="The PXP user's guide"
+HREF="index.html"><LINK
+REL="UP"
+TITLE="Using PXP"
+HREF="c533.html"><LINK
+REL="PREVIOUS"
+TITLE="Class-based processing of the node tree"
+HREF="x675.html"><LINK
+REL="NEXT"
+TITLE="The objects representing the document"
+HREF="c893.html"><LINK
+REL="STYLESHEET"
+TYPE="text/css"
+HREF="markup.css"></HEAD
+><BODY
+CLASS="SECT1"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><DIV
+CLASS="NAVHEADER"
+><TABLE
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TH
+COLSPAN="3"
+ALIGN="center"
+>The PXP user's guide</TH
+></TR
+><TR
+><TD
+WIDTH="10%"
+ALIGN="left"
+VALIGN="bottom"
+><A
+HREF="x675.html"
+>Prev</A
+></TD
+><TD
+WIDTH="80%"
+ALIGN="center"
+VALIGN="bottom"
+>Chapter 2. Using <SPAN
+CLASS="ACRONYM"
+>PXP</SPAN
+></TD
+><TD
+WIDTH="10%"
+ALIGN="right"
+VALIGN="bottom"
+><A
+HREF="c893.html"
+>Next</A
+></TD
+></TR
+></TABLE
+><HR
+ALIGN="LEFT"
+WIDTH="100%"></DIV
+><DIV
+CLASS="SECT1"
+><H1
+CLASS="SECT1"
+><A
+NAME="SECT.README.TO-HTML"
+>2.4. Example: An HTML backend for the <I
+CLASS="EMPHASIS"
+>readme</I
+>
+DTD</A
+></H1
+><P
+>The converter from <I
+CLASS="EMPHASIS"
+>readme</I
+> documents to HTML
+documents follows strictly the approach to define one class per element
+type. The HTML code is similar to the <I
+CLASS="EMPHASIS"
+>readme</I
+> source,
+because of this most elements can be converted in the following way: Given the
+input element
+
+<PRE
+CLASS="PROGRAMLISTING"
+><e>content</e></PRE
+>
+
+the conversion text is the concatenation of a computed prefix, the recursively
+converted content, and a computed suffix. </P
+><P
+>Only one element type cannot be handled by this scheme:
+<TT
+CLASS="LITERAL"
+>footnote</TT
+>. Footnotes are collected while they are found in
+the input text, and they are printed after the main text has been converted and
+printed. </P
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN747"
+>2.4.1. Header</A
+></H2
+><P
+><PRE
+CLASS="PROGRAMLISTING"
+>open Pxp_types
+open Pxp_document</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN751"
+>2.4.2. Type declarations</A
+></H2
+><P
+><PRE
+CLASS="PROGRAMLISTING"
+>class type footnote_printer =
+ object
+ method footnote_to_html : store_type -> out_channel -> unit
+ end
+
+and store_type =
+ object
+ method alloc_footnote : footnote_printer -> int
+ method print_footnotes : out_channel -> unit
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN755"
+>2.4.3. Class <TT
+CLASS="LITERAL"
+>store</TT
+></A
+></H2
+><P
+>The <TT
+CLASS="LITERAL"
+>store</TT
+> is a container for footnotes. You can add a
+footnote by invoking <TT
+CLASS="LITERAL"
+>alloc_footnote</TT
+>; the argument is an
+object of the class <TT
+CLASS="LITERAL"
+>footnote_printer</TT
+>, the method returns the
+number of the footnote. The interesting property of a footnote is that it can
+be converted to HTML, so a <TT
+CLASS="LITERAL"
+>footnote_printer</TT
+> is an object
+with a method <TT
+CLASS="LITERAL"
+>footnote_to_html</TT
+>. The class
+<TT
+CLASS="LITERAL"
+>footnote</TT
+> which is defined below has a compatible method
+<TT
+CLASS="LITERAL"
+>footnote_to_html</TT
+> such that objects created from it can be
+used as <TT
+CLASS="LITERAL"
+>footnote_printer</TT
+>s.</P
+><P
+>The other method, <TT
+CLASS="LITERAL"
+>print_footnotes</TT
+> prints the footnotes as
+definition list, and is typically invoked after the main material of the page
+has already been printed. Every item of the list is printed by
+<TT
+CLASS="LITERAL"
+>footnote_to_html</TT
+>.</P
+><P
+><PRE
+CLASS="PROGRAMLISTING"
+>class store =
+ object (self)
+
+ val mutable footnotes = ( [] : (int * footnote_printer) list )
+ val mutable next_footnote_number = 1
+
+ method alloc_footnote n =
+ let number = next_footnote_number in
+ next_footnote_number <- number+1;
+ footnotes <- footnotes @ [ number, n ];
+ number
+
+ method print_footnotes ch =
+ if footnotes <> [] then begin
+ output_string ch "<hr align=left noshade=noshade width=\"30%\">\n";
+ output_string ch "<dl>\n";
+ List.iter
+ (fun (_,n) ->
+ n # footnote_to_html (self : #store_type :> store_type) ch)
+ footnotes;
+ output_string ch "</dl>\n";
+ end
+
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN772"
+>2.4.4. Function <TT
+CLASS="LITERAL"
+>escape_html</TT
+></A
+></H2
+><P
+>This function converts the characters <, >, &, and " to their HTML
+representation. For example,
+<TT
+CLASS="LITERAL"
+>escape_html "<>" = "&lt;&gt;"</TT
+>. Other
+characters are left unchanged.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let escape_html s =
+ Str.global_substitute
+ (Str.regexp "<\\|>\\|&\\|\"")
+ (fun s ->
+ match Str.matched_string s with
+ "<" -> "&lt;"
+ | ">" -> "&gt;"
+ | "&" -> "&amp;"
+ | "\"" -> "&quot;"
+ | _ -> assert false)
+ s
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN778"
+>2.4.5. Virtual class <TT
+CLASS="LITERAL"
+>shared</TT
+></A
+></H2
+><P
+>This virtual class is the abstract superclass of the extension classes shown
+below. It defines the standard methods <TT
+CLASS="LITERAL"
+>clone</TT
+>,
+<TT
+CLASS="LITERAL"
+>node</TT
+>, and <TT
+CLASS="LITERAL"
+>set_node</TT
+>, and declares the type
+of the virtual method <TT
+CLASS="LITERAL"
+>to_html</TT
+>. This method recursively
+traverses the whole element tree, and prints the converted HTML code to the
+output channel passed as second argument. The first argument is the reference
+to the global <TT
+CLASS="LITERAL"
+>store</TT
+> object which collects the footnotes.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class virtual shared =
+ object (self)
+
+ (* --- default_ext --- *)
+
+ val mutable node = (None : shared node option)
+
+ method clone = {< >}
+ method node =
+ match node with
+ None ->
+ assert false
+ | Some n -> n
+ method set_node n =
+ node <- Some n
+
+ (* --- virtual --- *)
+
+ method virtual to_html : store -> out_channel -> unit
+
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN788"
+>2.4.6. Class <TT
+CLASS="LITERAL"
+>only_data</TT
+></A
+></H2
+><P
+>This class defines <TT
+CLASS="LITERAL"
+>to_html</TT
+> such that the character data of
+the current node is converted to HTML. Note that <TT
+CLASS="LITERAL"
+>self</TT
+> is an
+extension object, <TT
+CLASS="LITERAL"
+>self # node</TT
+> is the node object, and
+<TT
+CLASS="LITERAL"
+>self # node # data</TT
+> returns the character data of the node.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class only_data =
+ object (self)
+ inherit shared
+
+ method to_html store ch =
+ output_string ch (escape_html (self # node # data))
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN797"
+>2.4.7. Class <TT
+CLASS="LITERAL"
+>readme</TT
+></A
+></H2
+><P
+>This class converts elements of type <TT
+CLASS="LITERAL"
+>readme</TT
+> to HTML. Such an
+element is (by definition) always the root element of the document. First, the
+HTML header is printed; the <TT
+CLASS="LITERAL"
+>title</TT
+> attribute of the element
+determines the title of the HTML page. Some aspects of the HTML page can be
+configured by setting certain parameter entities, for example the background
+color, the text color, and link colors. After the header, the
+<TT
+CLASS="LITERAL"
+>body</TT
+> tag, and the headline have been printed, the contents
+of the page are converted by invoking <TT
+CLASS="LITERAL"
+>to_html</TT
+> on all
+children of the current node (which is the root node). Then, the footnotes are
+appended to this by telling the global <TT
+CLASS="LITERAL"
+>store</TT
+> object to print
+the footnotes. Finally, the end tags of the HTML pages are printed.</P
+><P
+>This class is an example how to access the value of an attribute: The value is
+determined by invoking <TT
+CLASS="LITERAL"
+>self # node # attribute "title"</TT
+>. As
+this attribute has been declared as CDATA and as being required, the value has
+always the form <TT
+CLASS="LITERAL"
+>Value s</TT
+> where <TT
+CLASS="LITERAL"
+>s</TT
+> is the
+string value of the attribute. </P
+><P
+>You can also see how entity contents can be accessed. A parameter entity object
+can be looked up by <TT
+CLASS="LITERAL"
+>self # node # dtd # par_entity "name"</TT
+>,
+and by invoking <TT
+CLASS="LITERAL"
+>replacement_text</TT
+> the value of the entity
+is returned after inner parameter and character entities have been
+processed. Note that you must use <TT
+CLASS="LITERAL"
+>gen_entity</TT
+> instead of
+<TT
+CLASS="LITERAL"
+>par_entity</TT
+> to access general entities.</P
+><P
+><PRE
+CLASS="PROGRAMLISTING"
+>class readme =
+ object (self)
+ inherit shared
+
+ method to_html store ch =
+ (* output header *)
+ output_string
+ ch "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">";
+ output_string
+ ch "<!-- WARNING! This is a generated file, do not edit! -->\n";
+ let title =
+ match self # node # attribute "title" with
+ Value s -> s
+ | _ -> assert false
+ in
+ let html_header, _ =
+ try (self # node # dtd # par_entity "readme:html:header")
+ # replacement_text
+ with WF_error _ -> "", false in
+ let html_trailer, _ =
+ try (self # node # dtd # par_entity "readme:html:trailer")
+ # replacement_text
+ with WF_error _ -> "", false in
+ let html_bgcolor, _ =
+ try (self # node # dtd # par_entity "readme:html:bgcolor")
+ # replacement_text
+ with WF_error _ -> "white", false in
+ let html_textcolor, _ =
+ try (self # node # dtd # par_entity "readme:html:textcolor")
+ # replacement_text
+ with WF_error _ -> "", false in
+ let html_alinkcolor, _ =
+ try (self # node # dtd # par_entity "readme:html:alinkcolor")
+ # replacement_text
+ with WF_error _ -> "", false in
+ let html_vlinkcolor, _ =
+ try (self # node # dtd # par_entity "readme:html:vlinkcolor")
+ # replacement_text
+ with WF_error _ -> "", false in
+ let html_linkcolor, _ =
+ try (self # node # dtd # par_entity "readme:html:linkcolor")
+ # replacement_text
+ with WF_error _ -> "", false in
+ let html_background, _ =
+ try (self # node # dtd # par_entity "readme:html:background")
+ # replacement_text
+ with WF_error _ -> "", false in
+
+ output_string ch "<html><header><title>\n";
+ output_string ch (escape_html title);
+ output_string ch "</title></header>\n";
+ output_string ch "<body ";
+ List.iter
+ (fun (name,value) ->
+ if value <> "" then
+ output_string ch (name ^ "=\"" ^ escape_html value ^ "\" "))
+ [ "bgcolor", html_bgcolor;
+ "text", html_textcolor;
+ "link", html_linkcolor;
+ "alink", html_alinkcolor;
+ "vlink", html_vlinkcolor;
+ ];
+ output_string ch ">\n";
+ output_string ch html_header;
+ output_string ch "<h1>";
+ output_string ch (escape_html title);
+ output_string ch "</h1>\n";
+ (* process main content: *)
+ List.iter
+ (fun n -> n # extension # to_html store ch)
+ (self # node # sub_nodes);
+ (* now process footnotes *)
+ store # print_footnotes ch;
+ (* trailer *)
+ output_string ch html_trailer;
+ output_string ch "</html>\n";
+
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN817"
+>2.4.8. Classes <TT
+CLASS="LITERAL"
+>section</TT
+>, <TT
+CLASS="LITERAL"
+>sect1</TT
+>,
+<TT
+CLASS="LITERAL"
+>sect2</TT
+>, and <TT
+CLASS="LITERAL"
+>sect3</TT
+></A
+></H2
+><P
+>As the conversion process is very similar, the conversion classes of the three
+section levels are derived from the more general <TT
+CLASS="LITERAL"
+>section</TT
+>
+class. The HTML code of the section levels only differs in the type of the
+headline, and because of this the classes describing the section levels can be
+computed by replacing the class argument <TT
+CLASS="LITERAL"
+>the_tag</TT
+> of
+<TT
+CLASS="LITERAL"
+>section</TT
+> by the HTML name of the headline tag.</P
+><P
+>Section elements are converted to HTML by printing a headline and then
+converting the contents of the element recursively. More precisely, the first
+sub-element is always a <TT
+CLASS="LITERAL"
+>title</TT
+> element, and the other
+elements are the contents of the section. This structure is declared in the
+DTD, and it is guaranteed that the document matches the DTD. Because of this
+the title node can be separated from the rest without any checks.</P
+><P
+>Both the title node, and the body nodes are then converted to HTML by calling
+<TT
+CLASS="LITERAL"
+>to_html</TT
+> on them.</P
+><P
+><PRE
+CLASS="PROGRAMLISTING"
+>class section the_tag =
+ object (self)
+ inherit shared
+
+ val tag = the_tag
+
+ method to_html store ch =
+ let sub_nodes = self # node # sub_nodes in
+ match sub_nodes with
+ title_node :: rest ->
+ output_string ch ("<" ^ tag ^ ">\n");
+ title_node # extension # to_html store ch;
+ output_string ch ("\n</" ^ tag ^ ">");
+ List.iter
+ (fun n -> n # extension # to_html store ch)
+ rest
+ | _ ->
+ assert false
+ end
+;;
+
+class sect1 = section "h1";;
+class sect2 = section "h3";;
+class sect3 = section "h4";;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN833"
+>2.4.9. Classes <TT
+CLASS="LITERAL"
+>map_tag</TT
+>, <TT
+CLASS="LITERAL"
+>p</TT
+>,
+<TT
+CLASS="LITERAL"
+>em</TT
+>, <TT
+CLASS="LITERAL"
+>ul</TT
+>, <TT
+CLASS="LITERAL"
+>li</TT
+></A
+></H2
+><P
+>Several element types are converted to HTML by simply mapping them to
+corresponding HTML element types. The class <TT
+CLASS="LITERAL"
+>map_tag</TT
+>
+implements this, and the class argument <TT
+CLASS="LITERAL"
+>the_target_tag</TT
+>
+determines the tag name to map to. The output consists of the start tag, the
+recursively converted inner elements, and the end tag.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class map_tag the_target_tag =
+ object (self)
+ inherit shared
+
+ val target_tag = the_target_tag
+
+ method to_html store ch =
+ output_string ch ("<" ^ target_tag ^ ">\n");
+ List.iter
+ (fun n -> n # extension # to_html store ch)
+ (self # node # sub_nodes);
+ output_string ch ("\n</" ^ target_tag ^ ">");
+ end
+;;
+
+class p = map_tag "p";;
+class em = map_tag "b";;
+class ul = map_tag "ul";;
+class li = map_tag "li";;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN844"
+>2.4.10. Class <TT
+CLASS="LITERAL"
+>br</TT
+></A
+></H2
+><P
+>Element of type <TT
+CLASS="LITERAL"
+>br</TT
+> are mapped to the same HTML type. Note
+that HTML forbids the end tag of <TT
+CLASS="LITERAL"
+>br</TT
+>.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class br =
+ object (self)
+ inherit shared
+
+ method to_html store ch =
+ output_string ch "<br>\n";
+ List.iter
+ (fun n -> n # extension # to_html store ch)
+ (self # node # sub_nodes);
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN851"
+>2.4.11. Class <TT
+CLASS="LITERAL"
+>code</TT
+></A
+></H2
+><P
+>The <TT
+CLASS="LITERAL"
+>code</TT
+> type is converted to a <TT
+CLASS="LITERAL"
+>pre</TT
+>
+section (preformatted text). As the meaning of tabs is unspecified in HTML,
+tabs are expanded to spaces.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class code =
+ object (self)
+ inherit shared
+
+ method to_html store ch =
+ let data = self # node # data in
+ (* convert tabs *)
+ let l = String.length data in
+ let rec preprocess i column =
+ (* this is very ineffective but comprehensive: *)
+ if i < l then
+ match data.[i] with
+ '\t' ->
+ let n = 8 - (column mod 8) in
+ String.make n ' ' ^ preprocess (i+1) (column + n)
+ | '\n' ->
+ "\n" ^ preprocess (i+1) 0
+ | c ->
+ String.make 1 c ^ preprocess (i+1) (column + 1)
+ else
+ ""
+ in
+ output_string ch "<p><pre>";
+ output_string ch (escape_html (preprocess 0 0));
+ output_string ch "</pre></p>";
+
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN858"
+>2.4.12. Class <TT
+CLASS="LITERAL"
+>a</TT
+></A
+></H2
+><P
+>Hyperlinks, expressed by the <TT
+CLASS="LITERAL"
+>a</TT
+> element type, are converted
+to the HTML <TT
+CLASS="LITERAL"
+>a</TT
+> type. If the target of the hyperlink is given
+by <TT
+CLASS="LITERAL"
+>href</TT
+>, the URL of this attribute can be used
+directly. Alternatively, the target can be given by
+<TT
+CLASS="LITERAL"
+>readmeref</TT
+> in which case the ".html" suffix must be added to
+the file name. </P
+><P
+>Note that within <TT
+CLASS="LITERAL"
+>a</TT
+> only #PCDATA is allowed, so the contents
+can be converted directly by applying <TT
+CLASS="LITERAL"
+>escape_html</TT
+> to the
+character data contents.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class a =
+ object (self)
+ inherit shared
+
+ method to_html store ch =
+ output_string ch "<a ";
+ let href =
+ match self # node # attribute "href" with
+ Value v -> escape_html v
+ | Valuelist _ -> assert false
+ | Implied_value ->
+ begin match self # node # attribute "readmeref" with
+ Value v -> escape_html v ^ ".html"
+ | Valuelist _ -> assert false
+ | Implied_value ->
+ ""
+ end
+ in
+ if href <> "" then
+ output_string ch ("href=\"" ^ href ^ "\"");
+ output_string ch ">";
+ output_string ch (escape_html (self # node # data));
+ output_string ch "</a>";
+
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN870"
+>2.4.13. Class <TT
+CLASS="LITERAL"
+>footnote</TT
+></A
+></H2
+><P
+>The <TT
+CLASS="LITERAL"
+>footnote</TT
+> class has two methods:
+<TT
+CLASS="LITERAL"
+>to_html</TT
+> to convert the footnote reference to HTML, and
+<TT
+CLASS="LITERAL"
+>footnote_to_html</TT
+> to convert the footnote text itself.</P
+><P
+>The footnote reference is converted to a local hyperlink; more precisely, to
+two anchor tags which are connected with each other. The text anchor points to
+the footnote anchor, and the footnote anchor points to the text anchor.</P
+><P
+>The footnote must be allocated in the <TT
+CLASS="LITERAL"
+>store</TT
+> object. By
+allocating the footnote, you get the number of the footnote, and the text of
+the footnote is stored until the end of the HTML page is reached when the
+footnotes can be printed. The <TT
+CLASS="LITERAL"
+>to_html</TT
+> method stores simply
+the object itself, such that the <TT
+CLASS="LITERAL"
+>footnote_to_html</TT
+> method is
+invoked on the same object that encountered the footnote.</P
+><P
+>The <TT
+CLASS="LITERAL"
+>to_html</TT
+> only allocates the footnote, and prints the
+reference anchor, but it does not print nor convert the contents of the
+note. This is deferred until the footnotes actually get printed, i.e. the
+recursive call of <TT
+CLASS="LITERAL"
+>to_html</TT
+> on the sub nodes is done by
+<TT
+CLASS="LITERAL"
+>footnote_to_html</TT
+>. </P
+><P
+>Note that this technique does not work if you make another footnote within a
+footnote; the second footnote gets allocated but not printed.</P
+><P
+><PRE
+CLASS="PROGRAMLISTING"
+>class footnote =
+ object (self)
+ inherit shared
+
+ val mutable footnote_number = 0
+
+ method to_html store ch =
+ let number =
+ store # alloc_footnote (self : #shared :> footnote_printer) in
+ let foot_anchor =
+ "footnote" ^ string_of_int number in
+ let text_anchor =
+ "textnote" ^ string_of_int number in
+ footnote_number <- number;
+ output_string ch ( "<a name=\"" ^ text_anchor ^ "\" href=\"#" ^
+ foot_anchor ^ "\">[" ^ string_of_int number ^
+ "]</a>" )
+
+ method footnote_to_html store ch =
+ (* prerequisite: we are in a definition list <dl>...</dl> *)
+ let foot_anchor =
+ "footnote" ^ string_of_int footnote_number in
+ let text_anchor =
+ "textnote" ^ string_of_int footnote_number in
+ output_string ch ("<dt><a name=\"" ^ foot_anchor ^ "\" href=\"#" ^
+ text_anchor ^ "\">[" ^ string_of_int footnote_number ^
+ "]</a></dt>\n<dd>");
+ List.iter
+ (fun n -> n # extension # to_html store ch)
+ (self # node # sub_nodes);
+ output_string ch ("\n</dd>")
+
+ end
+;;</PRE
+></P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN889"
+>2.4.14. The specification of the document model</A
+></H2
+><P
+>This code sets up the hash table that connects element types with the exemplars
+of the extension classes that convert the elements to HTML.
+
+<PRE
+CLASS="PROGRAMLISTING"
+>open Pxp_yacc
+
+let tag_map =
+ make_spec_from_alist
+ ~data_exemplar:(new data_impl (new only_data))
+ ~default_element_exemplar:(new element_impl (new no_markup))
+ ~element_alist:
+ [ "readme", (new element_impl (new readme));
+ "sect1", (new element_impl (new sect1));
+ "sect2", (new element_impl (new sect2));
+ "sect3", (new element_impl (new sect3));
+ "title", (new element_impl (new no_markup));
+ "p", (new element_impl (new p));
+ "br", (new element_impl (new br));
+ "code", (new element_impl (new code));
+ "em", (new element_impl (new em));
+ "ul", (new element_impl (new ul));
+ "li", (new element_impl (new li));
+ "footnote", (new element_impl (new footnote : #shared :> shared));
+ "a", (new element_impl (new a));
+ ]
+ ()
+;;</PRE
+></P
+></DIV
+></DIV
+><DIV
+CLASS="NAVFOOTER"
+><HR
+ALIGN="LEFT"
+WIDTH="100%"><TABLE
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+><A
+HREF="x675.html"
+>Prev</A
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="index.html"
+>Home</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+><A
+HREF="c893.html"
+>Next</A
+></TD
+></TR
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+>Class-based processing of the node tree</TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="c533.html"
+>Up</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+>The objects representing the document</TD
+></TR
+></TABLE
+></DIV
+></BODY
+></HTML
+>
\ No newline at end of file