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 substitution
Content of the given expression will be interpreted as template and any mtl: directive in it will be executed. The expression should have 'markup event stream' type.
mtl:evaluate
<mtl:evaluate expression="simple_expression"/>
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 | <simple_expression> = <simple_expression>
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 expression="post of 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;