<?xml version="1.0" encoding="ASCII"?><?xml-stylesheet type="text/xsl" href="../../../mathml/pmathml.xsl"?><html xmlns="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xml:space="preserve">
   <head>
      <meta http-equiv="Content-Type" content="text/html; utf-8"/>
      <title>Proceedings of Extreme Markup Languages&#174;</title>
      <link rel="stylesheet" href="../../../extreme-proceedings.css" type="text/css"/>
   </head>
   <body>
      <div id="head">
         <div class="inner">
            <img class="right" src="../../../icons/ExtremeNoDates.jpg"/>
            <h2>
               <i>Proceedings of Extreme Markup Languages<sup>&#174;</sup>
               </i>
            </h2>
         </div>
      </div>
      <div id="nav">
         <table width="100%" cellspacing="5">
            <tr height="29">
               <td class="button" width="20%" align="center">
                  <a title="Master Bibliography" href="../../../biblio.html">Master Bibliography</a>
               </td>
               <td class="button" width="20%" align="center">
                  <a title="Author Index" href="../../../authors.html">Author Index</a>
               </td>
               <td class="button" width="20%" align="center">
                  <a title="Topic Index" href="../../../topics.html">Topic Index</a>
               </td>
               <td class="button" width="20%" align="center">
                  <a title="Date Index" href="../../../dates.html">Date Index</a>
               </td>
               <td class="button" width="20%" align="center">
                  <a title="Proceedings Home" href="../../../index.html">Proceedings Home</a>
               </td>
            </tr>
         </table>
      </div>
      <div id="left1">
         <div class="inner">
            <h4>Composable Templates</h4>
            <address>Mario Bla&#382;evi&#263; </address>
            <div class="abstract">
               <h4>Abstract</h4>
               <p class="first">
        There are many template languages in use today. Their output is very often some form of markup. The input to a
        markup engine, however, is not modelled as markup but as a collection of values suitable to the host
        environment. This mismatch between input and output data model can cause issues in the template language design,
        most obviously because the templates cannot be treated as composable functions. We demonstrate how the use of
        the same markup data model for both input and output of a template leads to simple and powerful template
        language design. The language is then tested in practice by implementing a publishing system for technical
        documentation.
      </p>
            </div>
            <p class="keywords">
               <b style="font-size:85%">Keywords:</b> 
               <a href="../../../topics/Programming.html">Programming</a>
            </p>
            <div class="contents">
               <h4>Table of Contents</h4>
               <dl>
                  <dt>
                     <a href="#t1">Introduction</a>
                  </dt>
                  <dl>
                     <dt>
                        <a href="#t1-1">Filters</a>
                     </dt>
                     <dt>
                        <a href="#t1-2">Templates as Functional Programs</a>
                     </dt>
                     <dt>
                        <a href="#t1-3">An example</a>
                     </dt>
                     <dt>
                        <a href="#t1-4">Data Model</a>
                     </dt>
                     <dt>
                        <a href="#t1-5">Overview</a>
                     </dt>
                  </dl>
                  <dt>
                     <a href="#t2">Context</a>
                  </dt>
                  <dl>
                     <dt>
                        <a href="#t2-1">History</a>
                     </dt>
                     <dt>
                        <a href="#t2-2">Data Migration</a>
                     </dt>
                     <dt>
                        <a href="#t2-3">Processing Model</a>
                     </dt>
                  </dl>
                  <dt>
                     <a href="#definition">OMDE Template Language Definition</a>
                  </dt>
                  <dl>
                     <dt>
                        <a href="#t3-1">Data model</a>
                     </dt>
                     <dt>
                        <a href="#syntax">Template Syntax</a>
                     </dt>
                     <dt>
                        <a href="#t3-3">Template Semantics</a>
                     </dt>
                     <dl>
                        <dt>
                           <a href="#t3-3-1">Environment variables</a>
                        </dt>
                        <dt>
                           <a href="#t3-3-2">User-defined filters and templates</a>
                        </dt>
                     </dl>
                  </dl>
                  <dt>
                     <a href="#library">Predefined Filters</a>
                  </dt>
                  <dt>
                     <a href="#examples">Examples</a>
                  </dt>
                  <dl>
                     <dt>
                        <a href="#t5-1">Simple Lists</a>
                     </dt>
                     <dt>
                        <a href="#t5-2">Grouped Lists</a>
                     </dt>
                  </dl>
                  <dt>
                     <a href="#results">Results and Future Work</a>
                  </dt>
                  <dl>
                     <dt>
                        <a href="#t6-1">Code Size</a>
                     </dt>
                     <dt>
                        <a href="#t6-2">Performance</a>
                     </dt>
                     <dt>
                        <a href="#t6-3">Future Work</a>
                     </dt>
                  </dl>
                  <dt>
                     <a href="#related">Related Work</a>
                  </dt>
                  <dt>
                     <a href="#conclusion">Conclusion</a>
                  </dt>
               </dl>
            </div>
            <div class="authorBio">
               <h4>Mario Bla&#382;evi&#263;</h4>
               <p class="first">
          The author has a Master's degree in Computer Science from University of Novi Sad, Yugoslavia. Since moving to
          Canada in 2000, he has been working for OmniMark Technologies, later acquired by Stilo International plc.,
          mostly in the area of markup processing and on development of the OmniMark programming language.
        </p>
            </div>
         </div>
      </div>
      <div id="paperLinks">
         <table width="100%" cellspacing="5">
            <tr height="18">
               <td class="button" width="25%" align="center">
                  <a title="XML Source" href="../../../xml/2007/Blazevic01/EML2007Blazevic01.xml">XML&#160;Source</a>
               </td>
               <td class="button" width="25%" align="center">
                  <a title="PDF Version" href="../../../xslfo-pdf/2007/Blazevic01/EML2007Blazevic01.pdf">PDF&#160;(for&#160;print)</a>
               </td>
               <td class="button" width="25%" align="center">
                  <a title="Author Package" href="../../../author-pkg/2007/Blazevic01/EML2007Blazevic01.zip">Author&#160;Package</a>
               </td>
               <td class="nobutton" width="25%" align="center">
                  <span class="nolink">Typeset&#160;PDF</span>
               </td>
            </tr>
         </table>
      </div>
      <div id="right1">
         <div class="inner">
            <div class="front">
               <h1 class="title">Composable Templates</h1>
               <address>Mario Bla&#382;evi&#263; [Senior Software Developer; Stilo International]</address>
               <h3 class="conference">Extreme Markup Languages 2007&#174; (Montr&#233;al, Qu&#233;bec)</h3>
               <h4>
                  <i>Copyright &#169; 2007 Mario Bla&#382;evi&#263;. Reproduced with permission.</i>
               </h4>
            </div>
            <div class="mathml-warning">
               <p>
                  <i>
                     <b>Note:</b>
                  </i> This paper contains <a href="http://www.w3.org/Math/">W3C MathML</a>,
          which is not equally well supported in all browsers. If you have reason to think 
          that mathematical expressions are not displaying properly, consult the 
          <a href="../../../xslfo-pdf/2007/Blazevic01/EML2007Blazevic01.pdf">PDF version</a> (or try a different browser).</p>
            </div>
            <div class="section">
               <h2>
                  <a name="t1"/>Introduction</h2>
               <p>
        A template language is a domain-specific programming language which is, syntactically, a superset of its output.
        In other words, any valid instance of the target output, with the minor exception of character escaping issues,
        is itself a valid template.
      </p>
               <p>
        There are hundreds of template languages in existence. A cursory search of the Web will turn up dozens of
        stand-alone and library implementations. Most template languages, however, serve as a hidden part of another
        software system: they can be found in publishing systems, content management systems, word processors, macro and
        meta-programming engines, and many other places. A well-known but perhaps non-obvious example of an embedded
        template language interpreter is the function <b>printf</b> from the C standard
        library.
      </p>
               <p>
        The characteristic feature of template languages, the similarity of their syntax to the target output, is also
        the main reason for their popularity. The process of creating a template is declarative. A template writer can
        concentrate on specifying the output itself, not the process by which the output will be created. This also
        means that templates can be created and maintained by target-language experts, who need not be programmers.
        Another cause for their popularity is that implementing a template language interpreter is relatively trivial,
        and usually more interesting than the rest of the work.
      </p>
               <p>
        Syntactically, a template language is usually a mixed sequence of the target language literals, which get
        reproduced in the output with no modifications, and non-literal expressions which get evaluated in some way. The
        syntax and semantics of the non-literal expressions can vary from simple positional markers, as in the first
        argument of <b>printf</b>, to an unrestricted Turing-complete programming language
        as with <b>
                     <span style="font-size:85%">
                        <a href="#PHP" name="fromPHP">[
          PHP
        ]</a>
                     </span>
                  </b>. Most template languages try to strike a balance between these two extremes. On
        one hand, increasing the expressive power of the language increases the target scope of the template language.
        On the other hand, with expressivity comes increasing complexity.
      </p>
               <p>
        Another common goal in template language design is the support and enforcement of <i>separation of concerns</i> 
                  <b>
                     <span style="font-size:85%">
                        <a href="#MVC" name="fromMVC">[
          Parr 2004
        ]</a>
                     </span>
                  </b> between the template authors and
        software developers. Ideally, the templates should be concerned only with presentation, while the host software
        using the templates should feed them only the raw data with no formatting.
      </p>
               <p>
        A template language can be, and usually is, restricted in two ways. First, the language control structures can
        be limited to the point that they cannot express any business logic that doesn't belong in the presentation
        layer. Secondly, the language I/O constructs can be restricted so that a template only has access to the input
        data necessary to produce its output: for example, no file access would be allowed. With this restriction in
        place, we can view a template as a pure function from the restricted inputs given by the host environment to its
        target output.
      </p>
               <div class="subsec1">
                  <h3>
                     <a name="t1-1"/>Filters</h3>
                  <p>
          One way to increase the expressivity of a template language is by adding more control constructs to it. The
          first to be added are usually loops and conditionals, then variables, even arithmetic, until the language
          becomes Turing-complete. Alternatively, we can make the host software perform the necessary computations on
          demand and supply the results to the template. In other words, we can provide the templates with a function
          library. This will be our preferred route.
        </p>
                  <p>
          One class of functions that is often made available in template languages is <i>text
            filters</i>. Filters solve a practical problem familiar to anybody who has generated HTML, XML, or
          SGML output: all special characters in the textual input must be escaped before they can be output as data
          content <sup>
                        <span class="highlight">
                           <a href="#tod0e85" name="fromd0e85">1</a>
                        </span>
                     </sup>. The algorithm necessary to perform this escaping, however, cannot be expressed in a template
          language without some rather sophisticated extensions. Many popular template engines like <b>
                        <span style="font-size:85%">
                           <a href="#Django" name="fromDjango">[
          Django
        ]</a>
                        </span>
                     </b> therefore choose to provide text filters like <b>escape</b>,
          <b>center</b>, and <b>pluralize</b> ready-made.
        </p>
                  <p>
          While the addition of text filters to a template language obviously makes the language more difficult to
          learn, if the set of predefined filters is chosen carefully it can be used intuitively by non-programmers. The
          impact on separation of concerns, again, entirely depends on the filters that are made available to the
          template language. If a filter performs a high-level task that is usable only for presentation purposes, then
          the templates cannot violate the principle of separation of concerns by using it.
        </p>
                  <p>
          Another thing to examine is the impact of text filters on the I/O allowed to templates. If we have chosen to
          restrict the inputs available to the templates, the easiest and safest way to enforce this restriction in the
          presence of filters is to make all filters pure functions. In other words, a text filter can use only the
          input provided to it by the template and cannot have any effects other than feeding its result back to the
          template.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t1-2"/>Templates as Functional Programs</h3>
                  <p>
          At this point, we have reached the conclusion that a template should be a pure function that generates its
          output value from a restricted set of input values. To be able to achieve this task, the template should have
          access to a set of predefined text filters, and these filters should also be pure functions.
        </p>
                  <p>
          It should not come as surprise at this point that, according to most definitions, our abstract template
          language is a <i>functional programming language</i>. If we accept this
          conclusion, what can this new perspective on template languages teach us?
        </p>
                  <p>
          Most functional programming languages encourage recursion. While conceptually simple, unrestricted recursion
          makes the language Turing-complete. It can also be difficult to understand. For the latter reason, modern
          functional languages supply a number of higher-order functions that can be used to express common patterns of
          recursion in a more controlled way. Programmers are encouraged to use the standard higher-order functions
          instead of writing their own recursive algorithms <b>
                        <span style="font-size:85%">
                           <a href="#FP" name="fromFP">[
          Backus 1978
        ]</a>
                        </span>
                     </b>. Foremost examples among
          these standardized functions are <i>compose</i> and <i>map</i> (also referred to as <i>lift</i>). The former
          higher-order function composes two argument functions into a new function, and the latter applies its argument
          function to all members of a collection.
        </p>
                  <p>
          From our perspective, the interesting thing about <i>map</i> is that it acts like
          a loop construct, in that it invokes its function argument multiple times, once for every member of the
          collection argument. Unlike many loop constructs in general-purpose programming languages, however, it is very
          simple to understand and it provides a number of important guarantees: for example, it cannot be used to
          construct an infinite loop. We can say it is a <i>data driven</i> control
          structure, because its behaviour is driven by the shape of its collection argument.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t1-3"/>An example</h3>
                  <p> To illustrate how control constructs can be replaced by higher-order functions, we shall use a fragment
          of an example taken from the documentation of Django <b>
                        <span style="font-size:85%">
                           <a href="#Django" name="fromDjango">[
          Django
        ]</a>
                        </span>
                     </b> template language:
        
