Fork me on GitHub

Template

  • Simple & Friendly
  • High-Performance
  • High-Quality

Syntax

HTTL This document details the core functionality, if you intend to use HTTL development, please read.

test sample template syntax: src/test/resources/comment/templates

See test output results same file: src/test/resources/comment/results

basic syntax

and Velocity similar and different points see:Velocity comparison


	
		#if (books)
		
			#for (Book book: books)
			
			#end
		
$ {book.title}
#end

comment syntax

instruction on both sides can put HTML comments, to avoid interference with native HTML page.

HTTL at parse time, it will automatically remove the comment symbol Directive edge of HTML. (The default is on filter)


	
		
		
$ {book.title}
Using HTML

default comment character: (default, no configuration)

comment.left=<!--
comment.right=-->

If you use HTTL generate Java code, you can also read:

comment.left=/*
comment.right=*/

attribute syntax

based Html tag attributes: (instruction and expressions with the same comment syntax)


	
		
$ {book.title}

need to configure:

template.filters + = httl.spi.filters.AttributeSyntaxFilter

attribute syntax need to use jericho packet parsing HTML tags:

jericho-html-3.1.jar


net.htmlparser.jericho
jericho-html
3.1

conflict if the property and other frameworks, you can add the namespace:

attribute.namespace = httl

namespace wording such as:


place without the label, you can use the above comment syntax.

Compatible Syntax

HTTL offer compatible Velocity syntax support, just configuration: (from version 1.0.8 supports)

template.filters + = httl.spi.filters.VelocitySyntaxFilter

in compatibility mode, you can still use the standard syntax HTTL facilitate the gradual migration.

directive

HTTL only #set, #if, #else, #for, #break, #macro six directives, as well as output placeholders and notes escape, keeping the minimum instruction set, and they will not increase the instruction.

does not recognize the command name will be text output, such as HTML color: # FF00EE.

If the command name and text

phase, such as: #elseTEXT, available without parameters separated by parentheses, eg: #if (x) AAA #else() BBB #end() CCC

output instructions

$ {} filter output

output expression evaluates, and filtered, such as: filter variable HTML tags.

Format:
$ {Expression}

Example:
$ {User.name}

Note: HTTL default opened EscapeXmlFilter, to prevent HTML injection attacks, see:Security Samples. If you need stronger filtering, please self-fulfilling Filter, and configured to value.filters. Here the runtime hotspot note performance.

If the output variable of type Template, then the default is not filtered, for example: $ {include ("foo.httl")}

$! {} does not filter output

expression evaluates as output, without any filtering, usually used to output HTML fragment.

Format:
$! {Expression}

Example:
$! {Body}

Note: Do not filter output, make sure that the content is the developer of secure content determined, not by the user-submitted content, in order to prevent HTML injection attacks, see:Security Samples.

variable command

#set variable type

declare a variable of type, other types of variables within the template based on this type of derivation.

Format:
#set (type name, type name)

Example:
#set (User user, Listbooks)

Note: only supports List and Map of a generic, multi-level generic able to resolve, but not derived.

If there is a global variable can be used to configure the global import variable type declaration, there is no need for each template declaration:

import.variables + = User loginUser

default has been imported: (can be used directly in the template)

import.variables = Context parent, Template super, Template this, Engine engine
HTTL

If you are using the built-in MVC integration, integration has been in default import some common variables associated, as describedConfiguration - Import variable type declaration< / a>a.

If undeclared variable, default Object: (If it is a direct output variables, may declare type)

default.variable.type = java.lang.Object
$ {obj} // direct output, do not take the property, do not do arithmetic, no declared type

If your system, most of the String type operation, you can also change the default type String:

default.variable.type = java.lang.String

repeatedly to set the variable's type, if the type of parent-child relationship to subtype Priority:

#set (ParentClass var1)
#set (ChildClass var1)

regardless of the order, all with subtype Priority:

#set (ChildClass var1)
#set (ParentClass var1)

if it is two completely different types, error:

#set (OriginClass var1)
#set (DiffrentClass var1)

#set variable assignment

the expression evaluates into variable.

Format:
#set (name = expression)
#set (type name = expression)

#set (name: = expression)
#set (type name: = expression)

Example:
#set (price = book.price * book.discount)
#set (int price = book.price * book.discount)

