Velocity is a Java-based template engine (TEMPLATE ENGINE). It allows anyone to simply use the template language (Template language) to reference objects defined by Java code.
When Velocity is applied to web development, interface designers can develop a Web site that follows the MVC architecture with Java program developers. That is to say, page designers can only pay attention to the display of the page, but by Java program developers pay attention to business Logic coding. Velocity separated Java code from the web page, which provides a convenient for long-term maintenance of the Web site, and also provides an optional solution for our JSP and PHP.
Velocity's ability to develop this area, for example, it can generate SQL and PostScript, XML from template (Template), which can also be used as a stand-alone tool to generate source code and report, or as other system integrated components use. Velocity can also provide template services for Turbine Web Development Architecture. Velocity Turbine provides a template service to allow a web application to develop in a real MVC model.
What can Velocity do for us?
The Mud Store EXAMPLE
Suppose you are a page designer specializing in the online store of MUD, let us call it "Online MUD Store." Your business is very prosperous, our customers have undergone various types and quantities of MUD orders. They are all logged into your website after entering the username and password, and then allow them to view orders and purchase more MUD. Now, a very popular MUD is being discounted. In addition, some customer regular purchase is also a discount but not very popular Bright Red Mud, because there are not many people purchased, it is placed on the edge of the page. All users are tracked and stored in the database, so a certain day has a problem. Why don't you use Velocity to make users better browse the goods they are interested in?
Velocity makes it easy to customize the WEB page. As a designer of a web site, you want each user to have its own page when you log in.
You will meet some software engineers in some companies, you find that each of them agrees that customers should have personalized information. That let us send the software engineer to the side, look at what you should do.
You may be nested in the page as the following VTL declaration:
Hello $ Customer.Name!
#foreach ($ MUD IN $ NUDSONSPECIAL)
#if ($ Customer.Haspurchased ($ MUD))
$ FLOGGER.GETPROMO ($ MUD) td> TR>
#end
#end
TABLE>
Velocity Template Language (VTL): An Introduction
VTL means that the simplest, easiest and most complete merge page dynamic content is provided.
VTL uses References to nested dynamic content in Web Site, and a variable is a type of Reference. Variables are certain types of refreence, which can point to definitions in the Java code, or values from VTL Statement defined within the current page. Below is an example of a VTL Statement, which can be nested into the HTML code:
#set ($ a = "velocity")
Like all VTL Statement, this Statement starts with # characters and contains a Directive: SET. When an online user requests your page, Velocity Templating Engine will query the entire page to find all # characters, then make sure which is VTL Statement, which does not require VTL to make anything. # When you follow a Directive: Set, this set directive uses an expression (enclosed using parentheses) - a equation assigns a value to the variable. The variable is listed on the left, and its value is listed on the right, and finally they use = number segmentation.
In the above example, the variable is $ A, and its value is Velocity. The same start with other References, while the value is always closed by double quotes. Only String in Velocity can be assigned to the variable.
Remember the following rules:
Use the REFERENCES that is starting with the character to get what is obtained; Directives starting with # characters is used to make something.
Hello Velocity World!
Once a variable is assigned a value, then you can reference it anywhere in the HTML file. In the following example, a value is assigned to the $ foo variable and will be referenced thereafter.
#set ($ foo = "velocity")
Hello $ foo world!
body>
html>
The result of the above is to print "Hello Velocity World!" On the page.
In order to make STATEMENT containing VTL Directives more readable, we encourage you to start each VTL Statement in the new row, although you don't have to do this. SET DIRECTIVE will be described in detail later.
Comment
Untrue annotation:
## this is a single line commernd.
Multi-line comments:
# *
Thus Begins a Multi-Line Comment. Online Visitors Wo't
See this text Because The Velocity Templating Engine Will
Ignore IT.
* #
Document format:
# **
This is a vtl comment block and
May Be buy to store such information
as the document author and versioning
Information:
@Version 5
@Author
* #
References
There are three types of REFERENCES: Variables, Properties, and Methods, in VTL. As a page designer using VTL, you and your engineers must reach a consensus on the name of References so that you can use them in your Template.
Everything coming to and from a reason is processed as a String object. If there is an object $ foo is an Integer object, then Velocity will call its toString () method to transform this object to the String type.
variable
The format requires Java.
Attributes
example:
$ Customer.Address
$ purchase.total
$ Customer.Address has two meanings. It can be represented: Find the value of the HashTable Object Customer in address as the keyword; or the getaddress () method that calls the Customer object. When your page is requested, Velocity will determine the above two ways, and then return the appropriate value. method
One method is to be defined in a piece of code in Java, and it has the ability to complete some useful work, such as whether an execution calculation and judgment conditions are set, satisfied. The method is a References consisting of $ start and following the VTL identifier, typically also includes a VTL method. E.g:
The first two examples $ Customer.Getdress () and $ purchase.gettotal () look tall that the properties above $ Customer.Address and $ Purchase.Total. If you think there is some kind of contact between them, then you are correct.
The VTL attribute can be an abbreviation for the VTL method. $ Customer.Address property and use the $ Customer.GetadDress () method have the same effect. If possible, it is reasonable to use properties. The difference between the properties and methods is that you can give a method to specify a list of parameters.
Formal Reference tag
Reference exactly the format:
$ {mudslinger} variable
$ {Customer.Address} attribute
$ {purchase.gettotal ()} method
It is not a common format, but sometimes it is suitable for the format. For example: You want to organize a string through a variable $ Vice.
Jack is a $ ViceManiac.
Original variable is $ VICE now becomes $ ViceManiac, so Veloctiy doesn't know what you want. Therefore, it should be used in format writing.
Jack is a $ {vice }maniac
Now Velocity knows that the variable is $ VICE instead of $ ViceManiac.
Quiet Reference Notation
E.g:
When the FORM of the page is initially loaded, the variable $ Email has no value, then you must want it to display a Blank Text to replace the field such as "$ Email". Then use the Quiet Reference Notation to be appropriate.
The initial value of such a text box will not be email but a null value.
The official and quiet format of Reference Notation can also be used together, like this:
Getting Literal
Velocity uses special characters $ and # to help it work, so if you want to use these special characters in Template, you should be careful. This section will discuss $ characters.
Currency character
With a currency identifier such as $ 2.5 in VTL, VTL does not miss it to be a Reference because the Reference in VTL always begins with a uppercase or lowercase.
Escaping Valid VTL Reference
Use "/" as an escape in VTL.
For example: #set ($ email = "foo")
$ EMAIL
/ $ EMAIL
/ / $ email
/// $ email
Will Render as:
foo
$ EMAIL
/ foo
/ / $ email
If the email variable is not defined
$ EMAIL
/ $ EMAIL
/ / $ email
/// $ email
Will be Render:
$ EMAIL
/ $ EMAIL
/ / $ email
/// $ email
Note: The variables that have not been defined in VTL will be considered a string, so the following examples:
#set ($ foo = "gibbous")
$ moon = $ foo
The output result is:
$ moon = gibbous
Case Substitution
Now you have been familiar with Reference, you can use them efficiently to your template. Velocity takes advantage of many Java specifications to facilitate the use of designers. E.g:
$ foo
$ foo.getbar ()
## Is The Same AS
$ foo.bar
$ Data.Getuser ("Jon")
## Is The Same AS
$ Data.user ("Jon")
$ DATA.GETREQUEST (). getServerName ()
# is the same as
$ data.Request.servername
## Is The Same AS
$ {data.request.servername}
However, pay attention to the example variable of the object in the VTL. For example: $ foo.name will be interpreted as a GetName () method of the Foo object, not the Name instance variable of the Foo object.
Directives
Reference allows designers to use dynamic content, while Directive allows you to apply Java code to control your display logic, which reaches the display effect you expect.
#set
#set Directive is used to set the value of a Reference. E.g:
#set ($ primate = "monkey")
#set ($ Customer.Behavior = $ primate)
The (LHS) on the left side must be a variable or attribute Reference. The right side (RHS) can be one of the following types:
l Variables Reference
l string literal
l attribute Reference
l method Reference
l Number Literal
l arraylist
Here is an example of applying various types of RHS:
#set ($ value = $ foo 1) #set ($ value = $ bar -1)
#set ($ VALUE = $ foo * $ bar)
#set ($ VALUE = $ FOO / $ BAR)
If your RHS is a NULL, VTL's processing will be special: it will point to a already existing Reference, which may be comparable to beginners. E.g:
#set ($ Resut = $ query.criteria ("name")))
The Result of The First Query IS $ Result
#set ($ Resut = $ query.criteria ("address"))
The Result of The Second Query IS $ Result
If $ query.criteria ("name") returns a "Bill", and $ query.criteria ("address") returns NULL, the result is as follows:
The Result of the First Query Is Bill
The Result of the First Query Is Bill of THE FIRST Query
Take a look at the example below:
#set ($ criteria = ["name", "address"])
#foreach ($ criterion in $ criteria)
#set ($ Result = $ query.criteria ($ criterion))
#if ($ Result)
Query Was Successful
#end
#end
In the example above, the program will not be intelligent to determine whether the query is successful according to the value of $. After $ Result (Added to The Context), it cannot be set back to NULL (Removed from the context). The results of printing will show that the results of the query are successful, but there is a query that has failed.
In order to solve the above problems, we can use pre-defined ways:
#set ($ criteria = ["name", "address"])
#foreach ($ criterion in $ criteria)
#set ($ result = false)
#set ($ Result = $ query.criteria ($ criterion))
#if ($ Result)
Query Was Successful
#end
#end
String Literals
When you use #set Directive, String Litral is enclosed in a pair of double quotes.
However, when String Literal is encapsulated in single quotes, it will not be parsed:
#set ($ foo = "bar")
$ foo
#set ($ blang = '$ foo')
result:
Bar
$ foo
The above features can change whether the above features are valid by modifying the value of the stringliterals.interpolate = false of the Velocity.Properties file.
Conditional statements
IF / Elseif / Else When a web page is generated, use Velocity #if Directr, if the condition is established, you can embed text on the page. E.g:
#if ($ foo)
velocity! strong>
#end
The conditional statement in the above example will be established under the following conditions:
l $ foo is a Boolean type variable, and its value is True
L $ foo variable value is not NULL
Here you need to pay attention to a little: Velocity Context can only contain objects, so when we say "boolean" actually represents a Boolean object. Even if a method returns a boolean value, Velocity will use the internal provincial mechanism to convert it to a Boolean.
If the condition is established, the content between #IF and #end will be displayed.
#ELSEIF and #ELSE elements can be used with #if. E.g:
#if ($ FOO <10)
go north strong>
#ELSEIF ($ foo == 10)
Go East strong>
#ELSEIF ($ foo == 6)
Go South strong>
#ELSE
Go West strong>
#end
Note that the number of Velocity here is compared to Integer - Other types of objects will make the conditions false, but different from Java uses "==" to compare two values, and Velocity requires the same value on both sides. .
Relationship, logical operator
Use an equal signage in Velocity to determine the relationship between the two variables. E.g:
#set ($ foo = "deoxyribonucleic acid")
#set ($ bar = "ribonucleic acid")
#if ($ foo == $ foo)
In this case it's clear the aren't equivalent.so ...
#ELSE
They area not equivalent and this will be the output.
#end
Velocity has an AND, OR and NOT logic operators. Here are some examples:
## logical and
#if ($ FOO && $ BAR)
this and that strong>
#end
## logical or
#if ($ foo || $ bar)
this or what strong>
#end
## logical not
#if (! $ foo)
not that strong>
#end
cycle
Foreach cycle
example:
#foreach ($ Product In $ AllProducts)
$ product li>
#end
ul>
One value in each loop $ AllProducts will assign a $ produter variable.
$ allProducts can be a vector, havehtable or array. The value assigned to the $ produter is a Java object and can be referenced by variables. For example: If $ product is a Java's Product class, and the name of this product can be obtained by calling his getName () method. Now we assume that $ allproducts is a HashTable, if you want to get it, Key should be like this:
Velocity also provides a method of getting a number of cycles so that you can do this like this:
#foreach ($ Customer IN $ Customerlist)
$ VelocityCount TD>
$ Customer.Name TD> TR>
#end
TABLE>
The name of the $ velocityCount variable is a Velocity default name, you can also change it by modifying the velocity.properties file. By default, the count starts from "1", but you can set it from "1" or from "0" at Velocity.properties. Below is the configuration in the file:
# Default name of loop counter
# Variable Reference
Directive.Foreach.counter.name = velocitycount
# Default Starting Value of The Loop
# counter Variable Reference
Directive.Foreach.counter.initial.Value = 1
Include
#include script element allows template designers to introduce local files. The content that is introduced into the file will not be rented by the template engine. For security reasons, the introduced local file can only be in the template_root directory.
#included ("one.txt")
If you need to introduce multiple files, you can separate it by comma:
#include ("One.gif", "Two.txt", "Three.htm")
In parentheses can be a file name, but more time is used:
#inclue ("Greetings.txt", $ SeasonalStock)
Parse
#Parse Script Element allows template designers a local file containing VTL. Velocity will resolve the VTL and the Render template.
#parse ("me.vm")
Just like # include, # parse accepts a variable instead of a template. Any template pointed to by #PARS must be included in the template_root directory. Different from #include, # Parse can only specify a single object.
You can control the number of Template's maximum #PARSE-default value by modifying the value of the velocity.properties file PARSE_DIRECIVE.MAXDEPTH - the default value is 10. #parse is a recursive call, for example, if Dofoo.VM contains down:
Count down.
#set ($ count = 8)
#PARSE ("Parsefoo.VM")
All Done with Dofoo.vm! So in the Parsefoo.vm template, you can contain the following VTL:
$ count
#set ($ count = $ count - 1)
#if ($ count> 0)
#PARSE ("Parsefoo.VM")
#ELSE
All done with parsefoo.vm!
#end
The display result is:
Count down.
8
Seduce
6
5
4
3
2
1
0
All done with parsefoo.vm!
All done with dofoo.vm!
STOP
#stop Script Element allows template designers to stop performing template engines and returns. It is very helpful to apply it to Debug.
#stop
Velocimaos
#macro Script Element allows template designers to define a reusable VTL Template. E.g:
#macro (d)
TD> TR>
#end
In the above example, VelociMacro is defined as d, then you can call it in any VTL Directive:
#d ()
When your template is called, Velocity will replace () with
td> tr> ().
Each VelocimaCro can have any number of parameters - or even 0 parameters, although the number of parameters can be set at will, but the correct parameters must be specified when calling this VelociMacro. Below is a VelociMacro with two parameters, one parameter is the other parameter of Color is Array:
After the above call will produce the following display results:
Superior td> tr>
Michigan TD> TR>
Huron TD> TR>
Erie TD> TR>
Ontario TD> TR>
TABLE>
Velocimaos can implement line-in-line definitions in the Velocity template, which means that other Velocity templates in the same web site cannot get the definition of VelocimaS. Define a VelociMacro that can be shared by all templates. It is obviously a lot of benefits: it reduces the number of repetitions defined in a large heap template, saving working hours, reducing the chances of error, ensuring single modification. The #tableROWS ($ Color $ LIST) VelociMacro defined above is defined in a VelocimaS template library (defined in velocity.properties), so this MacRo can be called in any specification template. It can be applied multiple times and can be applied to different purposes. For example, the following calls:
#set ($ parts = ["Volva", "Stipe", "Annulus", "Gills", "Pileus"])
#set ($ Cellbgcol = "# cc00ff")
#TABLEROWS ($ Cellbgcol $ Parts)
TABLE>
The above VTL will produce the following output:
Volva TD TR>
stipe td TR>
Annulus TD TR>
Gills TD TR>
Pileus TD TR>
TABLE>
Velocimracro Arguments
Velocimacro can use any of the following elements as a parameter:
l Reference: Any Reference with $
L String Litral:
l Number Literal:
l IntegerRange: [1 ... .3] or [$ foo ... $ bar]
l Object arrays: ["a", "b", "c"]
l Boolean: True, False
When passing a Reference as a parameter to VelociMacro, Note that Reference is transmitted as a parameter. This means that the value of the parameters will be generated when executed within each Velocimacro. This feature allows you to pass a method call as a parameter to VelociMacro, and each VelociMacro is executed by this method call to generate different values. E.g:
#macro (Callme $ a)
$ a $ a $ a
#end
#callme ($ foo.bar ())
The result of the execution is: the bar () method of the Reference $ FOO is executed three times.
If you don't need this characteristic, you can pass the following methods:
#set ($ myval = $ foo.bar ())
#callme ($ myVAL)
Velocimracro Properties
A few rows in the velocity.properties file can make VelocimaS achieve more flexible. Note that more content can see developer guide.
VelociMacro.Libraary in a Velocity.properties file: a list of comma-separated template libraries. By default, Velocity looks for a single library: VM_GLOBAL_LIBRARY.VM. You can specify your template library by configuring this property. VelociMacro.Permissions.Allow.inline attribute in the Velocity.properties file: There are two optional value true or false, which can determine if VelociMacros can be defined within Regular Template. The default is TURE - allowing designers to define VelocimaS in their own templates.
Velocity.properties file
Velocimracro.Permissions.Allow.inline.Replace.global property There are two optional values true and false, which allows the user to determine if the VelociMacro definition of Inline can replace the global VelocRo definition (such as the file specified in the VelocimaCro.library property) Defined VelociMacro). By default, this value is false. This prevents the local VelociMacro definition override global definition.
Velocity.properties file
Velocimracro.Permissions.Allow.inline.local.scale properties are also true and false two optional values, the default is false. Its role is to determine if the VelociMacros defined by your inline is only visible in the defined template. In other words, if this property is set to True, a Inline defined VelocimaS can only be used within the Template defined. You can use this setting to implement a wonderful VM knock: a Template CAN define a private implement of the second vm this will be called by the first VM When invoked by That Template. All Templates Are UnAffected.
VelociMacro.Context.localscro.Context.localscope attribute in the velocity.properties file has two optional values of true and false, the default value of false. When set to TRUE, any modification of CONTET () in VelociMacro is considered to be a local setting for this VelocimaCro without permanent impact.
The VelociMacro.Library.AutoreLoad property in the velocity.properties file controls the automatic load of the VelocimaCro library. The default is False. When set to TURE, the call to a VelociMacro will automatically check if the original library changes, and if the change will reload it. This property allows you to reach the reloaded effect without restarting the servlet container, just like you use the Regular template. The premise of this attribute is that the Resource Loader cache is OFF state (file.Resource.Loader.cache = false). Note that this property is actually for development instead of product.
Velocimracro Trivia
Velocimacro must be defined before they are used. That is, your #macro () statement should appear before using VelocimaS.
It is important to note that if you try to #parse () a template containing #macro (). Because #parse () occurs during the runtime, but the parser determines whether the element of the VM element is a VM element in Parsetiem, such #parse () - ING a set of VM declarations will not work according to the expected look. In order to get the expected result, you only need to use VelociMacro.Library to make Velocity load your VMS at startup. Escaping VTL Directives
VTL Directives Can Be Escaped with "/", in use, use the VTL's Reference uses the format of escape characters.
## #include ("a.txt") Renders as (Notes)
#include ("a.txt")
## / # DE ("a.txt") Renders as / # include ("a.txt")
/ # include ("a.txt")
## // # include ("a.txt") Renders as /
/ / # include ("a.txt")
Be careful when using VTL Directives that contains multiple Script elements in a Directive (such as within an IF-Else-End Statement). Below is a typical application of VTL's if-statement:
#if ($ JAZZ)
Vyacheslav Ganelin
#end
If $ jazz is TURE, the output will be:
Vyacheslav Ganelin
If $ JAZZ is False, there will be no output. Use escapes will change the output. Consider the following situation:
/ # ix ($ JAZZ)
Vyacheslav Ganelin
/ # end
Now no matter $ jazz is true or false, the output results are:
#if ($ JAZZ)
Vyacheslav Ganelin
#end
In fact, since you use the escape, $ JAZZ is not parsed to the Boolean value. Using escape before escape, for example:
/ / # ix ($ jazz)
Vyacheslav Ganelin
// # end
The result of the above program is:
/ Vyacheslav Ganelin
/
But if $ jazz is false, it will not be output. (The book says there will be no output, but I think there should be "/" characters to be output.)
VTL: Formatting Issues
Although VTL usually starts a new line in this user manual, as shown below:
Send me #set ($ foo = ["$ 10 and", "a cake"]) # foreach ($ a in $ foo) $ A #END PLEASE.
The above code can be rewritten as:
Send Me
#set ($ foo = ["$ 10 and", "a cake"])
#foreach ($ a in $ foo)
$ a
#end
please.
or
Send Me
#set ($ foo = ["$ 10 and", "a cake"])
#Foreach ($ a in $ foo) $ a # end please.
These two output structures will be the same.
Other features and miscellaneous
Math can use Velocity built-in arithmetic functions in the template, such as plus, minus, multiplication, division
#set ($ foo = $ bar 3)
#set ($ foo = $ bar - 4)
#set ($ foo = $ bar * 6)
#set ($ foo = $ bar / 2)
An Integer type result will be returned when the division is performed. And the remainder you can use to get:
#set ($ foo = $ bar% 5)
When using mathematical calculation formulas in Velocity, an integer like -N, -2, -1, 0, 1, 2, and n can not be used without other types of data. When a non-integer object is used, it will be logged and will use NULL as the output result.
Range Operator
Range Operator can be used in combination with #set and #foreach statement. It is useful for processing a integer array, and the Range Operator has the following configuration:
[n..m]
M and N must be intellectual, and whether the M is greater than n. example:
First EXAMPLE:
#foreach ($ foo in [1..5])
$ foo
#end
SECOND EXAMPLE:
#foreach ($ BAR IN [2 ..- 2])
$ bar
#end
Third Example:
#set ($ arr = [0..1])
#foreach ($ I IN $ ARR)
$ I
#end
Fourth EXAMPLE:
[1..3]
The output result of the above four examples is:
First EXAMPLE:
1 2 3 4 5
SECOND EXAMPLE:
2 1 0 -1 -2
Third Example:
0 1
Fourth EXAMPLE:
[1..3]
Note: Range Operator is only valid in #set and #fore.
Advanced Issue: escaping and!
When a Reference is "!", The Reference will handle in a special manner when there is an escape in it. Note that this approach is different from the standard escape method. The control is as follows:
#set ($ foo = "bar")
Special form standard format
Before render before render render before render
$ /! foo $! foo / $ foo / $ foo
$ /! {foo} $! {foo} / $! foo / $! foo
$ / /! foo $ /! foo / $! {foo} / $! {foo}
$ / //! foo $ //! foo // $! {foo} / bar
VelocimaCro miscellaneous
CAN I User A DIRECTIVE OR ANOTHER VM AS AN ARGUMENT TO A VM?
For example: #Center (#bold ("Hello")))
No. A Directive parameter uses another Directive if it is not legal.
But it is still something you can do. The simplest way is to use double quotes:
#set ($ stuff = "#bold ('Hello')")
#center ($ stuff)
The above format can also be abbreviated as a line:
#Center ("#bold ('Hello'))
Note that the parameters in the example below are inside the Velocimracro instead of calling. Example: #macro (Inner $ FOO)
Inner: $ foo
#end
#macro (Outer $ foo)
#set ($ bar = "outerlala")
Outer: $ foo
#end
#set ($ bar = 'caltimela')
#outer ("#inner ($ bar)")
The output is:
Outer: Inner: Outerlala
Remember the characteristics of Veloctiy: The passage of the parameters is BY Name. E.g:
#macro (Foo $ Color)
Hi TD> TR>
There td> tr>
#end
#foo ($ bar.rowcolor ())
The above code will cause the rowcolor () method twice, not once. In order to avoid this phenomenon, we can perform it in the following manner:
#set ($ color = $ bar.rowcolor ())
#foo ($ color)
Can Iregister Velocimacros Via #PARSE ()?
Currently, VelocimaS must be defined before the template call is called. This means that your #macro () statement should appear before using Velocimaos.
If you try #parse () a template containing #macro () Directive, this is to keep in mind. Because #parse () occurs during the runtime, but the parser determines whether the element of the VM element is a VM element in Parsetiem, such #parse () - ING a set of VM declarations will not work according to the expected look. In order to get the expected result, you only need to use VelociMacro.Library to make Velocity load your VMS at startup.
What is velocromracro autoreloading?
Velocimracro.library.AutoreLoad is a property specifically for development rather than product. The default value of this property is False.
String concatenation
The problem of developers is what question is how do I make characters stitching? It is done using the " " number in Java.
In vtl wants to achieve the same feature, you only need to put it together to put it together. E.g:
#set ($ size = "big")
#set ($ Name = "BEN")
The Clock is $ SIZE $ Name.
The output will be: The clock is bigben .. More interesting is:
#set ($ size = "big")
#set ($ Name = "BEN")
#set ($ CLOKC = $ SIZE $ NAME ")
The clock is $ clock.
The same result is also obtained. The last example, when you want to mix the fixed field to your Reference, you need to use the standard format: