![]() |
Many web application frameworks provide a way of templating, write some boilerplate
HTML and fill in the details at the moment a page is requested. Apart from
that, a page may contains lots of external scripts, stylesheets, images and
fonts. For these two tasks libzeep comes with a template_processor
class.
Starting with the second task just mentioned, the template_processor
takes a docroot
parameter in its constructor. This docroot
is the location on disk where files are located. But it is also possible
to build libzeep with in-memory resources by using mrc
.
Have a look at the example code for usage.
The load_file
member of template_processor
loads a file from disk (or compiled resources), the file_time
member can be used to get the file time of a file. This can be used to generate
304 not modified
replies instead.
The load_template
member loads a template file from docroot and parses the XML contained in
this file into a zeep::xml::document
.
Since we're using a XML parser/library to load template, they should be strict XMTML. It is possible to make these files somewhat HTML 5 like by adding the doctype
<!DOCTYPE html SYSTEM "about:legacy-compat">
The tags inside a template can be processed using a tag_processor. Tag processors are linked to element and attributes in the template using XML namespaces.
The method create_reply_from_template
can be used to convert a template into a reply using the data store in a
scope
.
Libzeep comes with two tag_processor implementations, the first tag_processor_v1
is a legacy one and should probably not be used in new code. The second,
tag_processor_v2
,
is inspired by https://www.thymeleaf.org.
el
is the abbreviation for Expression Language.
It is a script language that tries to be like http://en.wikipedia.org/wiki/Unified_Expression_Language.
libzeep comes with code to evaluate el
expressions.
The language has the concept of variables and these can be created in the
C++ code using the json::element
class. Variables created this way are then stored in a scope
object and passed along
to the processing code.
To give an example:
zeep::json::element ints{ { { "value", 1 } }, { { "value", 2 } } }; scope.put("ints", ints);
And then you can process some expression language
construct
like this:
auto s = zeep::http::evaluate_el(scope, "|1: ${ints[0].value}, 2: ${ints[1].value}|");
And if you then print out the result it should give you something like:
"1: 1, 2: 2"
el
syntax
Most often you will use simple expressions:
Table 3.2. Simple expressions
expression |
evaluates to |
---|---|
|
variable |
|
selection variable (lookup is done in the scope of variables
that were selected with |
|
link URL |
|
fragment |
|
message (not supported yet in libzeep) |
The language has literals:
Table 3.3. Literals
expression |
evaluates to |
---|---|
|
Text literal |
|
Numeric literal, note that scientific notation is not supported |
|
Boolean literal |
|
Null literal |
|
token |
Text operations supported are:
Table 3.4. Text operations
construct |
description |
---|---|
|
concatenation, result is 'a b' |
|
literal substitution, if variable user contains 'scott', result is 'hello scott' |
Operators:
Table 3.5. operators
operators |
type |
---|---|
|
binary operators for standard arithmetic operations |
|
unary operator, minus sign |
|
binary operators for standard boolean operations |
|
unary operators, negate |
|
operators to compare values |
|
operators to check for equality |
|
conditional operator: if a then return b else null |
|
conditional operator: if a then return b else return c |
|
conditional operator: if a then return a else return b |
When using variables, accessing their content follows the same rules as
in Javascript. Arrays have a member function length
.
A few predefined utility objects are predefined. These are #dates, #numbers, #request and #security.
Table 3.6. Predefined objects and their methods
object.method |
Description |
---|---|
|
This method takes two parameters, a preferrably ISO formatted
date and a format string. The result will be the output of |
|
This method takes up to three parameters, a number that needs to be formatted, an int_digits parameter that specifies the minimum number of integral digits to use and a decimals parameter that specifies how many decimals to use. The number is formatted using the locale matching the language specified in the Accept HTTP request header. However, if that locale is not available the default locale is used. Defaults for int_digits is 1 and decimals is 0.
Example output: |
|
This method takes up to two parameters, a number that needs to be formatted, and a decimals parameter that specifies how many decimals to use. The number is divided by 1024 until it fits three int digits and the suffix is adjusted accordingly. Default for decimals is 0.
Example output: |
|
Returns the original URI in the HTTP request. |
|
Returns whether the uses has successfully logged in. |
|
Returns the username for the current user. |
|
Returns whether the uses has the role as specified by the parameter. |
This tag_processor works on tags, mostly. As opposed to tag_processor_v2
which works on attributes mainly. The tags are in a separate XML namespace.
You can change this name space using the ns
parameter in the
constructor, the default is http://www.hekkelman.com/libzeep/m1
.
There are several predefined processing tags which are summarized below.
There used to be also a way to add your own processing tags using an add_processor
method but that has been dropped.
Table 3.7. List of predefined processing tags
tag name (without prefix) |
Description |
Example |
---|---|---|
include |
Takes one parameter named |
|
if |
Takes one parameter named |
<zeep:if test="${not empty name}"> Hello ${name} </zeep:if> |
iterate |
Takes two parameters, |
<ul><zeep:iterate collection="${names}" var="name"> <li>${name}</li> </zeep:iterate></ul> |
for |
Takes three parameters. The parameters |
<zeep:for begin="1" end="3" var="i"> ${i}, </zeep:for> |
number |
Format the number in the |
<zeep:number n="1024" f="0.00#B"/> Will output 1K |
options |
This tag will insert multiple |
<zeep:options collection="${names}" value="id" label="fullName" selected="1" /> |
option |
Generate a single |
<zeep:option value="1" selected="${user}"> John Doe </zeep:option> |
checkbox |
Create an |
<zeep:checkbox name='cb1' checked='${true}'> Check me </zeep:checkbox> |
url |
The url processing tag creates a new variable in the current
scope with the name as specified in the |
<zeep:url var="next"> <zeep:param name='page' value='${page + 1}'/> <zeep:url> <a href="${next}">Next page</a> |
param |
see |
|
embed |
This tag takes the content of the |
<zeep:embed var="<em>hello, world!</em>"/> |
Tag processor version 2 is an implementation of the documentation for Thymeleaf. This documententation is a bit sparse, for now you might be better off reading the one at the Thymeleaf site.
There are some notable differences between Thymeleaf and libzeep though,
libzeep does not support the concept of messages
yet,
so using this for localization is not going to work. Furthermore, the Thymeleaf
library is written in Java and assumes all data constructs are Java object.
Of course that is different in libzeep.
There is only one tag this tag processor processes, which is <z:block>
,
for the rest this processor only processes attributes.
Some attributes are treated special, these are listed below. For the other
tags the general rule is that if the tag has the prefix for the v2
namespace, the value of the attribute will be evaluated and the result
will be placed in an attribute without the prefix. Possibly overwriting
an already existing attribute with that name.
So, e.g. if you have
<span id="one" z:id="${id}"/>
and the variable id
contains 'two'
the result will be
<span id="two"/>
Table 3.8. processed attributes