Note that in order to simplify the writing template, #set template variables are all valid, no restrictions within the instruction in the block:

#if (xxx)
#set (var="value") // Variable full template effectively, rather than if the block is valid
#end
$ {Var} // can be accessed within the block if the value of var

not like Java:

#set (var = null)
#if (xxx)
#set (var="value")
#end
$ {Var}

type declarations, and can be used as casts, for example:

#set (Book book = bookentry.value)

If bookentry.value type of loss, the above wording can recover book type.

a set command may also have more than one type declarations or assignments, separated by commas, but the type declaration and assignment to write separately, such as:

 #set (User user, List  books)
#set (price = book.price, discount = book.discount)

assignment will generate a local variable, it writes the current Context in If there include() sub-template, the template can also be in the child read the variable.

If you want to get in the parent template, template variables include the child, or you want to get after rendering the template variables Due to template rendering finished, it Context has pop(), so the need to write variables in the template will be higher Conetxt to read on the outside. If you need to use the Context assigned to the higher, you can use":="assignment, it will be variable write Context.getParent() in For example:

#set (price: = book.price * book.discount)

you can render the template, through Context.getContext(). get ("price"); got the above variables.

Note:

// you can put into the reference set unmodifiable Map, will not affect the operation.
Mapparameters = Collections.unmodifiableMap (parameters);

// Incoming parameters in the rendering process will not always be modified,
// Make sure the rendering process without side effects, as well as multiple rendering idempotent.
template.render (parameters, writer);

// Template #set (price = x) variables are put into the Context of the temporary collection.
Context.getContext(). Put ("price", x);

// First #set temporary collection lookup, then the native incoming parameters, locate and then to search on a Context.
Context.getContext(). Get ("price");

conditional instructions

#if condition

If the conditional expression evaluates to true or a non-empty, then the output contained in the instruction blocks.

Note: For non-Boolean value: non-zero number, non-empty string, non-empty, non-null object, is true.

Format:
#if (expression)

Example:
#if (user.role =="admin")
	...
#end

#else condition otherwise

If the preceding #if condition is not true, then the output #else directive contains blocks.

Note: #else directives can be directly without conditions, to reduce the #if condition combinations.

Format:
#else
#else (expression)

Example:
#if (user.role =="admin")
	...
#else (user.role =="member")
	...
#else
	...
#end

loop instructions

#for loop

resulting collection iteration expression, for each value in the set, repeatedly outputs the block contained in the instruction.

Format:
#for (name: expression)
#for (type name: expression)

Example:
#for (book: books)
	...
	$ {For.index}
	$ {For.size}
	$ {For.first}
	$ {For.last}
#end

type declarations, and can be used as casts, for example:

#for (Book book: booklist)
	$ {Book.title}
#end

If booklist generic lost, the above wording can recover book type.

in the iteration before, you can do the collection operations, such as:

# # Perform nine times
#for (9)

# # Literal sequence set, a digital output 1-9
#for (i: 1 .. 9)

# # Literal discrete set, 10,20,30 three digital outputs
#for (i: [10, 20, 30])

# # Take a non-empty iteration, if books1 is not empty, then iterative books1, otherwise iteration books2
#for (book: books1 | | books2)

# #set summed, then iterative
#for (book: books1 + books2)

# #set sort, then iterative
#for (book: books.sort)

# # Recursive iterations, such as Menu has a getChildren() method returns the child list:
#for (Menu menu: menus.recursive ("getChildren"))

#break cycle interrupts

When the conditional expression is true or non-empty interrupt the current iteration.

Note: #break conditional parameters directly: #break (i ​​== j), need not be written: #if (i == j) #break #end

Format:
#break
#break (expression)

Example:
#for (book: books)
	...
	#break (for.index == 10)
	...
#end

#else loop or

If the previous #for collection is empty, then the output #else directive contains blocks.

Note: #for #else directives can be directly used in combination, can reduce the #if not empty determine the conditions of writing.

Format:
#else
#else (expression)

Example:
#for (book: books)
	...
#else
	...
#end

template directives

#macro template fragment

the instruction block encapsulated into reusable template fragments, which can be passed as a variable, you can repeat the output can be inherited overwritten.

Format:
#macro (name)
#macro (name (name, name))
#macro (name (type name, type name))

Example:
#macro (xxx)
	...
#end

$ {Xxx} to execute the macro variables
$ {Xxx (arg1, arg2)} method to execute the macro

template inheritance macro coverage, see:inheritance example

while the macro definition, you can define the position while the output macro or the macro assigned to the variable, and define parameters for the macro to simplify the writing.

Format:
#macro ($ name)
#macro ($ name (name, name))
#macro ($ name (type name, type name))

#macro (var = name)
#macro (var = name (name, name))
#macro (var = name (type name, type name))

#macro ($ name =>cache)
#macro ($ name (name, name) =>cache)
#macro ($ name (type name, type name) =>cache)

#macro (var = name =>cache)
#macro (var = name (name, name) =>cache)
#macro (var = name (type name, type name) =>cache)

Example:
#macro ($ xxx)
	...
#end

#macro (xxx = xxx)
	...
#end

portfolio syntax equivalence relation:

#macro ($ xxx)
	...
#end

Is equivalent to: (a position in the macro definition output simultaneously)

#macro (xxx)
	...
#end
$ {Xxx}
#macro (aaa = xxx)
	...
#end

Is equivalent to: (performed while the macro definition, and assigns the result to the specified variable)

#macro (xxx)
	...
#end
#set (aaa = xxx)
#macro ($ xxx =>cache)
	...
#end

Is equivalent to: (a position in the macro definition output simultaneously)

#macro (xxx)
	...
#end
$ {Cache (xxx)}
#macro (aaa = xxx =>cache)
	...
#end

Is equivalent to: (performed while the macro definition, and assigns the result to the specified variable)

#macro (xxx)
	...
#end
#set (aaa = cache (xxx))

#break interrupt template

When the conditional expression is true or empty, interrupting the current template or macro execution.

Note: Do not #for Directives #break, indicates that an interrupt template or macro execution.

Format:
#break
#break (expression)

Example:
#break (debug)

comment directive

# # line comment

hidden line comment content, with a newline character, for the annotation process, or shielded instruction content.

Format:
# # Line comment

Example:
# # This is line comment

# ** # block comment

hide content block comment can contain line breaks, for the annotation process, or shielded instruction content.

Format:
# * Block comment * #

Example:
# *
	 This is block comment
* #

escaped directive

# [] # do not parse block

template content is output to output plain text content, block or bulk escape special characters.

Format:
# [No parse block] #

Example:
# [This is no parse block: #if $ {name}] #

\ # \ $ special character escape

instruction is output as special characters, used to output plain text content.

Format:
\ #, \ $, \ \

Example:
\ # Xxx
\ $ {Xxx}
\ \ $ {Xxx}

Expressions

based on Java expressions and extension methods.

supports Java all expressions, the following list only different points in Java:

  • operations are all null values ​​returns null, for example: $ {foo.bar.blabla}, if foo is null, all subsequent operations ultimately is null, and not a null pointer.
  • double equal sign"=="will be parsed equals() methods, rather than than the memory address.
  • single and double quotation marks will produce the string: 'a' or"a" is of type String, if you want to declare literal char, please use backticks: `a` as char type.
  • plus sign"+" digital first, $ {1 +"2"} output 3, instead of 12, string concatenation try to use $ {s1} $ {s2}, rather than $ {s1 + s2}
  • Bean property getter method will resolve to call, $ {user.name} is equivalent to $ {user.getName()}
  • all implement Comparable objects support comparison operators, such as: #if (date1
  • logic and supported by all objects or, respectively, returns null or non-null value, for example: $ {list1 | | list2}, if list1 is not empty then return list1, otherwise return list2.
  • List and Map can be bracketed values, such as: list [0] is equivalent to list.get (0), map ["abc"] is equivalent to map.get ("abc")
  • uppercase 3L will generate java.lang.Long value, lowercase 3l will generate long values.
  • support is operator with instanceof same source C #.

attribute lookup order to $ {obj.foo} as an example: (compile-time decisions, does not affect performance)

  • first checks for any type of imported obj foo() static method
  • then find obj.getFoo() function
  • then find obj.isFoo() function
  • then find obj.foo() function
  • then find obj.foo properties

operator expression

set operator

$ {list [0]} is equivalent to: $ {list.get (0)}

$ {Map.abc} is equivalent to: $ {map.get ("abc")}

$ {Map ["a.b.c"]} is equivalent to: $ {map.get ("a.b.c")}

Sequence generation: an .. 3
For example:
#for (i: 1 .. 10)
$ {I}
#end

List generated: [123,"abc", var]
For example:
#for (color: ["red","yellow","blue"])
$ {Color}
#end

Map generator: ["xxx": 123,"yyy":"abc","zzz": var]
For example: (this Map maintaining declaration order)
#for (entry: ["red":"# FF0000","yellow":"# 00FF00"])
$ {Entry.key} = $ {entry.value}
#end

Collection added: list1 + list2
For example:
#for (item: list1 + list2)
$ {Item}
#end

logical operators

#if (object)
Is equivalent to:
#if (object! = Null)

#if (string)
Is equivalent to:
#if (string! = null && string.length()>0)

#if (list)
Is equivalent to:
#if (list! = Null && list1.size()>0)

#for (item: list1 | | list2)
Is equivalent to:
#for (item: list1! = Null && list1.size()>0? List1: list2)

Date Operator

date1>date2
date1>= date2
date1

function expression

transformation function

obj.to ("com.foo.Bar")
obj.toMap
num.toDate
str.toDate
str.toDate ("yyyy-MM-dd HH: mm: ss")
str.toChar
str.toBoolean
str.toByte
str.toInt
str.toLong
str.toFloat
str.toDouble
str.toClass
str.toLocale

aggregate function

Array and List size method can be used to obtain the same size
array.size
list.size
map.size

list.sort
#for (item: list.sort)
#end

list.toCycle
#set (colors = ["red","blue","green"]. ToCycle)
#for (item: list)
$ {Colors.next}
#end

file functions

inherited template to the current template macro, replace the parent of the same name in the template macro, execute the parent template, the output to the current location.
$ {Extends ("/ layout.httl")}
$ {Extends ("/ layout.httl","UTF-8")}
$ {Extends (".. / Layout.httl")}
$ {Extends (".. / Layout.httl","UTF-8")}

Contains a template, perform the target template, the output to the current location.
$ {Include ("/ template.httl")}
$ {Include ("/ template.httl","UTF-8")}
$ {Include ("/ template.httl", ["arg":"value"])}
$ {Include (".. / Template.httl")}
$ {Include (".. / Template.httl","UTF-8")}

Template contains macros, perform target macro output to the current position.
$ {Include ("/ template.httl #macro")}
$ {Include ("/ template.httl #macro","UTF-8")}
$ {Include ("/ template.httl #macro")}
$ {Include ("/ template.httl #macro", ["arg":"value"])}

Read the contents of the target file, output to the current position.
$ {Read ("/ text.txt")}
$ {Read ("/ text.txt","UTF-8")}

internationalization function

$ {"key". message} or $ {message ("key")}
In localized = true when looking for the following sequence of key configuration files:
basename_zh_CN.properties
basename_zh.properties
basename.properties

$ {Include ("template.httl")}
In localized = true, the order find the following files are present:
template_zh_CN.httl
template_zh.httl
template.httl

httl.properties related configuration:

# international prefix configuration file information, from the Loader looks / WEB-INF/messages_zh_CN.properties
message.basename = / WEB-INF/messages

# Internationalized message formats, support for message and string
# Correspond MessageFormat.format() and String.format()
message.format = message

# Users can save files in UTF-8 international information, without the need ascii2native
message.encoding = UTF-8

# Open international search
localized = true

# Default Regional Information
locale = zh_CN

formatting function

num.format ("# # #, # # 0")
num.format ("# # #, # # 0. # #")
date.format ("yyyy-MM-dd")
date.format ("yyyy-MM-dd HH: mm: ss")

escape function

str.escapeXml
str.unescapeXml
str.escapeUrl
str.unescapeUrl
str.escapeString
str.unescapeString
str.escapeBase64
str.unescapeBase64

JSON function

# the object into a JSON string
obj.encodeJson

# Parse the JSON string into a Map object
str.decodeJson.toMap

# Parse the JSON string into an object
str.decodeJson ("com.foo.Bar"). to ("com.foo.Bar")

default transcoding using the built-in parser JSON string.

To use fastjson

transcoding, configure:

httl.properties:

json.codec = httl.spi.codecs.FastjsonCodec

pom.xml:

fastjson-1.1.25.jar


	com.alibaba
	fastjson
	1.1.25

XML function

# the object into XML string
obj.encodeXml

# Parse the XML string into an object
str.decodeXml.to ("com.foo.Bar")

used by default java.beans.XMLEncoder transcoding.

To use xstream

transcoding, configure:

httl.properties:

xml.codec = httl.spi.codecs.XstreamCodec

pom.xml:

xstream-1.4.3.jar


	com.thoughtworks.xstream
	xstream
	1.4.3

digest function

# generate MD5 code
str.md5

# Generate SHA code
str.sha

# Generate a summary of the specified type code
str.digest ("MD5")
str.digest ("SHA")

naming conversion function

# Convert underscores to separate naming
str.toUnderlineName

# Turn into a hump-separated name (first letter lowercase)
str.toCamelName

# To uppercase separated naming (first letter capitalized)
str.toCapitalName

system function

# current time
$ {Now()}

# Random number
$ {Random()}

# Unique code
uuid()

Velocity comparison

If you used a Velocity template, you can view the following comparison, a better understanding of:

syntax contrast

  1. HTTL command variable without $ symbol, which only supports #if (x == y), does not support the #if ($ x == $ y), because the command string is not quoted variables, and conventional language syntax, like add $ bit rubbish, but also easy to forget to write.

  2. HTTL placeholder necessary to increase the brackets, only support $ {aaa}, does not support the $ aaa, because $ is legal in JavaScript variable name symbols, and $ {} is not to reduce the confusion, but also to prevent more human development, it was to increase the brackets, some without, simply did not have a choice, are added, consistent.

  3. HTTL placeholder when the variable is null output blank string, unlike Velocity command is output as the original, ie $ {aaa}, is equivalent to the Velocity $ {aaa}, so as not to forget to write Developers exclamation, expression leak source, for as output, use the escape \ $ {aaa}, In HTTL in, $ {aaa} represents not content filtering for output as HTML fragments.

  4. HTTL support all local variables used for expression evaluation, that is, you do not like the Velocity as the first #set ($ j = $ i + 1) to a temporary variable, and then output the temporary variable $ {j}, HTTL can be directly output $ {i + 1}, other commands, too, such as: #if (i + 1 == n).

  5. HTTL method using extended Class native ways, such as: $ {"a". toChar}, rather than the Velocity Tool utility methods like: $ (StringTool.toChar ("a")), such call method is more intuitive, more in line with the code writing habits.

Directive contrast

Velocity HTTL similarities function change
$ {xxx.yyy}
$ xxx.yyy
$ {xxx.yyy} same output placeholder HTTL braces required
$! {xxx.yyy}
$! xxx.yyy
$! {xxx.yyy} different null value does not show source VM null value does not show source
HTTL to not filter output
# # ...
# * ... * #
# # ...
# * ... * #
same comment block is not displayed
# [[...]] # # [...] # similar not parse text block HTTL little pair of brackets
\ # \ $ \ \ \ # \ $ \ \ same special characters escaped
#set ($ xxx = $ yyy) #set (xxx = yyy)
#set (Type xxx = yyy)
#set (Type xxx)
same assign variables HTTL available with type declarations
#if ($ xxx == $ yyy) #if (xxx == yyy) same conditional
#elseif ($ xxx == $ yyy) #else (xxx == yyy) similar or conditional HTTL multiplexing #else directive
#else #else same otherwise determine
#end #end
#endif
#end (if)
same end instruction HTTL available with matching command names
#foreach ($ item in $ list) #for (item: list)
#for (Type item: list)
similar List cycle HTTL to Java format
#break #break
#break (xxx == yyy)
same interrupt cycle HTTL directly with conditions
# stop #break
#break (xxx == yyy)
similar stop template parsing HTTL multiplexing #break directive
#macro ($ xxx) #macro (xxx) different reusable template fragments macro VM as the macro instruction execution
HTTL performed as a function
# define ($ xxx) #macro (xxx = xxxmacro) similar catch block output to a variable HTTL multiplexing #macro directive
# include ("xxx.txt") $ {read ("xxx.txt")} similar read text file content HTTL to function extensions
# parse ("xxx.vm") $ {include ("xxx.httl")} similar contains another template output HTTL to function extensions
# evaluate ("$ {1 + 2}") $ {render ("$ {1 + 2}")} similar template evaluation HTTL to function extensions