Markup Templates Engine

Markup Templates Engine reads XML template documents and generates XML or HTML5/XHTML5 documents.

XML Template Language

Template Directives

Conditional Sections

mtl:if, mtl:elsif, mtl:else
<mtl:if expression="boolean_expression">
  ...
<mtl:elsif expression="boolean_expression"/>
  ...
<mtl:else/>
  ...
</mtl:if>

Looping

mtl:for
<mtl:for expression="iterating_expression">
  ...
</mtl:for>

Template Attributes

mtl:boolean.FOO

<element mtl:boolean.FOO="boolean_expression"/>

If boolean_expression is True generate <element FOO="FOO"/>, otherwise generate <element/>

Expressions

Simple expressions

simple_expression ::= <variable>
 | <simple_expression>.<member>

Iterating expressions

iterating_expression ::= <variable> of <simple_expression>

Boolean expressions

boolean_expression ::= <simple_expression>
 | not <boolean_expression>
 | <simple_expression> is null
 | <simple_expression> is not null

Use template processor in application

To use Template Processor in application it need to be connected to SAX content and lexical events source (for instance to XML_Simple_Reader) and to SAX content and lexical events consumer (for instance to XML_Pretty_Writer of HTML5_Writer).

Application defines set of parameters by XML_Template_Processor's Set_Parameter subprogram. Values are passed using holders mechanism. Supported types are:

Type Holder package Comment
boolean League.Holders.Booleans used as condition in 'if' directives
string League.Holders substituted literally inside character data and attribute value
markup event stream XML.Templates.Streams.Holders substituted as SAX event stream inside character data
JSON object League.Holders.JSON_Objects members are accessible by selector expression
JSON array League.Holders.JSON_Array elements are accessible by 'for' directive

Here is small example, it reads page.xml.tmpl file, process it end outputs result to standard output.

with Ada.Wide_Wide_Text_IO;

with League.Holders.Booleans;
with League.Holders.JSON_Arrays;
with League.JSON.Arrays;
with League.JSON.Objects;
with League.JSON.Values;
with League.Strings;
with XML.SAX.Input_Sources.Streams.Files;
with XML.SAX.Output_Destinations.Strings;
with XML.SAX.Pretty_Writers;
with XML.SAX.Simple_Readers;
with XML.Templates.Processors;

procedure Main is
   Input  : aliased XML.SAX.Input_Sources.Streams.Files.File_Input_Source;
   Reader : aliased XML.SAX.Simple_Readers.Simple_Reader;
   Filter : aliased XML.Templates.Processors.Template_Processor;
   Writer : aliased XML.SAX.Pretty_Writers.XML_Pretty_Writer;
   Output : aliased XML.SAX.Output_Destinations.Strings.String_Output_Destination;
   Post   : League.JSON.Objects.JSON_Object;
   Posts  : League.JSON.Arrays.JSON_Array;

begin
   Input.Open_By_File_Name
    (League.Strings.To_Universal_String ("page.xml.tmpl"));

   --  Configure reader.

   Reader.Set_Input_Source (Input'Unchecked_Access);
   Reader.Set_Content_Handler (Filter'Unchecked_Access);
   Reader.Set_Lexical_Handler (Filter'Unchecked_Access);

   --  Configure template processor.

   Filter.Set_Content_Handler (Writer'Unchecked_Access);
   Filter.Set_Lexical_Handler (Writer'Unchecked_Access);

   Filter.Set_Parameter
    (League.Strings.To_Universal_String ("title"),
     League.Holders.To_Holder
      (League.Strings.To_Universal_String ("Page title")));
   Filter.Set_Parameter
    (League.Strings.To_Universal_String ("is_admin"),
     League.Holders.Booleans.To_Holder (True));

   Post.Insert
    (League.Strings.To_Universal_String ("user"),
     League.JSON.Values.To_JSON_Value
      (League.Strings.To_Universal_String ("first")));
   Post.Insert
    (League.Strings.To_Universal_String ("post"),
     League.JSON.Values.To_JSON_Value
      (League.Strings.To_Universal_String
        ("This is first post from first user")));
   Posts.Append (Post.To_JSON_Value);
   Post.Insert
    (League.Strings.To_Universal_String ("user"),
     League.JSON.Values.To_JSON_Value
      (League.Strings.To_Universal_String ("second")));
   Post.Insert
    (League.Strings.To_Universal_String ("post"),
     League.JSON.Values.To_JSON_Value
      (League.Strings.To_Universal_String
        ("This is first post from second user")));
   Posts.Append (Post.To_JSON_Value);
   Filter.Set_Parameter
    (League.Strings.To_Universal_String ("posts"),
     League.Holders.JSON_Arrays.To_Holder (Posts));

   --  Configure XML writer.

   Writer.Set_Output_Destination (Output'Unchecked_Access);

   --  Process template.

   Reader.Parse;

   --  Output result.

   Ada.Wide_Wide_Text_IO.Put (Output.Get_Text.To_Wide_Wide_String);
end Main;

Here is content of page.xml.tmpl file:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:mtl="http://forge.ada-ru.org/matreshka/template">
  <head><title>${title}</title></head>
  <body>
    <mtl:if test="is_admin">
      <p>WARNING! YOU ARE ADMIN!</p>
    </mtl:if>
    <table>
      <tbody>
        <mtl:for each="post in posts">
          <tr>
            <td>${post.user}</td>
            <td>${post.post}</td>
          </tr>
        </mtl:for>
      </tbody>
    </table>
  </body>
</html>

and generated output:

<?xml version='1.0'?><html xmlns='http://www.w3.org/1999/xhtml'>
  <head><title>Page title</title></head>
  <body>
    
      <p>WARNING! YOU ARE ADMIN!</p>
    
    <table>
      <tbody>
        
          <tr>
            <td>first</td>
            <td>This is first post from first user</td>
          </tr>
        
          <tr>
            <td>second</td>
            <td>This is first post from second user</td>
          </tr>
        
      </tbody>
    </table>
  </body>
</html>

Generating of HTML5 Documents

HTML5 Writer can be used to produce optimized HTML5 documents by using most compact syntax form for attribute values and omitting optional tags.

Below is an example of its use with XML Simple Reader (it can obtain stream of SAX events from other sources too, for instance from templates processor):

with Ada.Text_IO;

with League.Strings;
with XML.SAX.Input_Sources.Streams.Files;
with XML.SAX.Output_Destinations.Strings;
with XML.SAX.Simple_Readers;
with XML.SAX.HTML5_Writers;

procedure Main is
   Input  : aliased XML.SAX.Input_Sources.Streams.Files.File_Input_Source;
   Reader : aliased XML.SAX.Simple_Readers.Simple_Reader;
   Writer : aliased XML.SAX.HTML5_Writers.HTML5_Writer;
   Output : aliased XML.SAX.Output_Destinations.Strings.String_Output_Destination;

begin
   Input.Open_By_File_Name
    (League.Strings.To_Universal_String ("page.tmpl"));

   --  Configure reader.

   Reader.Set_Input_Source (Input'Unchecked_Access);
   Reader.Set_Content_Handler (Writer'Unchecked_Access);
   Reader.Set_Lexical_Handler (Writer'Unchecked_Access);

   --  Configure HTML5 writer.

   Writer.Set_Output_Destination (Output'Unchecked_Access);

   --  Process template.

   Reader.Parse;

   --  Output result.

   Ada.Text_IO.Put (Output.Get_Text.To_UTF_8_String);
end Main;
Last modified 9 months ago Last modified on Dec 22, 2016, 3:45:01 PM