<div class="codeblock">
                        <pre>
   {% for story in story_list %}
   &lt;h2&gt;
     &lt;a href="{{ story.get_absolute_url }}"&gt;
       {{ story.headline|upper }}
     &lt;/a&gt;
   &lt;/h2&gt;
   &lt;p&gt;{{ story.tease|truncatewords:"100" }}&lt;/p&gt;
   {% endfor %}
</pre>
                     </div>
        
                  </p>
                  <p>
          The template fragment above is a pure function from <b>story_list</b> to HTML.
          The <b>story_list</b> input is a list of records containing fields <b>get_absolute_url</b>, <b>headline</b>, and <b>tease</b>. The example uses a control construct, namely the <b>for</b> loop, text filters <b>upper</b> and <b>truncatewords</b>, as well as field accessors <b>get_absolute_url</b>, <b>headline</b>, and <b>tease</b>. From a functional programmer's point of view, all of the above are
          pure functions:
          <ul>
                        <li>Each of the field accessors is a function from a story to one of its fields.</li>
                        <li>Text filters are functions from text to text.</li>
                        <li>
                The vertical bar symbol <b>|</b> is a higher-order function commonly known
                as <i>compose</i>, taking as arguments the two functions specified on its
                sides and returning their composition.
              </li>
                        <li>
                The dot symbol <b>.</b> denotes application of the function on its
                right-hand side to the value on its left.
              </li>
                        <li>
                The body of the <b>for</b> construct is a template function that
                concatenates the literal elements like
                
<div class="codeblock">
                              <pre>
   &lt;h2&gt;
     &lt;a href="
</pre>
                           </div> together with the results of function applications like
                
<div class="codeblock">
                              <pre>{{ story.get_absolute_url }}</pre>
                           </div>
              
                           <br class="br"/> This function is not one of the standardized higher-order functions, but it can be trivially
                defined. In Haskell <b>
                              <span style="font-size:85%">
                                 <a href="#Haskell" name="fromHaskell">[
          Haskell 2003
        ]</a>
                              </span>
                           </b>, for example, one definition would be as
                follows:
                
<div class="codeblock">
                              <pre>
   concatMapApply :: [a -&gt; [b]] -&gt; a -&gt; [b]
   concatMapApply functions input = concatMap ($ input) functions
                </pre>
                           </div>
              
                        </li>
                        <li>
                Finally, the <b>for</b> construct is an equivalent of the higher-order
                function <i>map</i>. The body of the construct is a function that gets
                applied to each item in the input list, and the result of the entire construct is the list of the
                function's results. If we don't care about the boundaries between different items of the result list,
                we can use <i>concatMap</i> instead of regular <i>map</i>. The former function concatenates together all the results, erasing the
                boundaries between them.
              </li>
                     </ul>
        
                  </p>
                  <p>
          If we put together all the pieces, the example template could be written in Haskell as follows:
          
<div class="codeblock">
                        <pre>
   module Example where

   import Char (toUpper)

   concatMapApply :: [a -&gt; [b]] -&gt; a -&gt; [b]
   concatMapApply functions input = concatMap ($ input) functions

   data Story = Story {get_absolute_url :: String,
                       headline :: String,
                       tease :: String}

   upper = map toUpper
   truncatewords max text = unwords (take max (words text))

   template :: [Story] -&gt; String
   template = concatMap (concatMapApply [const "  &lt;h2&gt;\n",
                                         const "    &lt;a href=\"",
                                         get_absolute_url,
                                         const "\"&gt;\n      ",
                                         upper . headline,
                                         const "\n",
                                         const "    &lt;/a&gt;\n",
                                         const "  &lt;/h2&gt;\n",
                                         const "  &lt;p&gt;",
                                         truncatewords 100 . tease,
                                         const "&lt;/p&gt;\n"])


   test = [Story "http://hello.org/" "Greeting" "This is a short greeting.",
           Story "http://hi.org/" "Another Greeting" "This is an even shorter greeting."]

   main = putStrLn (template test)
</pre>
                     </div>
        
                  </p>
                  <p>
          Haskell is obviously not a template language. While the Haskell code above demonstrates how a template can be
          represented using higher-order functions, it is not a template itself. If we translate the code back into a
          template language, keeping its functional structure along the way, here is what it could look like:
          
<div class="codeblock">
                        <pre>
   [- #map ["
   &lt;h2&gt;
     &lt;a href="[- @get_absolute_url -]"&gt;
       [- @headline:upper -]
     &lt;/a&gt;
   &lt;/h2&gt;
   &lt;p&gt;[- @tease:truncatewords(100) -]&lt;/p&gt;
   "] -]
</pre>
                     </div>
        
                  </p>
                  <p>
          As this short example hopefully demonstrates, it is possible to design the semantics of a template language on
          the principles of higher-order functional programming without sacrificing the directness of its syntax. The
          actual template language used in this example will be presented in section <a href="#definition">3</a> of the
          paper.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t1-4"/>Data Model</h3>
                  <p>
          The constructs the language provides for fetching input impose a certain view of the external world, both upon
          the template language and the template writer. This view is the <i>input data
            model</i>, and it represents one of the most distinguishing features of a template language.
        </p>
                  <p>
          The most restrictive kind of template languages provide a fixed number of input variables to each template.
          The input model in this case is a vector of input values. The template can specify the values it needs by their
          position, as in the <b>printf</b> example, or by name. Many template languages
          begin their life in this form.
        </p>
                  <p>
          The next addition to the data model tends to come in the form of multi-valued inputs. The reason for this
          extension is purely practical: many target outputs contain item lists, tables, etc. In order to be able to
          traverse the multiple values provided by the new input data model, the template language is usually extended
          by a looping construct. The looping construct is often semantically equivalent to the higher-order function
          <i>map</i>.
        </p>
                  <p>
          The logical next step is to add <i>nested</i> data collections, <i>i.e.</i>, lists of lists or S-expressions, to the input data model. With this extension
          in place, the templates become capable of generating outputs containing two-dimensional tables and nested
          lists.
        </p>
                  <p>
          Even as the <i>input</i> data model of a template language becomes more
          structured and expressive, the <i>output</i> data model is typically left as the
          same unstructured singleton value. The problem this dichotomy presents for templates as functions is that they
          cannot be composed: the output of one template cannot be fed into another template.
        </p>
                  <p>
          The solution to this impedance mismatch is to make template input and output have the same structure. One
          obvious candidate for this common structure is XML markup. Many of the existing template languages are used
          to generate markup: HTML, SGML or XML. Furthermore, XML can trivially encode nested data collections needed
          for the input data model of the template language.
        </p>
                  <p>
          The effect of this unification of input and output data model is to make every template a user-defined markup
          filter. These filters can be composed, mapped over components of XML documents, and combined in other ways
          using higher-order functions, to produce other markup filters. The goal of a template writer, then, is to
          construct a markup filter that will produce the target output from the input data encoded as an XML document.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t1-5"/>Overview</h3>
                  <p>
          The remainder of this paper will introduce OMDE [OmniMark
              Documentation Environment] template language, which tries to apply the above
          principles of template language design in practice. The next section will introduce the language and describe
          the context it's been developed in. The sections <a href="#definition">3</a> and <a href="#library">4</a>
          define the language in detail, and section <a href="#examples">5</a> explains its practical use through
          several examples. The results are presented in section <a href="#results">6</a>, and the remaining sections
          <a href="#related">7</a> and <a href="#conclusion">8</a> contain discussion of related work and the conclusion.
        </p>
               </div>
            </div>
            <div class="section">
               <h2>
                  <a name="t2"/>Context</h2>
               <div class="subsec1">
                  <h3>
                     <a name="t2-1"/>History</h3>
                  <p>
          OMDE stands for OmniMark Documentation Environment. It was originally developed in 1998.
           The OmniMark documentation before OMDE was a monolithic SGML document, and it was proving
           increasingly difficult to maintain. OmniMark <b>
                        <span style="font-size:85%">
                           <a href="#OmniMark" name="fromOmniMark">[
          OmniMark 2007
        ]</a>
                        </span>
                     </b> is a programming language targeting
           text and markup processing.
        </p>
                  <p>
        The original OMDE developed in 1998 was based on the <i>microdocument
            architecture</i> 
                     <b>
                        <span style="font-size:85%">
                           <a href="#Microdocument" name="fromMicrodocument">[
          Baker 1998
        ]</a>
                        </span>
                     </b>. Documentation has been divided into many small,
          interlinked topics. Each topic could have multiple SGML documents associated with it, as well as links to
          other topics. Both the SGML documents and links were categorized according to their purpose. For example, most
          language keyword topics had associated <i>syntax</i> and <i>purpose</i> documents, and links could be categorized into <i>related keywords</i> and <i>related concepts</i>. Both the
          SGML content and the inter-topic links were stored in a database.
        </p>
                  <p>
          The goals of the OMDE project included simple authoring, content reuse, and multiple
          outputs. In order to achieve the first goal, the SGML markup for topic content was made minimal. For example,
          there are only two tags, <b>code</b> and <b>codeblock</b>, available for marking up code fragments. It was the task of the
          publishing engine to scan the code for keywords and link them to corresponding keyword topics. Content reuse
          was to be accomplished by inclusion of topic content into larger, <i>narrative</i> topics. Due to lack of demand, however, this feature did not see much
          use, and only one narrative document has ever been designed. As for the multiple outputs, originally there were
          three: HTML, Windows help, and PDF generated through FrameMaker.
        </p>
                  <p>
          Over the years, several problems were identified with OMDE:
          <ul>
                        <li>
                FrameMaker, used for generating the PDF and Windows Help documentation, was a constant bottleneck in the
                release process due to certain operations that had to be performed manually.
              </li>
                        <li>
                The generated PDF was deemed to have poor quality.
              </li>
                        <li>
                Distribution of the Windows Help format has later been abandoned in favour of HTML.
              </li>
                        <li>
                The database that was used for the documentation had only a rudimentary support for versioning.
              </li>
                        <li>
                The content authoring software, necessary because the documentation was stored in a proprietary
                database, was implemented in Visual Basic and worked only on Windows.
              </li>
                     </ul>
        
                  </p>
                  <p>
          In the context of the present paper, the most significant problem was that the template language used by the
          OMDE publishing process was too simple: its data model allowed for singleton values only.
          As a consequence, much of the output formatting had to be specified by the host software, an OmniMark program,
          not by the templates. In that situation, only the initiated were (was?) able to modify the details of the
          generated output.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t2-2"/>Data Migration</h3>
                  <p>
          In December of 2006, it was decided that the OMDE processing software should be rewritten
          from scratch. The existing content would be reused with as little modification as possible. The proprietary
          database would be abandoned in favour of the combination of filesystem storage and Perforce
          SCM [Software Configuration Management] system for version control. The only output format produced in the beginning would be HTML,
          with PDF to follow later.
        </p>
                  <p>
          There are currently 3750 topics in OMDE, 2153 of them containing non-trivial SGML content.
          The published output consists of 1892 HTML files. It was decided that the only sane way to verifiably
          replicate the required functionality of the old OMDE was by producing the exact same output
          with all the existing bugs. Fixing the output issues could be left for a later day.
        </p>
                  <p>
          Microdocument architecture, proven as the best feature of the 1998 OMDE design, has been
          kept. Each topic, previously stored as a database record, became an SGML file instead. Inter-topic links,
          metadata, and SGML content moved from the record fields into the top-level elements of the topic file. The
          primary identifiers of topic records became file names, and database tables previously containing topics were
          mapped into directories containing topic files.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t2-3"/>Processing Model</h3>
                  <p>
          One of the project goals was to stress-test the new streaming capabilities of OmniMark 8. For this reason,
          processing logic has been organized into pipelines. Data originates from SGML topics, streams through various
          templates, and ends up as a collection of HTML files. The data stream is marked up in each phase of the
          process until the very end, when the markup is stripped from the stream before it gets written as plain text
          into the appropriate destination file.
        </p>
                  <p>
          Each template acts as a filter on a markup stream. There are top-level templates, largely matching the
          templates inherited from 1998, that closely mimic the output HTML pages. There are also templates that specify
          how a particular topic element, like paragraph, maps into HTML. Some templates contain no fragment of the
          output; they are used only to organize the input stream, usually by marking it up, before it can be processed
          into HTML.
        </p>
                  <p>
          It is arguable whether the templates of the latter kind really belong in the presentation layer. One example
          of a template that has nothing to do with the output format is the choice of the sorting and grouping
          criteria. In our opinion, this is more a matter of presentation than of business logic.
        </p>
                  <p>
          It must be emphasized that the word "pipeline", used here for lack of better terminology, should not be taken
          to imply linear processing. As already noted, the processing of elements from the SGML topic markup can be
          delegated to a smaller template filter, so the processing pipeline involves certain branching and division of
          tasks. Duplication and suppression of parts of the input stream also occur.
        </p>
               </div>
            </div>
            <div class="section">
               <h2>
                  <a name="definition"/>OMDE Template Language Definition</h2>
               <div class="subsec1">
                  <h3>
                     <a name="t3-1"/>Data model</h3>
                  <p>
          Some technical details aside, both input and output of a template are always markup streams. The markup model
          used in OMDE is much simpler than the full SGML/XML markup. Here is the whole of the model:

          <h4>Markup Stream Data Model</h4>
                     <table border="0" cellpadding="8" class="deflist">
                        <tr>
                           <th>Term</th>
                           <th>Definition</th>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>markup stream</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  sequence of <i>markup item</i>s
                </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>markup item</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>character</i> or <i>element</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>element</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  triple of <i>element name</i>, <i>element
                    attributes</i>, and <i>element content</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>element name</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>string</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>element attributes</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  map from <i>attribute name</i>s to <i>attribute
                    value</i>s
                </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>attribute name</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>string</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>attribute value</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>markup stream</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>element content</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>markup stream</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>string</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  sequence of <i>character</i>s
                </p>
                           </td>
                        </tr>
                     </table>
        
                  </p>
                  <p>
          Compared to SGML and XML, the markup model defined above is missing processing instructions, entities,
          comments, and marked sections. For the sake of simplicity, the model also removes some restrictions present in
          SGML and XML: there is no concept of a single document element, and attribute values can be arbitrary markup
          streams. Element content is different from an attribute value only in that it is present in every element,
          though it may be empty.
        </p>
                  <p>
          The initial input to the template pipeline typically consists of a single <i>topic
            element</i> representing the topic to be published. Topic elements can also be produced within the
          template language in two ways: by accessing attributes of the predefined variable <b>$topics</b> and by using built-in filters <b>#find-topic-id</b> and <b>#match-topic-id</b>.
        </p>
                  <p>
          Every topic has certain metadata associated with it, as well as links to other topics. Both metadata and links
          are represented as attribute values of the topic element representing the topic. All topic metadata fields
          named <b>Index</b>, for example, are mapped to a single attribute with name
          <b>Index</b> and value equal to the sequence of all metadata field values
          individually wrapped in an element named <b>Index</b>. All links are mapped in
          the same way, except in this case the attribute value is the sequence of the topic elements representing the
          topics that the links are pointing to.
        </p>
                  <p>
          Aside from metadata and link attributes, every topic element has three predefined attributes: <b>topic-content</b>, <b>topic-id</b> and <b>topic-type</b>. The latter two contain the unique topic identifier and the topic type
          name.
        </p>
                  <p>
          For example, the template 
<div class="codeblock">
                        <pre>[-$topics:@Library:#map[-@Name-]-]</pre>
                     </div> would produce a list of all
          library names, and
          
<div class="codeblock">
                        <pre>[-$topics:@Library:#map["&lt;a href="[-@topic-id-]"&gt;[-@Name:#escape-html-]&lt;/a&gt;"]-]</pre>
                     </div>
          would present all library names as HTML
          links.
        </p>
                  <p>
          The value of the attribute <b>topic-content</b> of a topic element represents the
          parsed SGML content of the topic. This value is generated on demand, which means that full parsing of the
          topic is delayed until necessary. As the topic content is parsed, the SGML elements within are mapped into the
          elements of the data model in a straightforward fashion. The remaining SGML markup is processed in the usual
          way: entities get expanded, processing instructions and comments ignored.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="syntax"/>Template Syntax</h3>
                  <p>
          The grammar of OMDE templates in EBNF form follows below.

          <h4>OMDE Template Syntax</h4>
                     <table border="0" cellpadding="8" class="deflist">
                        <tr>
                           <th>Non-Terminal</th>
                           <th>Definition</th>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>template</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  {<i>template item</i>}
                </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>template item</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>character </i>| <i>filter composition</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>filter composition</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  "<b>[-</b>" <i>filter </i>{"<b>:</b>" <i>filter</i>} "<b>-]</b>"
                </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>filter</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>filter reference</i> | <i>template
                    reference</i> | <i>built-in filter</i> [<i>filter argument</i>] | <i>variable reference</i> |
                  <i>inline template</i> | <i>attribute
                    reference</i> | <i>element literal</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>filter reference</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>name</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>template reference</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>name</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>built-in filter</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  "<b>#</b>" <i>name</i> ["<b>(</b>" {<i>character</i>} "<b>)</b>"]
                </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>filter argument</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>filter composition</i> | <i>inline
                    template</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>inline template</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  '<b>["</b>' <i>template</i> '<b>"]</b>'
                </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>variable reference</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  "<b>$</b>" <i>name</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>attribute reference</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  "<b>@</b>" <i>name</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>element literal</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  "<b>&lt;</b>" <i>name</i> {<i>element attribute</i>} "<b>&gt;</b>" <i>filter argument</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>element attribute</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>name</i> "<b>=</b>" <i>filter argument</i>
                
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top">
                              <i>name</i>
                           </td>
                           <td valign="top">
                              <p class="first">
                  
                                 <i>letter</i> {<i>letter</i> | "<b>-</b>" | "<b>_</b>"}
                </p>
                           </td>
                        </tr>
                     </table>
        
                  </p>
                  <p>
          All whitespace is significant in a <i>template</i>, and insignificant inside a
          <i>filter composition</i>. There are no comments built into the language, but
          they can be simulated by using unreachable inline templates.
        </p>
                  <p>
          The syntax presented above is ambiguous: an unqualified name can be a <i>filter
            reference</i> or a <i>template reference</i>. This ambiguity is
          resolved by looking up the name in question. New filters and templates can be added by creating a file or
          subdirectory in a special directory reserved for the purpose. The files specifying filters have the extension
          <b>.path</b> and their syntax matches <i>filter
            composition</i>, whereas the files specifying templates end with <b>.tpl</b> and contain the <i>template</i> syntax.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t3-3"/>Template Semantics</h3>
                  <p>
          The simplest template contains only text and no filter compositions. When such a template gets applied to a
          markup stream, the result is the template text.
        </p>
                  <p>
          In general, the result of evaluating a template on an input stream is the concatenation of results of
          evaluation of individual template components on the stream. If we denote the evaluation function as <i>
                        <b>E<sub>template</sub>
                        </b>
                     </i>(<i>template</i>, <i>input</i>, <i>environment</i>), we can write the semantics
          more formally as follows:
        </p>
                  <span style="font-family: 'Lucida Sans Unicode'">
                     <mml:math display="block" overflow="scroll">
  
                        <mml:mtable columnalign="right center left">
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>template</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
        
                                    <mml:mrow>
          
                                       <mml:msub>
            
                                          <mml:mi>T</mml:mi>
            
                                          <mml:mn>1</mml:mn>
          
                                       </mml:msub>
          
                                       <mml:msub>
            
                                          <mml:mi>T</mml:mi>
            
                                          <mml:mn>2</mml:mn>
          
                                       </mml:msub>
          
                                       <mml:mo>&#8230;</mml:mo>
          
                                       <mml:msub>
            
                                          <mml:mi>T</mml:mi>
            
                                          <mml:mi>n</mml:mi>
          
                                       </mml:msub>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>item</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:msub>
            
                                       <mml:mi>T</mml:mi>
            
                                       <mml:mn>1</mml:mn>
          
                                    </mml:msub>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
        
                                 <mml:mspace width="0.5em"/>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>item</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:msub>
            
                                       <mml:mi>T</mml:mi>
            
                                       <mml:mn>2</mml:mn>
          
                                    </mml:msub>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
        
                                 <mml:mspace width="0.25em"/>
        
                                 <mml:mo>&#8230;</mml:mo>
        
                                 <mml:mspace width="0.25em"/>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>item</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:msub>
            
                                       <mml:mi>T</mml:mi>
            
                                       <mml:mi>n</mml:mi>
          
                                    </mml:msub>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>

    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>item</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
          
                                       <mml:mi>Character</mml:mi>
          
                                       <mml:mfenced>
            
                                          <mml:mi>c</mml:mi>
          
                                       </mml:mfenced>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mi>c</mml:mi>
      
                              </mml:mtd>
    
                           </mml:mtr>

    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>item</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo mathvariant="bold">[-</mml:mo>
            
                                       <mml:mi>composition</mml:mi>
            
                                       <mml:mo mathvariant="bold">-]</mml:mo>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>composition</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mi>composition</mml:mi>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>

    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>composition</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:msub>
              
                                          <mml:mi>filter</mml:mi>
              
                                          <mml:mn>1</mml:mn>
            
                                       </mml:msub>
            
                                       <mml:mi mathvariant="bold">:</mml:mi>
            
                                       <mml:msub>
              
                                          <mml:mi>filter</mml:mi>
              
                                          <mml:mn>2</mml:mn>
            
                                       </mml:msub>
            
                                       <mml:mi mathvariant="bold">:</mml:mi>
            
                                       <mml:mo>&#8230;</mml:mo>
            
                                       <mml:mi mathvariant="bold">:</mml:mi>
            
                                       <mml:msub>
              
                                          <mml:mi>filter</mml:mi>
              
                                          <mml:mi>n</mml:mi>
            
                                       </mml:msub>
          
                                    </mml:mrow>
          
                                    <mml:msub>
            
                                       <mml:mi>S</mml:mi>
            
                                       <mml:mn>0</mml:mn>
          
                                    </mml:msub>
          
                                    <mml:msub>
            
                                       <mml:mi>env</mml:mi>
            
                                       <mml:mn>0</mml:mn>
          
                                    </mml:msub>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>n</mml:mi>
        
                                 </mml:msub>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd/>
      
                              <mml:mtd/>
      
                              <mml:mtd>
        
                                 <mml:mtext>where &#160;</mml:mtext>
        
                                 <mml:mfenced>
        
                                    <mml:msub>
          
                                       <mml:mi>S</mml:mi>
          
                                       <mml:mi>i</mml:mi>
        
                                    </mml:msub>
        
                                    <mml:msub>
          
                                       <mml:mi>env</mml:mi>
          
                                       <mml:mi>i</mml:mi>
        
                                    </mml:msub>
        
                                 </mml:mfenced>
        
                                 <mml:mo>=</mml:mo>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:msub>
            
                                       <mml:mi>filter</mml:mi>
            
                                       <mml:mi>i</mml:mi>
          
                                    </mml:msub>
          
                                    <mml:msub>
            
                                       <mml:mi>S</mml:mi>
            
                                       <mml:mrow>
              
                                          <mml:mi>i</mml:mi>
              
                                          <mml:mo>-</mml:mo>
              
                                          <mml:mn>1</mml:mn>
            
                                       </mml:mrow>
          
                                    </mml:msub>
          
                                    <mml:msub>
            
                                       <mml:mi>env</mml:mi>
            
                                       <mml:mrow>
              
                                          <mml:mi>i</mml:mi>
              
                                          <mml:mo>-</mml:mo>
              
                                          <mml:mn>1</mml:mn>
            
                                       </mml:mrow>
          
                                    </mml:msub>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo mathvariant="bold">["</mml:mo>
            
                                       <mml:mi>template</mml:mi>
            
                                       <mml:mo mathvariant="bold">"]</mml:mo>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mfenced>
        
                                    <mml:mrow>
          
                                       <mml:msub>
            
                                          <mml:mi>E</mml:mi>
            
                                          <mml:mi>template</mml:mi>
          
                                       </mml:msub>
          
                                       <mml:mo>&#8289;</mml:mo>
          
                                       <mml:mfenced>
            
                                          <mml:mi>template</mml:mi>
            
                                          <mml:mi>S</mml:mi>
            
                                          <mml:mi>env</mml:mi>
          
                                       </mml:mfenced>
        
                                    </mml:mrow>
        
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mi>name</mml:mi>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:msub>
              
                                          <mml:mi>E</mml:mi>
              
                                          <mml:mi>composition</mml:mi>
            
                                       </mml:msub>
            
                                       <mml:mo>&#8289;</mml:mo>
            
                                       <mml:mfenced>
              
                                          <mml:mrow>
                
                                             <mml:mi>ResolveFilter</mml:mi>
                
                                             <mml:mfenced>
                  
                                                <mml:mi>name</mml:mi>
                
                                             </mml:mfenced>
              
                                          </mml:mrow>
              
                                          <mml:mi>S</mml:mi>
              
                                          <mml:mi>env</mml:mi>
            
                                       </mml:mfenced>
          
                                    </mml:mrow>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd/>
      
                              <mml:mtd/>
      
                              <mml:mtd>
          
                                 <mml:mtext>where &#160;</mml:mtext>
          
                                 <mml:mi>name</mml:mi>
          
                                 <mml:mtext>&#160;is a user-defined filter name</mml:mtext>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mi>name</mml:mi>
          
                                    <mml:mrow>
            
                                       <mml:msub>
              
                                          <mml:mi>S</mml:mi>
              
                                          <mml:mn>1</mml:mn>
            
                                       </mml:msub>
            
                                       <mml:msub>
              
                                          <mml:mi>S</mml:mi>
              
                                          <mml:mn>2</mml:mn>
            
                                       </mml:msub>
            
                                       <mml:mo>&#8230;</mml:mo>
            
                                       <mml:msub>
              
                                          <mml:mi>S</mml:mi>
              
                                          <mml:mi>n</mml:mi>
            
                                       </mml:msub>
            
                                    </mml:mrow>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:msub>
              
                                          <mml:mi>E</mml:mi>
              
                                          <mml:mi>template</mml:mi>
            
                                       </mml:msub>
            
                                       <mml:mo>&#8289;</mml:mo>
            
                                       <mml:mfenced>
              
                                          <mml:msub>
                
                                             <mml:mi>T</mml:mi>
                
                                             <mml:mn>1</mml:mn>
              
                                          </mml:msub>
              
                                          <mml:msub>
                
                                             <mml:mi>S</mml:mi>
                
                                             <mml:mn>1</mml:mn>
              
                                          </mml:msub>
              
                                          <mml:mi>env</mml:mi>
            
                                       </mml:mfenced>
            
                                       <mml:mspace width="0.25em"/>
            
                                       <mml:mo>&#8230;</mml:mo>
            
                                       <mml:mspace width="0.25em"/>
            
                                       <mml:msub>
              
                                          <mml:mi>E</mml:mi>
              
                                          <mml:mi>template</mml:mi>
            
                                       </mml:msub>
            
                                       <mml:mo>&#8289;</mml:mo>
            
                                       <mml:mfenced>
              
                                          <mml:msub>
                
                                             <mml:mi>T</mml:mi>
                
                                             <mml:mn>n</mml:mn>
              
                                          </mml:msub>
              
                                          <mml:msub>
                
                                             <mml:mi>S</mml:mi>
                
                                             <mml:mi>n</mml:mi>
              
                                          </mml:msub>
              
                                          <mml:mi>env</mml:mi>
            
                                       </mml:mfenced>
          
                                    </mml:mrow>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd/>
      
                              <mml:mtd/>
      
                              <mml:mtd>
        
                                 <mml:mtext>where &#160;</mml:mtext>
        
                                 <mml:msub>
          
                                    <mml:mi>T</mml:mi>
          
                                    <mml:mn>i</mml:mn>
        
                                 </mml:msub>
        
                                 <mml:mo>=</mml:mo>
        
                                 <mml:mi>ResolveTemplate</mml:mi>
        
                                 <mml:mfenced>
          
                                    <mml:mi>name</mml:mi>
          
                                    <mml:msub>
            
                                       <mml:mi>S</mml:mi>
            
                                       <mml:mi>i</mml:mi>
          
                                    </mml:msub>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd/>
      
                              <mml:mtd/>
      
                              <mml:mtd>
         
                                 <mml:mtext>and &#160;</mml:mtext>
         
                                 <mml:mi>name</mml:mi>
         
                                 <mml:mtext>&#160;is a user-defined template name</mml:mtext>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo mathvariant="bold">$</mml:mo>
            
                                       <mml:mi>name</mml:mi>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mi>env</mml:mi>
            
                                       <mml:mfenced>
              
                                          <mml:mi>name</mml:mi>
            
                                       </mml:mfenced>
          
                                    </mml:mrow>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo rspace="0" mathvariant="bold">@</mml:mo>
            
                                       <mml:mi>name</mml:mi>
          
                                    </mml:mrow>
          
                                    <mml:mrow>
            
                                       <mml:mi>Element</mml:mi>
            
                                       <mml:mfenced>
              
                                          <mml:mi>element-name</mml:mi>
              
                                          <mml:mi>attributes</mml:mi>
              
                                          <mml:mi>content</mml:mi>
            
                                       </mml:mfenced>
          
                                    </mml:mrow>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mi>attributes</mml:mi>
            
                                       <mml:mfenced>
              
                                          <mml:mi>name</mml:mi>
            
                                       </mml:mfenced>
          
                                    </mml:mrow>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>filter</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo rspace="veryverythinmathspace" mathvariant="bold">&lt;</mml:mo>
            
                                       <mml:mi>name</mml:mi>
            
                                       <mml:mspace width="0.5em"/>
            
                                       <mml:mrow>
              
                                          <mml:msub>
                
                                             <mml:mi>attr</mml:mi>
                
                                             <mml:mn>1</mml:mn>
              
                                          </mml:msub>
              
                                          <mml:mo lspace="veryverythinmathspace">=</mml:mo>
              
                                          <mml:msub>
                
                                             <mml:mi>V</mml:mi>
                
                                             <mml:mn>1</mml:mn>
              
                                          </mml:msub>
            
                                       </mml:mrow>
            
                                       <mml:mo>&#8230;</mml:mo>
            
                                       <mml:mrow>
              
                                          <mml:msub>
                
                                             <mml:mi>attr</mml:mi>
                
                                             <mml:mi>n</mml:mi>
              
                                          </mml:msub>
              
                                          <mml:mo lspace="veryverythinmathspace">=</mml:mo>
              
                                          <mml:msub>
                
                                             <mml:mi>V</mml:mi>
                
                                             <mml:mi>n</mml:mi>
              
                                          </mml:msub>
            
                                       </mml:mrow>
            
                                       <mml:mo lspace="veryverythinmathspace" mathvariant="bold">&gt;</mml:mo>
            
                                       <mml:mi>content</mml:mi>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo minsize="2">(</mml:mo>
        
                                 <mml:mtable align="baseline 1" columnalign="left">
        
                                    <mml:mtr>
        
                                       <mml:mtd>
          
                                          <mml:mi>Element</mml:mi>
          
                                          <mml:mo>&#8289;</mml:mo>
          
                                          <mml:mtable align="baseline 1" columnalign="left" framespacing="0">
          
                                             <mml:mtr>
          
                                                <mml:mtd>
            
                                                   <mml:mo minsize="1.5">(</mml:mo>
            
                                                   <mml:mi>name</mml:mi>
            
                                                   <mml:mo>,</mml:mo>
          
                                                </mml:mtd>
          
                                             </mml:mtr>
          
                                             <mml:mtr>
          
                                                <mml:mtd>
          
                                                   <mml:mfenced>
            
                                                      <mml:mrow>
              
                                                         <mml:msub>
                
                                                            <mml:mi>attr</mml:mi>
                
                                                            <mml:mn>1</mml:mn>
              
                                                         </mml:msub>
              
                                                         <mml:mo>&#8614;</mml:mo>
              
                                                         <mml:msub>
                
                                                            <mml:mi>E</mml:mi>
                
                                                            <mml:mi>arg</mml:mi>
              
                                                         </mml:msub>
              
                                                         <mml:mo>&#8289;</mml:mo>
              
                                                         <mml:mfenced>
                
                                                            <mml:msub>
                  
                                                               <mml:mi>V</mml:mi>
                  
                                                               <mml:mn>1</mml:mn>
                
                                                            </mml:msub>
                
                                                            <mml:mi>S</mml:mi>
                
                                                            <mml:mi>env</mml:mi>
              
                                                         </mml:mfenced>
            
                                                      </mml:mrow>
            
                                                      <mml:mo>&#8230;</mml:mo>
            
                                                      <mml:mrow>
              
                                                         <mml:msub>
                
                                                            <mml:mi>attr</mml:mi>
                
                                                            <mml:mi>n</mml:mi>
              
                                                         </mml:msub>
              
                                                         <mml:mo>&#8614;</mml:mo>
              
                                                         <mml:msub>
                
                                                            <mml:mi>E</mml:mi>
                
                                                            <mml:mi>arg</mml:mi>
              
                                                         </mml:msub>
              
                                                         <mml:mo>&#8289;</mml:mo>
              
                                                         <mml:mfenced>
                
                                                            <mml:msub>
                  
                                                               <mml:mi>V</mml:mi>
                  
                                                               <mml:mi>n</mml:mi>
                
                                                            </mml:msub>
                
                                                            <mml:mi>S</mml:mi>
                
                                                            <mml:mi>env</mml:mi>
              
                                                         </mml:mfenced>
            
                                                      </mml:mrow>
          
                                                   </mml:mfenced>
          
                                                   <mml:mo>,</mml:mo>
          
                                                </mml:mtd>
          
                                             </mml:mtr>
          
                                             <mml:mtr>
          
                                                <mml:mtd>
          
                                                   <mml:mrow>
            
                                                      <mml:msub>
              
                                                         <mml:mi>E</mml:mi>
              
                                                         <mml:mi>arg</mml:mi>
            
                                                      </mml:msub>
            
                                                      <mml:mo>&#8289;</mml:mo>
            
                                                      <mml:mfenced>
              
                                                         <mml:mi>content</mml:mi>
              
                                                         <mml:mi>S</mml:mi>
              
                                                         <mml:mi>env</mml:mi>
            
                                                      </mml:mfenced>
          
                                                   </mml:mrow>
          
                                                   <mml:mo minsize="1.5">)</mml:mo>
          
                                                   <mml:mo>,</mml:mo>
          
                                                </mml:mtd>
          
                                             </mml:mtr>
          
                                          </mml:mtable>
        
                                       </mml:mtd>
        
                                    </mml:mtr>
        
                                    <mml:mtr>
        
                                       <mml:mtd>
          
                                          <mml:mi>env</mml:mi>
          
                                          <mml:mo minsize="2">)</mml:mo>
        
                                       </mml:mtd>
        
                                    </mml:mtr>
        
                                 </mml:mtable>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>arg</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo mathvariant="bold">[-</mml:mo>
            
                                       <mml:mi>composition</mml:mi>
            
                                       <mml:mo mathvariant="bold">-]</mml:mo>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>composition</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mi>composition</mml:mi>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
    
                           <mml:mtr>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>arg</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mrow>
            
                                       <mml:mo mathvariant="bold">["</mml:mo>
            
                                       <mml:mi>template</mml:mi>
            
                                       <mml:mo mathvariant="bold">"]</mml:mo>
          
                                    </mml:mrow>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:mo>=</mml:mo>
      
                              </mml:mtd>
      
                              <mml:mtd>
        
                                 <mml:msub>
          
                                    <mml:mi>E</mml:mi>
          
                                    <mml:mi>template</mml:mi>
        
                                 </mml:msub>
        
                                 <mml:mo>&#8289;</mml:mo>
        
                                 <mml:mfenced>
          
                                    <mml:mi>template</mml:mi>
          
                                    <mml:mi>S</mml:mi>
          
                                    <mml:mi>env</mml:mi>
        
                                 </mml:mfenced>
      
                              </mml:mtd>
    
                           </mml:mtr>
  
                        </mml:mtable>

                     </mml:math>
                  </span>
                  <div class="subsec2">
                     <h4>
                        <a name="t3-3-1"/>Environment variables</h4>
                     <p>
            When a filter composition is applied to an input markup stream, both the stream and the current environment
            first get processed by the leftmost filter in the composition, then the results get filtered through the
            second filter in the composition, <i>etc</i>, until the rightmost filter in the
            composition produces the output stream. The environment produced by the last filter is discarded; any
            modifications made to the environment (<i>i.e.</i>, variable assignments) are
            visible only within the innermost enclosing filter composition. Note that the scope of variable assignments is
            dynamic.
          </p>
                     <p>
            The initial environment contains only two variables: <b>$date</b>, containing the
            current date and time, and <b>$topics</b>, which contains the root of the topic
            tree represented as a single element with empty content. The element's attributes map each topic type name to
            the sequence of all topics of that type. The only way to modify the environment is by using the built-in
            filter <b>#let</b>.
          </p>
                  </div>
                  <div class="subsec2">
                     <h4>
                        <a name="t3-3-2"/>User-defined filters and templates</h4>
                     <p>
            The semantics of a user-defined name depends on whether the name represents a <i>filter
              reference</i> or a <i>template reference</i>, as described in section
            <a href="#syntax">3-2</a>. In the former case, the referenced filter gets applied to entire input stream. If
            the name does not represent a filter reference, the input stream is split into individual items, and every
            item is processed separately. The template chosen for processing a particular markup item depends both on
            the given template name and on the markup item type. As a result, the same template reference may be
            resolved to different templates during the processing of an input stream with many items.
          </p>
                  </div>
               </div>
            </div>
            <div class="section">
               <h2>
                  <a name="library"/>Predefined Filters</h2>
               <p>
        This section will present the list of all predefined filters in OMDE. Note that the choice of filters was driven
        by practical concerns. There are many filters that would make perfect sense among these, like <b>#last</b> or <b>#length</b>, but they were not added simply
        because no template has needed them so far.
      </p>
               <p>
        One class of built-in filters operates on purely textual input with no elements. This kind of filters is quite
        common in Web template languages.
      </p>
               <h4>Text Filters</h4>
               <table border="0" cellpadding="8" class="deflist">
                  <tr>
                     <th>Syntax</th>
                     <th>Description</th>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#ascii-code</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Converts each character in the input text into its decimal representation of the character's ASCII code.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#characters</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Wraps each character in the input text into an element named <b>Character</b>, with no attributes.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#escape-html</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Escapes the characters with special meanings in HTML from the input: angle brackets, ampersand, and quotes.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#escape-html-content</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Escapes the characters with special meanings in HTML content from the input: angle brackets and ampersand.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#escape-uri</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Escapes the characters with special meanings in URIs from the input.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#find-topic-id(</b>
                        <i>topic type</i>
                        <b>)</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Scans the input and wraps each substring matching a valid <i>topic id</i> of
              the given <i>topic type</i> found in the input into the appropriate topic
              element.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#match-topic-id(</b>
                        <i>topic type</i>
                        <b>)</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Checks if its entire input matches a valid <i>topic id</i> of the given
              <i>topic type</i>. If so, wraps the input into the appropriate topic element,
              and otherwise drops it.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#lexicographic</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Transform each textual item in the input into its canonical lexicographic form.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#lowercase</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Converts all letters in the input text into lowercase.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#right-aligned (</b>
                        <i>W</i>
                        <b>)</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Aligns the entire input text to the right with the given constant width <i>W</i>.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#substring</b> 
                        <i>S</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates <i>S</i> on the input text into <i>S'</i>, then outputs each occurrence of <i>S'</i> in
              the input text.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#trim-whitespace</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Removes the leading and trailing whitespace from each top-level textual item.
            </p>
                     </td>
                  </tr>
               </table>
               <p>
        The following filters expect a sequence of elements as input, and throw an error if they encounter any text
        outside an element content. Apart form this restriction, they are completely generic: with the exception of
        <b>#distribute</b>, the filters accept any sequence of well-formed elements. This
        generality is possible because all the filters except <b>#distribute</b> and
        <b>#content</b> are higher-level functions. They expect another function as
        argument, and any processing that is specific to the input can be delegated to this argument.
      </p>
               <h4>Element Filters</h4>
               <table border="0" cellpadding="8" class="deflist">
                  <tr>
                     <th>Syntax</th>
                     <th>Description</th>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#content</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Replaces each top-level element in the input stream with its content.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#copy</b> 
                        <i>X</i>?</td>
                     <td valign="top">
                        <p class="first">
              Replaces each element <tt class="code">&lt;a&gt;</tt>
                           <i>C</i>
                           <tt class="code">&lt;/a&gt;</tt>
              in the input with <tt class="code">&lt;a&gt;</tt> 
                           <i>E<sub>arg</sub>(X, <tt class="code">&lt;a&gt;</tt>
                              <i>C</i>
                              <tt class="code">&lt;/a&gt;</tt>)</i> 
                           <tt class="code">&lt;/a&gt;</tt>,
              the element wrapped around the result of evaluation of the given argument <i>X</i> on the element. If the argument is not specified, copies the entire element
              with its original content.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#distribute</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Expects input with two levels of elements and no text. Each top-level element with <i>N</i> children gets replaced by <i>N</i> copies of the
              top-level element with one child each. For example, it would turn
              <tt class="code">&lt;a&gt;&lt;b/&gt;&lt;c/&gt;&lt;/a&gt;</tt> into
              <tt class="code">&lt;a&gt;&lt;b/&gt;&lt;/a&gt;&lt;a&gt;&lt;c/&gt;&lt;/a&gt;</tt>.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#group-by</b> 
                        <i>K</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              For each contiguous sequence of elements <i>S =
                E<sub>1</sub>&#8230;E<sub>N</sub>
                           </i> where <i>E<sub>arg</sub>(K,
                E<sub>i</sub>)</i> evaluates to the same result <i>R</i> for every
              element of the sequence, output a single element named <b>Group</b>, with a
              single attribute named <b>GroupKey</b> and valued <i>R</i>, and with the content <i>S</i>.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#if</b> 
                        <i>T</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              For each element <i>A</i> in the input, evaluates <i>E<sub>arg</sub>(T</i>, <i>A</i>). If the result is
              non-empty, outputs the original element <i>A</i>. If there is no output,
              suppresses the element.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#interpret-path</b> 
                        <i>P</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates the given argument on each input element into <i>P'</i>, then
              outputs the result of evaluation of <i>P'</i> on the element.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#map</b> 
                        <i>F</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates F on each element in the input and outputs all the results.
              Note that <b>#map</b> can be expressed as
              
<div class="codeblock">
                              <pre>
   
                                 <b>#map</b>[-<i>F</i>-] = <b>#copy</b>[-<i>F</i>-]:<b>#content</b>
                              </pre>
                           </div>
            
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#no</b> 
                        <i>T</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Opposite from <b>#if</b>. For each element <i>A</i> in the input, evaluates <i>E<sub>arg</sub>(T,
                A)</i>. If the evaluation produces any output whatsoever, suppresses the element. If the result
              is empty, outputs the original element <i>A</i>.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#mark-duplicates</b> 
                        <i>K</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates the key <i>K</i> on each input element. Whenever the result is the
              same for two consecutive elements, both are individually enclosed into an element named <b>Duplicate</b> with no attributes. Other elements are output unmodified.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#merge-sorted-groups</b> 
                        <i>G</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Expects two streams of group elements, sorted by the value of <b>GroupKey</b>
              attribute: one in its input and the other as the result of evaluation of <i>G</i> on the input. Merges the two streams into a single sorted stream of groups.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#sort-by</b> 
                        <i>K</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates <i>E<sub>arg</sub>(K, A)</i> on each input element <i>A</i>, then sorts the elements by the ascending value of the results.
            </p>
                     </td>
                  </tr>
               </table>
               <p>
        The remaining built-in filters can handle mixed content as their input.
      </p>
               <h4>Mixed Content Filters</h4>
               <table border="0" cellpadding="8" class="deflist">
                  <tr>
                     <th>Syntax</th>
                     <th>Description</th>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#apply</b> 
                        <i>F</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              If the input is not empty, applies F to the entire input. If the input is empty, the output of <b>#apply</b> is empty as well.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#drop-last</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Reproduces the input except for the last character or element, which is dropped.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#first</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Outputs only the first character or element from the input.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#flat-content</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Eliminates all element tags from the input.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#id</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Replicates the input.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#let</b> 
                        <i>var</i> 
                        <b>=</b> 
                        <i>V</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates <i>V</i> on the entire input, stores the result value into variable
              <i>var</i> in the current environment, and replicates its entire input into
              the output.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#lines</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Wraps each line of text in the input into an element named <b>Line</b> with
              no attributes. Top-level elements are treated the same as non-breaking characters.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#log</b>
                     </td>
                     <td valign="top">
                        <p class="first">
              Passes the input through unmodified, logging its XML representation on the standard error stream at the
              same time.
            </p>
                     </td>
                  </tr>
                  <tr>
                     <td valign="top">
                        <b>#match</b> 
                        <i>P</i>
                     </td>
                     <td valign="top">
                        <p class="first">
              Evaluates <i>P</i> on the entire input. If the input equals the result, it
              gets output through, otherwise it is suppressed.
            </p>
                     </td>
                  </tr>
               </table>
            </div>
            <div class="section">
               <h2>
                  <a name="examples"/>Examples</h2>
               <div class="subsec1">
                  <h3>
                     <a name="t5-1"/>Simple Lists</h3>
                  <p>
          Here is a section of the template file <b>ToHTML/Library-topic.tpl</b>:
          
<div class="codeblock">
                        <pre>
   &lt;td bgcolor="#e3e3e3" align=left valign=top&gt;
   &lt;font size=2&gt;
   &lt;b&gt;Functions&lt;/b&gt;&lt;br&gt;
   [-
      #let $TheLibrary=[-#copy-]:
      $topics:@Function:
      #if[-@FunctionLibrary:#match[-$TheLibrary-]-]:
      #sort-by[-@Name:#content:#lexicographic-]:
      #map
      ["&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href="[-
            &lt;TopicFileReference&gt;[-@topic-id-]
         -]"&gt;[-
            @Name:#content:#escape-lessthan-in-html-content
         -]&lt;/a&gt;&lt;br&gt;[-nl-]"]
   -]
   &amp;nbsp;
   &lt;/td&gt;
   &lt;td bgcolor="#e3e3e3" align=left valign=top&gt;
   &lt;font size=2&gt;
   &lt;b&gt;Platforms&lt;/b&gt;&lt;br&gt;
   [-
      @Platform:#sort-by[-@Name:#content:#lexicographic-]:
      #map["&amp;nbsp;&amp;nbsp;&amp;nbsp;[-@Name:#content:#escape-html-content-]&lt;br&gt;[-nl-]"]
   -]
   &amp;nbsp;
   &lt;/td&gt;</pre>
                     </div>
        
                  </p>
                  <p>
          The above template code expects a single <b>Library-topic</b> element in its
          input, and from this input it generates a list of all library functions and all platforms that the library
          works on. The main difference between the two lists is that the list of platforms can be obtained from the
          attribute <b>platforms</b> of the library topic, whereas the links between
          libraries and functions run in the opposite direction: every function topic has an attribute <b>FunctionLibrary</b> pointing to the appropriate library topic, but not the other way
          around. This organization of links makes the documentation maintenance easier: when a new function is added to
          a library, the library topic can be left unmodified.
        </p>
                  <p>
          The list of platforms is relatively easy to generate. The template reference <b>[-nl-]</b> inserts a newline. Inline templates can include literal newline characters
          and span multiple lines, but explicit naming of newlines like this can make them easier to spot.
          
<div class="codeblock">
                        <pre>
   @Platform:#sort-by[-@Name:#content:#lexicographic-]</pre>
                     </div> grabs the list of all platforms, then sorts them
          lexicographically by the platform names. The following line maps an inline template over the list of
          platforms. The inline template formats each platform into HTML.
        </p>
                  <p>
          The function list generation is less straightforward because of the difference in linking. In order to get the
          list, we start with a list of <i>all</i> function topics:
          
<div class="codeblock">
                        <pre>
   $topics:@Function:</pre>
                     </div>
          Then we filter the list to retain only those functions whose <b>FunctionLibrary</b>
          attribute links to our library:
          
<div class="codeblock">
                        <pre>
   #if[-@FunctionLibrary:#match[-$TheLibrary-]-]:</pre>
                     </div>
          The variable <i>TheLibrary</i> has been previously set to the input library by
          the built-in filter <b>#let</b>. This assignment has no effect outside the
          composition. Once we obtain the list of functions, the rest of the pipeline is similar to the one for the
          platform list. The only difference is that we have to insert an HTML hyperlink to the page representing the
          function topic. We abstract from the exact URI of the target page by wrapping it into a <b>TopicFileReference</b> element. This element will be post-processed in the final stage
          of the processing pipeline, where the topics get written as HTML files and the topic references resolved into
          the relative URI paths.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t5-2"/>Grouped Lists</h3>
                  <p>
          The template file <b>generic/Keyword/Alpha-ToHTML.tpl</b> generates the
          alphabetical list of all keyword topics, grouped by first character of the keyword. The template contains the
          following lines that do the bulk of the work:
          
<div class="codeblock">
                        <pre>
   [-
      $topics:@Keyword:#copy[-@Entry-]:#distribute:
      #sort-by[-#flat-content:#lexicographic-]:
      #group-by[-#flat-content:#lexicographic:#first-]:FillGroupsAtoZ:
      #let $Line=[-TopicListToHTMLLine-]:#if[-#content-]:ListItemGroupToHTML
   -] </pre>
                     </div>
        
                  </p>
                  <p>
          This template expects input containing a single <b>Keyword-topic</b> element.
          Because a single keyword topic can describe several related OmniMark language keywords, every keyword topic
          has the potentially multi-valued attribute <b>Entry</b> with all the language
          keywords. These entries appear separately in the output list, but they all link to the same keyword topic.
        </p>
                  <p>
          Because there are many keywords in OmniMark, their alphabetical list is divided into section according to the
          leading character of the keyword. Every keyword section is preceded by a line containing all section links.
          The list is always the same, except the leading character of the current section must be emphasized and must
          not be a link. A further complication is that letters A-Z must all be present in the list; if there is no
          keyword starting with a particular letter, the letter should not be a link and must be made grey.
        </p>
                  <p>
          The first line of the above pipeline,
          
<div class="codeblock">
                        <pre>
   [-
      $topics:@Keyword:#copy[-@Entry-]:#distribute:
   -]</pre>
                     </div>
          prepares the list of all keyword topics, then fills the content of each keyword topic by all keyword entries
          it describes, and finally distributes the top-level <b>Keyword-topic</b> tags so
          they wrap individual entries. The next line first sorts the list of wrapped entries in lexicographic order,
          then groups the sorted entries by their first character, and fills in the missing letters. The latter task is
          accomplished by invoking the shared pipeline <b>generic/FillGroupsAtoZ.path</b>
          with the following contents:
          
<div class="codeblock">
                        <pre>
   #merge-sorted-groups[-
      AtoZ:#characters:#map["[-&lt;Group GroupKey=[-#content-]&gt;[""]-]"]
   -]</pre>
                     </div>
          The content of the referenced template file <b>generic/AtoZ.tpl</b> is simply
          
