<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <link rel="stylesheet" href="style.css" type="text/css"> <meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"> <link rel="Start" href="index.html"> <link rel="previous" href="Intro_preprocessor.html"> <link rel="Up" href="index.html"> <link title="Index of types" rel=Appendix href="index_types.html"> <link title="Index of exceptions" rel=Appendix href="index_exceptions.html"> <link title="Index of values" rel=Appendix href="index_values.html"> <link title="Index of class methods" rel=Appendix href="index_methods.html"> <link title="Index of classes" rel=Appendix href="index_classes.html"> <link title="Index of class types" rel=Appendix href="index_class_types.html"> <link title="Index of modules" rel=Appendix href="index_modules.html"> <link title="Index of module types" rel=Appendix href="index_module_types.html"> <link title="Pxp_types" rel="Chapter" href="Pxp_types.html"> <link title="Pxp_document" rel="Chapter" href="Pxp_document.html"> <link title="Pxp_dtd" rel="Chapter" href="Pxp_dtd.html"> <link title="Pxp_tree_parser" rel="Chapter" href="Pxp_tree_parser.html"> <link title="Pxp_core_types" rel="Chapter" href="Pxp_core_types.html"> <link title="Pxp_ev_parser" rel="Chapter" href="Pxp_ev_parser.html"> <link title="Pxp_event" rel="Chapter" href="Pxp_event.html"> <link title="Pxp_dtd_parser" rel="Chapter" href="Pxp_dtd_parser.html"> <link title="Pxp_codewriter" rel="Chapter" href="Pxp_codewriter.html"> <link title="Pxp_marshal" rel="Chapter" href="Pxp_marshal.html"> <link title="Pxp_yacc" rel="Chapter" href="Pxp_yacc.html"> <link title="Pxp_reader" rel="Chapter" href="Pxp_reader.html"> <link title="Intro_trees" rel="Chapter" href="Intro_trees.html"> <link title="Intro_extensions" rel="Chapter" href="Intro_extensions.html"> <link title="Intro_namespaces" rel="Chapter" href="Intro_namespaces.html"> <link title="Intro_events" rel="Chapter" href="Intro_events.html"> <link title="Intro_resolution" rel="Chapter" href="Intro_resolution.html"> <link title="Intro_getting_started" rel="Chapter" href="Intro_getting_started.html"> <link title="Intro_advanced" rel="Chapter" href="Intro_advanced.html"> <link title="Intro_preprocessor" rel="Chapter" href="Intro_preprocessor.html"> <link title="Example_readme" rel="Chapter" href="Example_readme.html"><link title="The readme processor" rel="Section" href="#1_Thereadmeprocessor"> <link title="The readme DTD" rel="Subsection" href="#2_ThereadmeDTD"> <link title="The readme converter to HTML" rel="Subsection" href="#2_ThereadmeconvertertoHTML"> <link title="The readme converter to ASCII" rel="Subsection" href="#2_ThereadmeconvertertoASCII"> <link title="The main program" rel="Subsection" href="#2_Themainprogram"> <title>PXP Reference : Example_readme</title> </head> <body> <div class="navbar"><a href="Intro_preprocessor.html">Previous</a> <a href="index.html">Up</a> </div> <center><h1>Example_readme</h1></center> <br> <br> <a name="1_Thereadmeprocessor"></a> <h1>The <code class="code">readme</code> processor</h1> <p> <p> The task of the <code class="code">readme</code> processor is to convert a document conforming to the XML DTD "readme.dtd" into an HTML document or a text document. This example especially demonstrates how to use node extensions to add custom methods to nodes (see <a href="Intro_extensions.html"><code class="code"><span class="constructor">Intro_extensions</span></code></a>), and how to use the object-oriented feature of late binding so that every node type behaves differently. <p> Note that the converter code dates back from 1999. Nowadays I would probably have written it as a purely functional transformer. This task is now left to the reader... <p> <a name="2_ThereadmeDTD"></a> <h2>The <code class="code">readme</code> DTD</h2> <p> The motivation for <code class="code">readme</code> was that I often wrote two versions of files such as README and INSTALL explaining aspects of a distributed software archive; one version was ASCII-formatted, the other was written in HTML. Maintaining both versions meant double amount of work, and changes of one version could be forgotten in the other version. To improve this situation I invented the <code class="code">readme</code> DTD which allows me to maintain only one source written as XML document, and to generate both the ASCII and the HTML version from it <p> In this section, I explain only the DTD. The <code class="code">readme</code> DTD is contained in the PXP distribution together with the two converters to produce ASCII and HTML. <p> The documents have a simple structure: There are up to three levels of nested sections, paragraphs, item lists, footnotes, hyperlinks, and text emphasis. The outermost element has usually the type <code class="code">readme</code>, it is declared by <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> readme (sect1+)><br> <!<span class="constructor">ATTLIST</span> readme<br> title <span class="constructor">CDATA</span> <span class="keywordsign">#</span><span class="constructor">REQUIRED</span>><br> </code><pre></pre> <p> This means that this element contains one or more sections of the first level (element type <code class="code">sect1</code>), and that the element has a required attribute <code class="code">title</code> containing character data (<code class="code"><span class="constructor">CDATA</span></code>). Note that <code class="code">readme</code> elements must not contain text data. <p> The three levels of sections are declared as follows: <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> sect1 (title,(sect2<span class="keywordsign">|</span>p<span class="keywordsign">|</span>ul)+)><br> <br> <!<span class="constructor">ELEMENT</span> sect2 (title,(sect3<span class="keywordsign">|</span>p<span class="keywordsign">|</span>ul)+)><br> <br> <!<span class="constructor">ELEMENT</span> sect3 (title,(p<span class="keywordsign">|</span>ul)+)><br> </code><pre></pre> <p> Every section has a <code class="code">title</code> element as first subelement. After the title an arbitrary but non-empty sequence of inner sections, paragraphs and item lists follows. Note that the inner sections must belong to the next higher section level; <code class="code">sect3</code> elements must not contain inner sections because there is no next higher level. <p> Obviously, all three declarations allow paragraphs (<code class="code">p</code>) and item lists (<code class="code">ul</code>). The definition can be simplified at this point by using a parameter entity: <p> <pre></pre><code class="code"><!<span class="constructor">ENTITY</span> % p.like <span class="string">"p|ul"</span>><br> <br> <!<span class="constructor">ELEMENT</span> sect1 (title,(sect2|%p.like;)+)><br> <br> <!<span class="constructor">ELEMENT</span> sect2 (title,(sect3|%p.like;)+)><br> <br> <!<span class="constructor">ELEMENT</span> sect3 (title,(%p.like;)+)><br> </code><pre></pre> <p> Here, the entity <code class="code">p.like</code> is nothing but a macro abbreviating the same sequence of declarations; if new elements on the same level as <code class="code">p</code> and <code class="code">ul</code> are later added, it is sufficient only to change the entity definition. Note that there are some restrictions on the usage of entities in this context; most important, entities containing a left parenthesis must also contain the corresponding right parenthesis. <p> Note that the entity <code class="code">p.like</code> is a <b>parameter</b> entity, i.e. the <code class="code"><span class="constructor">ENTITY</span></code> declaration contains a percent sign, and the entity is referred to by <code class="code">%p.like;</code>. This kind of entity must be used to abbreviate parts of the DTD; the <b>general</b> entities declared without percent sign and referred to as <code class="code"><span class="keywordsign">&</span>amp;name;</code> are not allowed in this context. <p> The <code class="code">title</code> element specifies the title of the section in which it occurs. The title is given as character data, optionally interspersed with line breaks (<code class="code">br</code>): <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> title (<span class="keywordsign">#</span><span class="constructor">PCDATA</span><span class="keywordsign">|</span>br)*><br> </code><pre></pre> <p> Compared with the <code class="code">title</code> <b>attribute</b> of the <code class="code">readme</code> element, this element allows inner markup (i.e. <code class="code">br</code>) while attribute values do not: It is an error if an attribute value contains the left angle bracket < literally such that it is impossible to include inner elements. <p> The paragraph element <code class="code">p</code> has a structure similar to <code class="code">title</code>, but it allows more inner elements: <p> <pre></pre><code class="code"><!<span class="constructor">ENTITY</span> % text <span class="string">"br|code|em|footnote|a"</span>><br> <br> <!<span class="constructor">ELEMENT</span> p (<span class="keywordsign">#</span><span class="constructor">PCDATA</span>|%text;)*><br> </code><pre></pre> <p> Line breaks do not have inner structure, so they are declared as being empty: <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> br <span class="constructor">EMPTY</span>><br> </code><pre></pre> <p> This means that really nothing is allowed within <code class="code">br</code>; you must always write <code class="code"><br></br></code> or abbreviated <code class="code"><br/></code>. <p> Code samples should be marked up by the <code class="code">code</code> tag; emphasized text can be indicated by <code class="code">em</code>: <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> code (<span class="keywordsign">#</span><span class="constructor">PCDATA</span>)><br> <br> <!<span class="constructor">ELEMENT</span> em (<span class="keywordsign">#</span><span class="constructor">PCDATA</span>|%text;)*><br> </code><pre></pre> <p> That <code class="code">code</code> elements are not allowed to contain further markup while <code class="code">em</code> elements do is a design decision by the author of the DTD. <p> Unordered lists simply consists of one or more list items, and a list item may contain paragraph-level material: <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> ul (li+)><br> <br> <!<span class="constructor">ELEMENT</span> li (%p.like;)*><br> </code><pre></pre> <p> Footnotes are described by the text of the note; this text may contain text-level markup. There is no mechanism to describe the numbering scheme of footnotes, or to specify how footnote references are printed. <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> footnote (<span class="keywordsign">#</span><span class="constructor">PCDATA</span>|%text;)*><br> </code><pre></pre> <p> Hyperlinks are written as in HTML. The anchor tag contains the text describing where the link points to, and the <code class="code">href</code> attribute is the pointer (as URL). There is no way to describe locations of "hash marks". If the link refers to another <code class="code">readme</code> document, the attribute <code class="code">readmeref</code> should be used instead of <code class="code">href</code>. The reason is that the converted document has usually a different system identifier (file name), and the link to a converted document must be converted, too. <p> <pre></pre><code class="code"><!<span class="constructor">ELEMENT</span> a (<span class="keywordsign">#</span><span class="constructor">PCDATA</span>)*><br> <!<span class="constructor">ATTLIST</span> a <br> href <span class="constructor">CDATA</span> <span class="keywordsign">#</span><span class="constructor">IMPLIED</span><br> readmeref <span class="constructor">CDATA</span> <span class="keywordsign">#</span><span class="constructor">IMPLIED</span><br> ><br> </code><pre></pre> <p> Note that although it is only sensible to specify one of the two attributes, the DTD has no means to express this restriction. <p> So far the DTD. Finally, here is a sample document for it: <p> <pre></pre><code class="code"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"ISO-8859-1"</span><span class="keywordsign">?></span><br> <!<span class="constructor">DOCTYPE</span> readme <span class="constructor">SYSTEM</span> <span class="string">"readme.dtd"</span>><br> <readme title=<span class="string">"How to use the readme converters"</span>><br> <sect1><br> <title><span class="constructor">Usage</span></title><br> <p><br> <span class="constructor">The</span> <em>readme</em> converter is invoked on the command line by:<br> </p><br> <p><br> <code>readme [ -text <span class="keywordsign">|</span> -html ] input.xml</code><br> </p><br> <p><br> <span class="constructor">Here</span> is a list <span class="keyword">of</span> options:<br> </p><br> <ul><br> <li><br> <p><br> <code>-text</code>: <br> specifies that <span class="constructor">ASCII</span> output should be produced</p><br> </li><br> <li><br> <p><br> <code>-html</code>: <br> specifies that <span class="constructor">HTML</span> output should be produced</p><br> </li><br> </ul><br> <p><br> <span class="constructor">The</span> input file must be given on the command line. <span class="constructor">The</span> converted output is<br> printed <span class="keyword">to</span> <em>stdout</em>.<br> </p><br> </sect1><br> <sect1><br> <title><span class="constructor">Author</span></title><br> <p><br> <span class="constructor">The</span> program has been written by<br> <a href=<span class="string">"mailto:gerd@gerd-stolpmann.de"</span>><span class="constructor">Gerd</span> <span class="constructor">Stolpmann</span></a>.<br> </p><br> </sect1><br> </readme><br> </code><pre></pre> <p> <a name="2_ThereadmeconvertertoHTML"></a> <h2>The <code class="code">readme</code> converter to HTML</h2> <p> The converter from <code class="code">readme</code> documents to HTML documents follows strictly the approach to define one extension class per element type. The generated HTML code is structurally similar to the <code class="code">readme</code> source, because of this most elements can be converted in the following straigh-forward way: Given the input element <p> <code class="code"><e>content</e></code> <p> the conversion text is the concatenation of a computed prefix, the recursively converted content, and a computed suffix. <p> Only one element type cannot be handled by this scheme: <code class="code">footnote</code>. 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> Now we comment to source code of the <code class="code">to_html.ml</code> converter. <p> <a name="3_Header"></a> <h3>Header</h3> <p> <pre></pre><code class="code"><span class="keyword">open</span> <span class="constructor">Pxp_types</span><br> <span class="keyword">open</span> <span class="constructor">Pxp_document</span><br> <span class="keyword">open</span> <span class="constructor">Pxp_dtd</span>.<span class="constructor">Entity</span><br> </code><pre></pre> <p> <a name="3_Typedeclarations"></a> <h3>Type declarations</h3> <p> <pre></pre><code class="code"><span class="keyword">class</span> <span class="keyword">type</span> footnote_printer =<br> <span class="keyword">object</span><br> <span class="keyword">method</span> footnote_to_html : store_type <span class="keywordsign">-></span> out_channel <span class="keywordsign">-></span> unit<br> <span class="keyword">end</span><br> <br> <span class="keyword">and</span> store_type =<br> <span class="keyword">object</span><br> <span class="keyword">method</span> alloc_footnote : footnote_printer <span class="keywordsign">-></span> int<br> <span class="keyword">method</span> print_footnotes : out_channel <span class="keywordsign">-></span> unit<br> <span class="keyword">end</span><br> </code><pre></pre> <p> For comments see the implementations below. <p> <a name="3_Theclassstoreoftypestoretype"></a> <h3>The class <code class="code">store</code> of type <code class="code">store_type</code> </h3> <p> The <code class="code">store</code> is a container for footnotes. You can add a footnote by invoking <code class="code">alloc_footnote</code>; the argument is an object of the class <code class="code">footnote_printer</code>, the method returns the number of the footnote. The interesting property of a footnote is that it can be converted to HTML, so a <code class="code">footnote_printer</code> is an object with a method <code class="code">footnote_to_html</code>. The class <code class="code">footnote</code> which is defined below has a compatible method <code class="code">footnote_to_html</code> such that objects created from it can be used as <code class="code">footnote_printer</code>s. <p> The other method, <code class="code">print_footnotes</code> 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 <code class="code">footnote_to_html</code>. <p> <pre></pre><code class="code"><span class="keyword">class</span> store =<br> <span class="keyword">object</span> (self)<br> <br> <span class="keyword">val</span> <span class="keyword">mutable</span> footnotes = ( [] : (int * footnote_printer) list )<br> <span class="keyword">val</span> <span class="keyword">mutable</span> next_footnote_number = 1<br> <br> <span class="keyword">method</span> alloc_footnote n =<br> <span class="keyword">let</span> number = next_footnote_number <span class="keyword">in</span><br> next_footnote_number <- number+1;<br> footnotes <- footnotes @ [ number, n ];<br> number<br> <br> <span class="keyword">method</span> print_footnotes ch =<br> <span class="keyword">if</span> footnotes <> [] <span class="keyword">then</span> <span class="keyword">begin</span><br> output_string ch <span class="string">"<hr align=left noshade=noshade width=\"30%\">\n"</span>;<br> output_string ch <span class="string">"<dl>\n"</span>;<br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> (_,n) <span class="keywordsign">-></span> <br> n <span class="keywordsign">#</span> footnote_to_html (self : <span class="keywordsign">#</span>store_type :> store_type) ch)<br> footnotes;<br> output_string ch <span class="string">"</dl>\n"</span>;<br> <span class="keyword">end</span><br> <br> <span class="keyword">end</span><br> </code><pre></pre> <p> <a name="3_Thefunctionescapehtml"></a> <h3>The function <code class="code">escape_html</code></h3> <p> This function converts the characters <, >, &, and " to their HTML representations. For example, <p> <pre></pre><code class="code"> escape_html <span class="string">"<>"</span> = <span class="string">"&lt;&gt;"</span> </code><pre></pre> <p> Other characters are left unchanged. <p> <pre></pre><code class="code"><span class="keyword">let</span> escape_html s =<br> <span class="constructor">Str</span>.global_substitute<br> (<span class="constructor">Str</span>.regexp <span class="string">"<\\|>\\|&\\|\"\\|@\\|:"</span>)<br> (<span class="keyword">fun</span> s <span class="keywordsign">-></span><br> <span class="keyword">match</span> <span class="constructor">Str</span>.matched_string s <span class="keyword">with</span><br> <span class="string">"<"</span> <span class="keywordsign">-></span> <span class="string">"&lt;"</span><br> <span class="keywordsign">|</span> <span class="string">">"</span> <span class="keywordsign">-></span> <span class="string">"&gt;"</span><br> <span class="keywordsign">|</span> <span class="string">"&"</span> <span class="keywordsign">-></span> <span class="string">"&amp;"</span><br> <span class="keywordsign">|</span> <span class="string">"\""</span> <span class="keywordsign">-></span> <span class="string">"&quot;"</span><br> <span class="keywordsign">|</span> <span class="string">"@"</span> <span class="keywordsign">-></span> <span class="string">"&#64;"</span><br> <span class="keywordsign">|</span> <span class="string">":"</span> <span class="keywordsign">-></span> <span class="string">"&#58;"</span><br> <span class="keywordsign">|</span> _ <span class="keywordsign">-></span> <span class="keyword">assert</span> <span class="keyword">false</span>)<br> s<br> </code><pre></pre> <p> Note (of 2009): There is also the Ocamlnet function <code class="code"><span class="constructor">Netencoding</span>.<span class="constructor">Html</span>.encode</code> one can use. It has a special XML mode. <p> <a name="3_Thevirtualclassshared"></a> <h3>The virtual class <code class="code">shared</code></h3> <p> This virtual class is the abstract superclass of the extension classes shown below. It defines the standard methods <code class="code">clone</code>, <code class="code">node</code>, and <code class="code">set_node</code>, and declares the type of the virtual method <code class="code">to_html</code>. 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 <code class="code">store</code> object which collects the footnotes. <p> <pre></pre><code class="code"><span class="keyword">class</span> <span class="keyword">virtual</span> shared =<br> <span class="keyword">object</span> (self)<br> <br> <span class="comment">(* --- default_ext --- *)</span><br> <br> <span class="keyword">val</span> <span class="keyword">mutable</span> node = (<span class="constructor">None</span> : shared node option)<br> <br> <span class="keyword">method</span> clone = {< >} <br> <span class="keyword">method</span> node =<br> <span class="keyword">match</span> node <span class="keyword">with</span><br> <span class="constructor">None</span> <span class="keywordsign">-></span><br> <span class="keyword">assert</span> <span class="keyword">false</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> n <span class="keywordsign">-></span> n<br> <span class="keyword">method</span> set_node n =<br> node <- <span class="constructor">Some</span> n<br> <br> <span class="comment">(* --- virtual --- *)</span><br> <br> <span class="keyword">method</span> <span class="keyword">virtual</span> to_html : store <span class="keywordsign">-></span> out_channel <span class="keywordsign">-></span> unit<br> <br> <span class="keyword">end</span><br> </code><pre></pre> <p> For an introduction into extension classes see <a href="Intro_extensions.html"><code class="code"><span class="constructor">Intro_extensions</span></code></a>. <p> <a name="3_Theclassonlydata"></a> <h3>The class <code class="code">only_data</code></h3> <p> This class defines <code class="code">to_html</code> such that the character data of the current node is converted to HTML. Note that <code class="code">self</code> is an extension object (of type <a href="Pxp_document.extension.html"><code class="code"><span class="constructor">Pxp_document</span>.extension</code></a>), <code class="code">self <span class="keywordsign">#</span> node</code> is the node object (of type <a href="Pxp_document.node.html"><code class="code"><span class="constructor">Pxp_document</span>.node</code></a>), and <code class="code">self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> data</code> returns the character data of the node (see <a href="Pxp_document.node.html#METHODdata"><code class="code"><span class="constructor">Pxp_document</span>.node.data</code></a>). <p> <pre></pre><code class="code"><span class="keyword">class</span> only_data =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">method</span> to_html store ch =<br> output_string ch (escape_html (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> data))<br> <span class="keyword">end</span><br> </code><pre></pre> <p> <a name="3_Theclassreadme"></a> <h3>The class <code class="code">readme</code></h3> <p> This class converts elements of type <code class="code">readme</code> to HTML. Such an element is (by definition) always the root element of the document. First, the HTML header is printed; the <code class="code">title</code> 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 <code class="code">body</code> tag, and the headline have been printed, the contents of the page are converted by invoking <code class="code">to_html</code> on all children of the current node (which is the root node). Then, the footnotes are appended to this by telling the global <code class="code">store</code> object to print the footnotes. Finally, the end tags of the HTML pages are printed. <p> <pre></pre><code class="code"><span class="keyword">class</span> readme =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">method</span> to_html store ch =<br> <span class="comment">(* output header *)</span><br> output_string <br> ch <span class="string">"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">"</span>;<br> output_string<br> ch <span class="string">"<!-- WARNING! This is a generated file, do not edit! -->\n"</span>;<br> <span class="keyword">let</span> title = <br> <span class="keyword">match</span> self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> attribute <span class="string">"title"</span> <span class="keyword">with</span><br> <span class="constructor">Value</span> s <span class="keywordsign">-></span> s<br> <span class="keywordsign">|</span> _ <span class="keywordsign">-></span> <span class="keyword">assert</span> <span class="keyword">false</span><br> <span class="keyword">in</span><br> <span class="keyword">let</span> html_header =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:header"</span>) <br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_trailer =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:trailer"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_bgcolor =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:bgcolor"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">"white"</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_textcolor =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:textcolor"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_alinkcolor =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:alinkcolor"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_vlinkcolor =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:vlinkcolor"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_linkcolor =<br> <span class="keyword">try</span> replacement_text <br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:linkcolor"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> html_background =<br> <span class="keyword">try</span> replacement_text<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"readme:html:background"</span>)<br> <span class="keyword">with</span> <span class="constructor">WF_error</span> _ <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <br> output_string ch <span class="string">"<html><header><title>\n"</span>;<br> output_string ch (escape_html title);<br> output_string ch <span class="string">"</title></header>\n"</span>;<br> output_string ch <span class="string">"<body "</span>;<br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> (name,value) <span class="keywordsign">-></span><br> <span class="keyword">if</span> value <> <span class="string">""</span> <span class="keyword">then</span> <br> output_string ch (name ^ <span class="string">"=\""</span> ^ escape_html value ^ <span class="string">"\" "</span>))<br> [ <span class="string">"bgcolor"</span>, html_bgcolor;<br> <span class="string">"text"</span>, html_textcolor;<br> <span class="string">"link"</span>, html_linkcolor;<br> <span class="string">"alink"</span>, html_alinkcolor;<br> <span class="string">"vlink"</span>, html_vlinkcolor;<br> ];<br> output_string ch <span class="string">">\n"</span>;<br> output_string ch html_header;<br> output_string ch <span class="string">"<h1>"</span>;<br> output_string ch (escape_html title);<br> output_string ch <span class="string">"</h1>\n"</span>;<br> <span class="comment">(* process main content: *)</span><br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> n <span class="keywordsign">-></span> n <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store ch)<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> sub_nodes);<br> <span class="comment">(* now process footnotes *)</span><br> store <span class="keywordsign">#</span> print_footnotes ch;<br> <span class="comment">(* trailer *)</span><br> output_string ch html_trailer;<br> output_string ch <span class="string">"</html>\n"</span>;<br> <span class="keyword">end</span><br> </code><pre></pre> <p> This class is an example how to access the value of an attribute: The value is determined by invoking <code class="code">self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> attribute <span class="string">"title"</span></code> (see <a href="Pxp_document.node.html#METHODattribute"><code class="code"><span class="constructor">Pxp_document</span>.node.attribute</code></a>). As this attribute has been declared as CDATA and as being required, the value has always the form <code class="code"><span class="constructor">Value</span> s</code> where <code class="code">s</code> is the string value of the attribute. Attribute values have type <a href="Pxp_types.html#TYPEatt_value"><code class="code"><span class="constructor">Pxp_types</span>.att_value</code></a>. <p> You can also see how entity contents can be accessed. A parameter entity object can be looked up by <code class="code">self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> dtd <span class="keywordsign">#</span> par_entity <span class="string">"name"</span></code> (see <a href="Pxp_dtd.dtd.html#METHODpar_entity"><code class="code"><span class="constructor">Pxp_dtd</span>.dtd.par_entity</code></a>), and by invoking <a href="Pxp_dtd.Entity.html#VALreplacement_text"><code class="code"><span class="constructor">Pxp_dtd</span>.<span class="constructor">Entity</span>.replacement_text</code></a> the value of the entity is returned after inner parameter and character entities have been processed. Note that you must use <a href="Pxp_dtd.dtd.html#METHODgen_entity"><code class="code"><span class="constructor">Pxp_dtd</span>.dtd.gen_entity</code></a> instead of <code class="code">par_entity</code> to access general entities. <p> <a name="3_Theclassessectionsect1sect2andsect3"></a> <h3>The classes <code class="code">section</code>, <code class="code">sect1</code>, <code class="code">sect2</code>, and <code class="code">sect3</code></h3> <p> As the conversion process is very similar, the conversion classes of the three section levels are derived from the more general <code class="code">section</code> 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 <code class="code">the_tag</code> of <code class="code">section</code> by the HTML name of the headline tag. <p> <pre></pre><code class="code"><span class="keyword">class</span> section the_tag =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">val</span> tag = the_tag<br> <br> <span class="keyword">method</span> to_html store ch =<br> <span class="keyword">let</span> sub_nodes = self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> sub_nodes <span class="keyword">in</span><br> <span class="keyword">match</span> sub_nodes <span class="keyword">with</span><br> title_node :: rest <span class="keywordsign">-></span><br> output_string ch (<span class="string">"<"</span> ^ tag ^ <span class="string">">\n"</span>);<br> title_node <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store ch;<br> output_string ch (<span class="string">"\n</"</span> ^ tag ^ <span class="string">">"</span>);<br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> n <span class="keywordsign">-></span> n <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store ch)<br> rest<br> <span class="keywordsign">|</span> _ <span class="keywordsign">-></span><br> <span class="keyword">assert</span> <span class="keyword">false</span><br> <span class="keyword">end</span><br> <br> <span class="keyword">class</span> sect1 = section <span class="string">"h1"</span><br> <span class="keyword">class</span> sect2 = section <span class="string">"h3"</span><br> <span class="keyword">class</span> sect3 = section <span class="string">"h4"</span><br> </code><pre></pre> <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 <code class="code">title</code> 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> Both the title node, and the body nodes are then converted to HTML by calling <code class="code">to_html</code> on them. <p> <a name="3_Theclassesmaptagpemulandli"></a> <h3>The classes <code class="code">map_tag</code>, <code class="code">p</code>, <code class="code">em</code>, <code class="code">ul</code>, and <code class="code">li</code> </h3> <p> Several element types are converted to HTML by simply mapping them to corresponding HTML element types. The class <code class="code">map_tag</code> implements this, and the class argument <code class="code">the_target_tag</code> determines the tag name to map to. The output consists of the start tag, the recursively converted inner elements, and the end tag. <p> <pre></pre><code class="code"><span class="keyword">class</span> map_tag the_target_tag =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">val</span> target_tag = the_target_tag<br> <br> <span class="keyword">method</span> to_html store ch =<br> output_string ch (<span class="string">"<"</span> ^ target_tag ^ <span class="string">">\n"</span>);<br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> n <span class="keywordsign">-></span> n <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store ch)<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> sub_nodes);<br> output_string ch (<span class="string">"\n</"</span> ^ target_tag ^ <span class="string">">"</span>);<br> <span class="keyword">end</span><br> <br> <span class="keyword">class</span> p = map_tag <span class="string">"p"</span><br> <span class="keyword">class</span> em = map_tag <span class="string">"b"</span><br> <span class="keyword">class</span> ul = map_tag <span class="string">"ul"</span><br> <span class="keyword">class</span> li = map_tag <span class="string">"li"</span><br> </code><pre></pre> <p> <a name="3_Theclassbr"></a> <h3>The class <code class="code">br</code></h3> <p> Element of type <code class="code">br</code> are mapped to the same HTML type. Note that HTML forbids the end tag of <code class="code">br</code>. <p> <pre></pre><code class="code"><span class="keyword">class</span> br =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">method</span> to_html store ch =<br> output_string ch <span class="string">"<br>\n"</span>;<br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> n <span class="keywordsign">-></span> n <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store ch)<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> sub_nodes);<br> <span class="keyword">end</span><br> </code><pre></pre> <p> <a name="3_Theclasscode"></a> <h3>The class <code class="code">code</code></h3> <p> The <code class="code">code</code> type is converted to a <code class="code">pre</code> section (preformatted text). As the meaning of tabs is unspecified in HTML, tabs are expanded to spaces. <p> <pre></pre><code class="code"><span class="keyword">class</span> code =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">method</span> to_html store ch =<br> <span class="keyword">let</span> data = self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> data <span class="keyword">in</span><br> <span class="comment">(* convert tabs *)</span><br> <span class="keyword">let</span> l = <span class="constructor">String</span>.length data <span class="keyword">in</span><br> <span class="keyword">let</span> <span class="keyword">rec</span> preprocess i column =<br> <span class="comment">(* this is very ineffective but comprehensible: *)</span><br> <span class="keyword">if</span> i < l <span class="keyword">then</span><br> <span class="keyword">match</span> data.[i] <span class="keyword">with</span><br> <span class="string">'\t'</span> <span class="keywordsign">-></span><br> <span class="keyword">let</span> n = 8 - (column <span class="keyword">mod</span> 8) <span class="keyword">in</span><br> <span class="constructor">String</span>.make n <span class="string">' '</span> ^ preprocess (i+1) (column + n)<br> <span class="keywordsign">|</span> <span class="string">'\n'</span> <span class="keywordsign">-></span><br> <span class="string">"\n"</span> ^ preprocess (i+1) 0<br> <span class="keywordsign">|</span> c <span class="keywordsign">-></span><br> <span class="constructor">String</span>.make 1 c ^ preprocess (i+1) (column + 1)<br> <span class="keyword">else</span><br> <span class="string">""</span><br> <span class="keyword">in</span><br> output_string ch <span class="string">"<p><pre>"</span>;<br> output_string ch (escape_html (preprocess 0 0));<br> output_string ch <span class="string">"</pre></p>"</span>;<br> <span class="keyword">end</span><br> </code><pre></pre> <p> <a name="3_Theclassa"></a> <h3>The class <code class="code">a</code></h3> <p> Hyperlinks, expressed by the <code class="code">a</code> element type, are converted to the HTML <code class="code">a</code> type. If the target of the hyperlink is given by <code class="code">href</code>, the URL of this attribute can be used directly. Alternatively, the target can be given by <code class="code">readmeref</code> in which case the ".html" suffix must be added to the file name. <p> Note that within <code class="code">a</code> only #PCDATA is allowed, so the contents can be converted directly by applying <code class="code">escape_html</code> to the character data contents. <p> <pre></pre><code class="code"><span class="keyword">class</span> a =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">method</span> to_html store ch =<br> output_string ch <span class="string">"<a "</span>;<br> <span class="keyword">let</span> href =<br> <span class="keyword">match</span> self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> attribute <span class="string">"href"</span> <span class="keyword">with</span><br> <span class="constructor">Value</span> v <span class="keywordsign">-></span> escape_html v<br> <span class="keywordsign">|</span> <span class="constructor">Valuelist</span> _ <span class="keywordsign">-></span> <span class="keyword">assert</span> <span class="keyword">false</span><br> <span class="keywordsign">|</span> <span class="constructor">Implied_value</span> <span class="keywordsign">-></span><br> <span class="keyword">begin</span> <span class="keyword">match</span> self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> attribute <span class="string">"readmeref"</span> <span class="keyword">with</span><br> <span class="constructor">Value</span> v <span class="keywordsign">-></span> escape_html v ^ <span class="string">".html"</span><br> <span class="keywordsign">|</span> <span class="constructor">Valuelist</span> _ <span class="keywordsign">-></span> <span class="keyword">assert</span> <span class="keyword">false</span><br> <span class="keywordsign">|</span> <span class="constructor">Implied_value</span> <span class="keywordsign">-></span><br> <span class="string">""</span><br> <span class="keyword">end</span><br> <span class="keyword">in</span><br> <span class="keyword">if</span> href <> <span class="string">""</span> <span class="keyword">then</span><br> output_string ch (<span class="string">"href=\""</span> ^ href ^ <span class="string">"\""</span>);<br> output_string ch <span class="string">">"</span>;<br> output_string ch (escape_html (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> data));<br> output_string ch <span class="string">"</a>"</span>;<br> <br> <span class="keyword">end</span><br> </code><pre></pre> <p> <a name="3_Theclassfootnote"></a> <h3>The class <code class="code">footnote</code></h3> <p> The <code class="code">footnote</code> class has two methods: <code class="code">to_html</code> to convert the footnote reference to HTML, and <code class="code">footnote_to_html</code> to convert the footnote text itself. <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> The footnote must be allocated in the <code class="code">store</code> 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 <code class="code">to_html</code> method stores simply the object itself, such that the <code class="code">footnote_to_html</code> method is invoked on the same object that encountered the footnote. <p> The <code class="code">to_html</code> method 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 <code class="code">to_html</code> on the sub nodes is done by <code class="code">footnote_to_html</code> <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> <pre></pre><code class="code"><span class="keyword">class</span> footnote =<br> <span class="keyword">object</span> (self)<br> <span class="keyword">inherit</span> shared<br> <br> <span class="keyword">val</span> <span class="keyword">mutable</span> footnote_number = 0<br> <br> <span class="keyword">method</span> to_html store ch =<br> <span class="keyword">let</span> number = <br> store <span class="keywordsign">#</span> alloc_footnote (self : <span class="keywordsign">#</span>shared :> footnote_printer) <span class="keyword">in</span><br> <span class="keyword">let</span> foot_anchor = <br> <span class="string">"footnote"</span> ^ string_of_int number <span class="keyword">in</span><br> <span class="keyword">let</span> text_anchor =<br> <span class="string">"textnote"</span> ^ string_of_int number <span class="keyword">in</span><br> footnote_number <- number;<br> output_string ch ( <span class="string">"<a name=\""</span> ^ text_anchor ^ <span class="string">"\" href=\"#"</span> ^ <br> foot_anchor ^ <span class="string">"\">["</span> ^ string_of_int number ^ <br> <span class="string">"]</a>"</span> )<br> <br> <span class="keyword">method</span> footnote_to_html store ch =<br> <span class="comment">(* prerequisite: we are in a definition list <dl>...</dl> *)</span><br> <span class="keyword">let</span> foot_anchor = <br> <span class="string">"footnote"</span> ^ string_of_int footnote_number <span class="keyword">in</span><br> <span class="keyword">let</span> text_anchor =<br> <span class="string">"textnote"</span> ^ string_of_int footnote_number <span class="keyword">in</span><br> output_string ch (<span class="string">"<dt><a name=\""</span> ^ foot_anchor ^ <span class="string">"\" href=\"#"</span> ^ <br> text_anchor ^ <span class="string">"\">["</span> ^ string_of_int footnote_number ^ <br> <span class="string">"]</a></dt>\n<dd>"</span>);<br> <span class="constructor">List</span>.iter<br> (<span class="keyword">fun</span> n <span class="keywordsign">-></span> n <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store ch)<br> (self <span class="keywordsign">#</span> node <span class="keywordsign">#</span> sub_nodes);<br> output_string ch (<span class="string">"\n</dd>"</span>)<br> <br> <span class="keyword">end</span><br> </code><pre></pre> <p> <a name="3_Thespecificationofthedocumentmodel"></a> <h3>The specification of the document model</h3> <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. See <a href="Intro_extensions.html#bindext"><i>How to bind extension classes to element types</i></a> for comments, and <a href="Pxp_document.html#VALmake_spec_from_alist"><code class="code"><span class="constructor">Pxp_document</span>.make_spec_from_alist</code></a> for the function definition. <p> <pre></pre><code class="code"><span class="keyword">let</span> tag_map =<br> make_spec_from_alist<br> ~data_exemplar:(<span class="keyword">new</span> data_impl (<span class="keyword">new</span> only_data))<br> ~default_element_exemplar:(<span class="keyword">new</span> element_impl (<span class="keyword">new</span> no_markup))<br> ~element_alist:<br> [ <span class="string">"readme"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> readme));<br> <span class="string">"sect1"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> sect1));<br> <span class="string">"sect2"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> sect2));<br> <span class="string">"sect3"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> sect3));<br> <span class="string">"title"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> no_markup));<br> <span class="string">"p"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> p));<br> <span class="string">"br"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> br));<br> <span class="string">"code"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> code));<br> <span class="string">"em"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> em));<br> <span class="string">"ul"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> ul));<br> <span class="string">"li"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> li));<br> <span class="string">"footnote"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> footnote : <span class="keywordsign">#</span>shared :> shared));<br> <span class="string">"a"</span>, (<span class="keyword">new</span> element_impl (<span class="keyword">new</span> a));<br> ]<br> ()<br> </code><pre></pre> <p> <a name="2_ThereadmeconvertertoASCII"></a> <h2>The <code class="code">readme</code> converter to ASCII</h2> <p> This converter is quite similar to the HTML converter, and not presented here. The source code is part of the PXP source tarball, however. <p> <a name="2_Themainprogram"></a> <h2>The main program</h2> <p> <pre></pre><code class="code"><span class="keyword">open</span> <span class="constructor">Pxp_types</span><br> <span class="keyword">open</span> <span class="constructor">Pxp_document</span><br> <span class="keyword">open</span> <span class="constructor">Pxp_tree_parser</span><br> <br> <span class="keyword">let</span> <span class="keyword">rec</span> print_error e =<br> prerr_endline(string_of_exn e)<br> <br> <br> <span class="keyword">let</span> run f a =<br> <span class="keyword">try</span> f a <span class="keyword">with</span><br> e <span class="keywordsign">-></span> print_error e<br> <br> <br> <span class="keyword">let</span> convert_to_html filename =<br> <span class="keyword">let</span> document =<br> parse_document_entity<br> { default_config <span class="keyword">with</span> encoding = <span class="keywordsign">`</span><span class="constructor">Enc_iso88591</span> }<br> (from_file filename)<br> <span class="constructor">To_html</span>.tag_map<br> <span class="keyword">in</span><br> <span class="keyword">let</span> root = document <span class="keywordsign">#</span> root <span class="keyword">in</span><br> <span class="keyword">let</span> store = <span class="keyword">new</span> <span class="constructor">To_html</span>.store <span class="keyword">in</span><br> root <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_html store stdout<br> <br> <br> <span class="keyword">let</span> convert_to_text filename =<br> <span class="keyword">let</span> document =<br> parse_document_entity<br> default_config<br> (from_file filename)<br> <span class="constructor">To_text</span>.tag_map<br> <span class="keyword">in</span><br> <span class="keyword">let</span> root = document <span class="keywordsign">#</span> root <span class="keyword">in</span><br> <span class="keyword">let</span> store = <span class="keyword">new</span> <span class="constructor">To_text</span>.store <span class="keyword">in</span><br> <span class="keyword">let</span> box = <span class="keyword">new</span> <span class="constructor">To_text</span>.box 79 79 <span class="keyword">in</span><br> root <span class="keywordsign">#</span> extension <span class="keywordsign">#</span> to_box store box;<br> box <span class="keywordsign">#</span> output 0 0 stdout<br> <br> <br> <span class="keyword">let</span> main() =<br> <span class="keyword">let</span> want_html = ref <span class="keyword">false</span> <span class="keyword">in</span><br> <span class="keyword">let</span> want_text = ref <span class="keyword">false</span> <span class="keyword">in</span><br> <span class="keyword">let</span> filename = ref <span class="constructor">None</span> <span class="keyword">in</span><br> <span class="constructor">Arg</span>.parse<br> [ <span class="string">"-html"</span>, <span class="constructor">Arg</span>.<span class="constructor">Set</span> want_html, <br> <span class="string">" convert file to html"</span>;<br> <span class="string">"-text"</span>, <span class="constructor">Arg</span>.<span class="constructor">Set</span> want_text,<br> <span class="string">" convert file to text"</span>;<br> ]<br> (<span class="keyword">fun</span> s <span class="keywordsign">-></span> <br> <span class="keyword">match</span> !filename <span class="keyword">with</span><br> <span class="constructor">None</span> <span class="keywordsign">-></span> filename := <span class="constructor">Some</span> s<br> <span class="keywordsign">|</span> <span class="constructor">Some</span> _ <span class="keywordsign">-></span><br> raise (<span class="constructor">Arg</span>.<span class="constructor">Bad</span> <span class="string">"Multiple arguments not allowed."</span>))<br> <span class="string">"usage: readme [ -text | -html ] input.xml >output"</span>;<br> <span class="keyword">let</span> fn =<br> <span class="keyword">match</span> !filename <span class="keyword">with</span><br> <span class="constructor">None</span> <span class="keywordsign">-></span> <br> prerr_endline <span class="string">"readme: no input"</span>;<br> exit 1<br> <span class="keywordsign">|</span> <span class="constructor">Some</span> s <span class="keywordsign">-></span> s<br> <span class="keyword">in</span><br> <span class="keyword">match</span> !want_html, !want_text <span class="keyword">with</span><br> <span class="keyword">true</span>, <span class="keyword">false</span> <span class="keywordsign">-></span><br> run convert_to_html fn<br> <span class="keywordsign">|</span> <span class="keyword">false</span>, <span class="keyword">true</span> <span class="keywordsign">-></span><br> run convert_to_text fn<br> <span class="keywordsign">|</span> _ <span class="keywordsign">-></span><br> prerr_endline (<span class="string">"readme: Please select exactly one output format"</span>)<br> <br> <span class="keyword">let</span> () =<br> main()<br> </code><pre></pre> <p> <br> </body></html>