<div class="codeblock">
                        <pre>
   ABCDEFGHIJKLMNOPQRSTUVWXYZ</pre>
                     </div>
        
                  </p>
                  <p>
          The prepared list of sorted and grouped keyword entries is then used to set variable <i>Line</i> to a marked-up representation of the line containing the section links. The
          value of the variable is prepared by template file <b>TopicListToHTMLLine/Group.tpl</b>, whose content is:
          
<div class="codeblock">
                        <pre>
   [-
      #no[-#content-]:#apply["&lt;font color="#999999"&gt;[-@GroupKey-]&lt;/font&gt;"]
   -][-
      #if[-#content-]:#copy[""]
   -]
          </pre>
                     </div>
        
                  </p>
                  <p>
          Note that the above template discards entire content of all character groups. If a group has no entries inside
          it, its content will be a grey character. If the group was not empty, its content gets removed completely.
        </p>
                  <p>
          With the section link line ready, the pipeline invokes the template in file <b>ListItemGroupToHTML/Group.tpl</b>:
          
<div class="codeblock">
                        <pre>
   &lt;a name="[-@GroupKey:#lowercase-]"&gt;&lt;font color="#9966CC"&gt;
   [-#let $CurrentCharacter=[-@GroupKey-]:$Line:LineToHTML-]&lt;/font&gt;
   &lt;/a&gt;
   &lt;br&gt;
   [-#content:BrokenListItemToHTML-]&lt;br&gt;
   &lt;br&gt;
   &lt;hr&gt;</pre>
                     </div>
        
                  </p>
                  <p>
          The template gets invoked on a single <b>Group</b> element containing all entries
          that start with the same character. The line
          
<div class="codeblock">
                        <pre>
   [-#let $CurrentCharacter=[-@GroupKey-]:$Line:LineToHTML-]&lt;/font&gt;</pre>
                     </div>
          is responsible for generating the HTML links to section anchors, while the line
          
<div class="codeblock">
                        <pre>
   [-#content:BrokenListItemToHTML-]&lt;br&gt;</pre>
                     </div>
          generates the alphabetical list of keyword entries within the section. The template file <b>generic/BrokenListItemToHTML.tpl</b> simply refers to another name
          
<div class="codeblock">
                        <pre>
   &lt;br&gt;[-ListItemToHTML-]</pre>
                     </div>
          which is a directory containing different templates for different types of topics. In our case, the relevant
          file is <b>ListItemToHTML/Keyword-topic.tpl</b>, with the following
          content:
          
<div class="codeblock">
                        <pre>
   &lt;a href="[-&lt;TopicFileReference&gt;[-@topic-id-]-]"&gt;[-
      @Name:#content:#escape-html-content
   -]&lt;/a&gt;</pre>
                     </div>
        
                  </p>
                  <p>
          Finally, the template <b>LineToHTML/Group.tpl</b> receives as input the value of
          the previously prepared variable <i>Line</i>. The template replaces every
          <b>Group</b> element by the HTML link to the corresponding section anchor. The
          key of the group that matches the leading character of the current section, made ready in the variable
          <i>CurrentCharacter</i>, is presented with a larger font and is not linked. This
          template is presented below.
          
<div class="codeblock">
                        <pre>
   [-
      #no[-@GroupKey:#match[-$CurrentCharacter-]-]:
      #apply["&lt;a href="#[-@GroupKey:#lowercase-]"&gt;[-@GroupKey-]&lt;/a&gt;"]
   -][-
      #if[-@GroupKey:#match[-$CurrentCharacter-]-]:
      #apply["&lt;font size="+3" color="#000000"&gt;&lt;strong&gt;[-@GroupKey-]&lt;/strong&gt;&lt;/font&gt;"]
   -] </pre>
                     </div>
     
                  </p>
               </div>
            </div>
            <div class="section">
               <h2>
                  <a name="results"/>Results and Future Work</h2>
               <p>
        The OMDE rewrite has been successfully completed in approximately one man-month. This time
        included the migration of the existing content and verification of the output against the old environment. One
        measure of the achieved level of separation of concerns, the OmniMark code does not specify a single HTML tag.
        On the other side of the fence, the templates have proven intuitive enough to be edited by the technical
        documentation writers, though so far only small modifications have been made.
      </p>
               <div class="subsec1">
                  <h3>
                     <a name="t6-1"/>Code Size</h3>
                  <p>
          The HTML-specific module of the 1998 OMDE contained 5827 lines of OmniMark code, as well as
          4381 lines of HTML templates. The new publishing system consists of 1884 lines of OmniMark code and 2855 lines
          of templates. The strict separation of concerns and the clean model of processing logic reuse will hopefully
          prevent the slow accretion of code that plagued the old system.
        </p>
                  <p>
          The OmniMark code is shorter because it does not contain any presentation-specific logic. Approximately a
          third of the code is spent on the built-in filter implementations, and these filters are heavily used by the
          templates: the average number of uses is 13 and the median is 9. Of course, this result can be viewed in two
          ways: it can be seen as a proof of good factoring of built-in filters, or as an indication of poor factoring
          of templates. Indeed, the original OMDE templates have been only minimally refactored. The
          main reason that the line count of templates has decreased is that, in some cases, two or more similar
          templates have been unified into one in the course of migration. For example, there used to be two separate,
          but almost identical templates describing the current and legacy libraries. These two templates have been
          unified into a single template that uses conditional logic to produce two different outputs. It was felt that
          in this case the benefit of single-sourcing the template in the long term outweighed the disadvantage of the
          increased template complexity.
        </p>
                  <p>
          Even without the proper factoring of templates, the amount of code reuse is surprisingly high for a project
          that did not even have code reuse as an explicit goal. This is especially interesting in light of the fact
          that OMDE has no concept of inheritance. The usual techniques of reuse of the content
          processing logic, like DITA, focus on process inheritance <b>
                        <span style="font-size:85%">
                           <a href="#DITA" name="fromDITA">[
          DITA 1998
        ]</a>
                        </span>
                     </b>. The most likely reason for
          the amount of code reuse is the enforced emphasis on higher-order functions. There has been little research of
          higher-order functions as a vehicle for code reuse <b>
                        <span style="font-size:85%">
                           <a href="#reuse" name="fromreuse">[
          Wadler 1998
        ]</a>
                        </span>
                     </b>, but the observed results
          certainly match the folklore of the functional programming community.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t6-2"/>Performance</h3>
                  <p>
          The system builds the entire documentation in HTML form (19 MB in 1892 pages) in approximately three and half
          minutes on an Athlon 64 X2 3800+ CPU, using a single thread of execution. While the speed could be improved,
          at this point it is far from being a bottleneck.
        </p>
                  <p>
          In order to publish all index pages, the system partially parses 1461 SGML topic files, allocates 354,902
          coroutines, of which at most 39 are used at the same time, and performs 20,943,723 coroutine context switches.
          To publish all current topics, OMDE performs 15,068 parses of SGML files (some files are
           parsed more than once), 4,743,939 coroutines allocations (at most 43 simultaneously), and
          121,354,197 coroutine switches. The latter task takes three minutes, the bulk of the total processing time.
          These statistics show that pipelined processing of markup streams has a substantial price, and fast coroutine
          creation and context switching is of paramount importance <b>
                        <span style="font-size:85%">
                           <a href="#Coroutines" name="fromCoroutines">[
          Wilmott 2003
        ]</a>
                        </span>
                     </b>. If we, rather
          optimistically, assume the thread creation time of 10 microseconds and thread switching time of 1 microsecond
          <b>
                        <span style="font-size:85%">
                           <a href="#Performance" name="fromPerformance">[
          Corsaro 2003
        ]</a>
                        </span>
                     </b>, the total overhead for the last task would be over two and half minutes if
          threads were used instead of coroutines.
        </p>
               </div>
               <div class="subsec1">
                  <h3>
                     <a name="t6-3"/>Future Work</h3>
                  <p>
          At this point the OMDE project, though far from perfect, has achieved its initial goals.
          The next development iteration will probably concentrate on the generation of alternative output formats:
          various subset of the documentation for different audiences, as well as output in PDF form. It will be
          interesting to see what level of template reuse can be achieved when there are multiple output targets.
        </p>
               </div>
            </div>
            <div class="section">
               <h2>
                  <a name="related"/>Related Work</h2>
               <p>
        There are too many existing template languages, engines and systems to list here. Some of them have various
        similarities to the one presented here. For example, Smarty <b>
                     <span style="font-size:85%">
                        <a href="#Smarty" name="fromSmarty">[
          Smarty
        ]</a>
                     </span>
                  </b>, Django <b>
                     <span style="font-size:85%">
                        <a href="#Django" name="fromDjango">[
          Django
        ]</a>
                     </span>
                  </b> and StringTemplate <b>
                     <span style="font-size:85%">
                        <a href="#StringTemplate" name="fromStringTemplate">[
          Parr 2006
        ]</a>
                     </span>
                  </b> all support text filters. Django and
        StringTemplate allow filter composition. Some of the built-in filters in Django transform structured inputs.
        Django does not emphasize the use of filters as higher-order functions; it provides a number of control
        constructs instead. The StringTemplate language is more like OMDE in its minimalism, but its built-in filters do
        not appear to operate on structured values.
      </p>
               <p>
        The main difference between OMDE and other template languages appears to be in the choice of
        the data model. Most template languages use an input data model that matches the data structures available in
        the host language. Functional languages specifically designed for markup processing, like XSLT <b>
                     <span style="font-size:85%">
                        <a href="#XSLT" name="fromXSLT">[
          XSLT 1999
        ]</a>
                     </span>
                  </b> and XQuery <b>
                     <span style="font-size:85%">
                        <a href="#XQuery" name="fromXQuery">[
          XQuery 2007
        ]</a>
                     </span>
                  </b>, on the other hand, have a markup-based data model but
        are not template languages. There has been work on template languages developed on top of XSLT. One example is
        TemplateXSLT <b>
                     <span style="font-size:85%">
                        <a href="#TemplateXSLT" name="fromTemplateXSLT">[
          TemplateXSLT 2002
        ]</a>
                     </span>
                  </b>, but at least in this case the template language design is
        traditional in that it provides explicit control constructs instead of taking advantage of the data model; it is
        not data-driven.
      </p>
               <p>
        One significant obstacle in using XSLT as the host language is that its data model is based on trees, not
        streams. While this is not a problem for small documents (as in the OMDE project presented here) and short
        pipelines, this model does not scale well because it requires the entire input tree to be constructed in each
        phase of the pipeline. The benefits of the streaming model are explained in more depth in
        <b>
                     <span style="font-size:85%">
                        <a href="#FBP" name="fromFBP">[
          Morrison 1994
        ]</a>
                     </span>
                  </b> and <b>
                     <span style="font-size:85%">
                        <a href="#Coroutines" name="fromCoroutines">[
          Wilmott 2003
        ]</a>
                     </span>
                  </b>.
      </p>
               <p>
        Functional programming techniques have been applied to markup processing plenty of times. The Haskell library
        HaXML <b>
                     <span style="font-size:85%">
                        <a href="#HaXML" name="fromHaXML">[
          HaXML 1999
        ]</a>
                     </span>
                  </b>, for example, provides higher order functions (combinators) for processing XML
        and HTML trees. In the more mainstream context of XSLT, functional programming extensions with higher-order
        functions have been implemented by FXSLT <b>
                     <span style="font-size:85%">
                        <a href="#FXSLT" name="fromFXSLT">[
          Novatchev 2006
        ]</a>
                     </span>
                  </b>.
      </p>
               <p>
        The pipeline processing model has been used for markup processing many times before <b>
                     <span style="font-size:85%">
                        <a href="#Transmorpher" name="fromTransmorpher">[
          Transmorpher 2001
        ]</a>
                     </span>
                  </b> 
                  <b>
                     <span style="font-size:85%">
                        <a href="#XPipe" name="fromXPipe">[
          XPipe 2002
        ]</a>
                     </span>
                  </b> 
                  <b>
                     <span style="font-size:85%">
                        <a href="#XML-Pipeline" name="fromXML-Pipeline">[
          XML Pipeline 2002
        ]</a>
                     </span>
                  </b>. Most of the current XML
        pipeline languages rely on components written in a lower-level programming language like XSLT, though some also
        provide a set of higher-level functions for combining the components. From this perspective, the main novelty
        presented in this paper is the use of templates for defining the primitive pipeline components instead of XSLT.
      </p>
               <p>
        The author's previous work <b>
                     <span style="font-size:85%">
                        <a href="#Combinators" name="fromCombinators">[
          Combinators 2006
        ]</a>
                     </span>
                  </b>, while based on the same principles of streaming and
        higher-order functions, uses a more expressive language because it is not limited to markup processing. The
        present work restricts the data model in order to simplify the processing language.
      </p>
            </div>
            <div class="section">
               <h2>
                  <a name="conclusion"/>Conclusion</h2>
               <p>
        We have shown how the use of concepts of higher-level functional programming, together with a markup-based data
        model, can make complex control structures unnecessary in a template language. Furthermore, if we use the same
        data model both for input and output data, the resulting templates become composable. The concept has been
        successfully implemented and tested in a production system for publishing technical documentation.
      </p>
            </div>
            <h3 class="footnotes">Notes</h3>
            <table class="footnotes">
               <tr>
                  <td class="ftnote-num" valign="top" width="10%" align="right">
                     <p class="first">
                        <a href="#fromd0e85" name="tod0e85">
                           <b>1.</b>
                        </a>
                     </p>
                  </td>
                  <td valign="top">
                     <p class="first">
              Omission of escaping has many times in the past led to security vulnerabilities. The most notorious
              variant is probably the vulnerability to SQL injection attacks. <b>
                           <span style="font-size:85%">
                              <a href="#injection" name="frominjection">[
          Su 2006
        ]</a>
                           </span>
                        </b>
            
                     </p>
                  </td>
               </tr>
            </table>
            <hr class="hr"/>
            <h3>
               <i>Acknowledgments</i>
            </h3>
            <p class="first">
        I want to thank Jacques L&#233;gar&#233; and Helen St. Denis for finding the time to read the paper and
        point out the problems, and the Stilo Corporation for giving me the time to write it.
      </p>
            <hr class="hr"/>
            <h3>
               <i>Bibliography</i>
            </h3>
            <p>
               <b>
                  <a name="FP" href="#fromFP">[
          Backus 1978
        ] </a>
               </b> 
          Backus, J., <i>Can programming be liberated from the von Neumann style?: a functional
            style and its algebra of programs</i> Commun. ACM 21, 8 (Aug. 1978), 613-641.
        </p>
            <p>
               <b>
                  <a name="Microdocument" href="#fromMicrodocument">[
          Baker 1998
        ] </a>
               </b> 
          Mark Baker, <i>Designing Microdocument Architecture systems</i>,
          <a href="http://www.infoloom.com/gcaconfs/WEB/paris98/baker.HTM#" target="_blank">http://www.infoloom.com/gcaconfs/WEB/paris98/baker.HTM#</a>, SGML/XML Europe 1998, Paris
        </p>
            <p>
               <b>
                  <a name="Combinators" href="#fromCombinators">[
          Combinators 2006
        ] </a>
               </b> 
          Mario Bla&#382;evi&#263;, <i>Streaming component combinators</i>, Extreme
          Markup Languages, 2006.
        </p>
            <p>
               <b>
                  <a name="Performance" href="#fromPerformance">[
          Corsaro 2003
        ] </a>
               </b> 
          Angelo Corsaro, Douglas C. Schmidt, <i>The Design and Performance of Real-time Java
            Middleware</i>, IEEE Transactions on Parallel and Distributed Systems. Vol. 14, no. 11, pp.
          1155-1167. Nov. 2003
        </p>
            <p>
               <b>
                  <a name="DITA" href="#fromDITA">[
          DITA 1998
        ] </a>
               </b> 
          Priestley, M., <i>DITA XML: a reuse by reference architecture for technical
            documentation</i> In Proceedings of the 19th Annual international Conference on Computer
          Documentation (Sante Fe, New Mexico, USA, October 21 - 24, 2001). SIGDOC '01. ACM Press, New York, NY,
          152-156.
        </p>
            <p>
               <b>
                  <a name="Django" href="#fromDjango">[
          Django
        ] </a>
               </b> 
          Lawrence Journal-World, <i>The Django Template Language</i>,
          <a href="http://www.djangoproject.com/documentation/templates/" target="_blank">http://www.djangoproject.com/documentation/templates/</a>, 2007.
        </p>
            <p>
               <b>
                  <a name="Haskell" href="#fromHaskell">[
          Haskell 2003
        ] </a>
               </b> 
          S. Peyton Jones, editor, Haskell 98 Language and Libraries: The Revised Report, Cambridge University Press,
          2003, <a href="http://haskell.org/" target="_blank">http://haskell.org/</a>
        
            </p>
            <p>
               <b>
                  <a name="HaXML" href="#fromHaXML">[
          HaXML 1999
        ] </a>
               </b> 
          Malcolm Wallace, Colin Runciman, <i>Haskell and XML: Generic Combinators or Type-Based
            Translation?</i>, International Conference on Functional Programming, 1999.
        </p>
            <p>
               <b>
                  <a name="FBP" href="#fromFBP">[
          Morrison 1994
        ] </a>
               </b> 
          John Paul Morrison, <i>Flow Based Programming</i>, Van Nostrand Reinhold, 1994.
        </p>
            <p>
               <b>
                  <a name="FXSLT" href="#fromFXSLT">[
          Novatchev 2006
        ] </a>
               </b> 
          Dimitre Novatchev, <i>Higher-Order Functional Programming with XSLT 2.0 and
            FXSL</i>, Extreme Markup Languages, 2006.
        </p>
            <p>
               <b>
                  <a name="OmniMark" href="#fromOmniMark">[
          OmniMark 2007
        ] </a>
               </b> 
          
               <i>OmniMark language documentation</i>,
          <a href="http://developers.stilo.com/docs-extract/html/index.htm" target="_blank">http://developers.stilo.com/docs-extract/html/index.htm</a>
        
            </p>
            <p>
               <b>
                  <a name="MVC" href="#fromMVC">[
          Parr 2004
        ] </a>
               </b> 
          Parr, T. J., <i>Enforcing strict model-view separation in template engines</i>,
          In Proceedings of the 13th international Conference on World Wide Web (New York, NY, USA, May 17 - 20, 2004).
          WWW '04. ACM Press, New York, NY, 224-233.
        </p>
            <p>
               <b>
                  <a name="StringTemplate" href="#fromStringTemplate">[
          Parr 2006
        ] </a>
               </b> 
          Terence Parr, <i>A Functional Language For Generating Structured Text</i>,
          <a href="http://www.cs.usfca.edu/~parrt/papers/ST.pdf" target="_blank">http://www.cs.usfca.edu/~parrt/papers/ST.pdf</a>, University of San Francisco, 2006.
        </p>
            <p>
               <b>
                  <a name="PHP" href="#fromPHP">[
          PHP
        ] </a>
               </b> 
          
               <i>PHP: Hypertext Preprocessor</i>, <a href="http://www.php.net/" target="_blank">http://www.php.net/</a>
        
            </p>
            <p>
               <b>
                  <a name="Smarty" href="#fromSmarty">[
          Smarty
        ] </a>
               </b> 
          
               <i>Smarty: Template Engine</i>, <a href="http://smarty.php.net/" target="_blank">http://smarty.php.net/</a>
        
            </p>
            <p>
               <b>
                  <a name="injection" href="#frominjection">[
          Su 2006
        ] </a>
               </b> 
          Su, Z., Wassermann, G., <i>The essence of command injection attacks in web
            applications</i> In Conference Record of the 33rd ACM SIGPLAN-SIGACT Symposium on Principles of
          Programming Languages (Charleston, South Carolina, USA, January 11 - 13, 2006). POPL '06. ACM Press, New York,
          NY, 372-382.
        </p>
            <p>
               <b>
                  <a name="TemplateXSLT" href="#fromTemplateXSLT">[
          TemplateXSLT 2002
        ] </a>
               </b> 
          Jason Diamond, <i>Template Languages in XSLT</i>,
          <a href="http://www.xml.com/pub/a/2002/03/27/templatexslt.html" target="_blank">http://www.xml.com/pub/a/2002/03/27/templatexslt.html</a> XML.com, O'Reilly Media, Inc., 2006
        </p>
            <p>
               <b>
                  <a name="Transmorpher" href="#fromTransmorpher">[
          Transmorpher 2001
        ] </a>
               </b> 
          J&#233;r&#244;me Euzenat, Laurent Tardif, <i>XML Transformation Flow
            Processing</i>, Extreme Markup Languages, 2001.
        </p>
            <p>
               <b>
                  <a name="reuse" href="#fromreuse">[
          Wadler 1998
        ] </a>
               </b> 
          Wadler, P., <i>How to solve the reuse problem? Functional programming</i>,
          Proceedings. Fifth International Conference on Software Reuse, 1998.
        </p>
            <p>
               <b>
                  <a name="Coroutines" href="#fromCoroutines">[
          Wilmott 2003
        ] </a>
               </b> 
          Sam Wilmott, <i>What programming language designers should do to help markup
            processing</i>, Extreme Markup Languages, 2003.
        </p>
            <p>
               <b>
                  <a name="XML-Pipeline" href="#fromXML-Pipeline">[
          XML Pipeline 2002
        ] </a>
               </b> 
          
               <i>XML Pipeline Definition Language Version 1.0 </i>,
          <a href="http://www.w3.org/TR/2002/NOTE-xml-pipeline-20020228/" target="_blank">http://www.w3.org/TR/2002/NOTE-xml-pipeline-20020228/</a>
        
            </p>
            <p>
               <b>
                  <a name="XPipe" href="#fromXPipe">[
          XPipe 2002
        ] </a>
               </b> 
          
               <i>XPipe presentation at XML SIG NY</i>,
          <a href="http://xpipe.sourceforge.net/BinaryStuff/xpipeny.ppt" target="_blank">http://xpipe.sourceforge.net/BinaryStuff/xpipeny.ppt</a>, 2002.
        </p>
            <p>
               <b>
                  <a name="XQuery" href="#fromXQuery">[
          XQuery 2007
        ] </a>
               </b> 
          
               <i>XQuery 1.0: An XML Query Language</i>,
          <a href="http://www.w3.org/TR/xquery/" target="_blank">http://www.w3.org/TR/xquery/</a>
        
            </p>
            <p>
               <b>
                  <a name="XSLT" href="#fromXSLT">[
          XSLT 1999
        ] </a>
               </b> 
          
               <i>XSL Transformations (XSLT) Version 1.0</i>,
          <a href="http://www.w3.org/TR/xslt/" target="_blank">http://www.w3.org/TR/xslt/</a>
        
            </p>
            <hr class="hr"/>
            <hr class="hr"/>
            <p class="footertitle">Composable Templates</p>
            <address>Mario Bla&#382;evi&#263; [Senior Software Developer, Stilo International]</address>
            <hr class="hr"/>
         </div>
      </div>
   </body>
</html>
