Share freemarker again

Source: Internet
Author: User
Tags define local xslt java anonymous class

There are many OECP communitiesFreemarkerIt seems that there is noFreemarkerThis is a detailed article. Therefore, LOLA will upload an introduction for you today.Freemarker.
FreemarkerIt is a powerful template engine. Compared with velocity, it has powerful process calling, recursion, and closure callback functions.FreemarkerIt can accomplish almost all the functions we want. In my opinion,FreemarkerFully capable of being used as an auxiliary code generation tool for MDA (model-driven architecture.
Freemarker's first eye-catching is its powerful process calling and recursive processing capabilities. Second, the xml-style syntax structure has obvious boundaries, unlike velocity, which requires spaces between paragraphs.
Before using the maxcompute service, you must set the runtime environment.FreemarkerWe need to download the relevant program:
Freemaker: http://freemarker.sourceforge.net/
Fmpp: http://fmpp.sourceforge.net/
Fmpp isFreemarkerWith it, we can implement more functions. In the following example, fmpp is required.
Here we will first raise the question. You can see the following xml file, althoughFreemarkerThe ability is not only to process xml files, but to use xml as an example is more intuitive:
<? Xml version = '000000' encoding = "gb2312"?>
<Types xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns = "urn: DruleForm-Lite.xsd">
<Type name = "Type1">
<Labels>
<Label lang = "zh-CN" value = "warranty"/>
</Labels>
<Field name = "Field11" type = "Float" lbound = "1" ubound = "1">
<Labels>
<Label lang = "zh-CN" value = "warranty ID"/>
</Labels>
</Field>
<Field name = "Field12" type = "String" lbound = "1" ubound = "*"/>
<Field name = "Field13" type = "Integer" lbound = "1" ubound = "*"/>
<Field name = "Field14" type = "Type2" lbound = "1" ubound = "*">
<Type name = "Type2">
<Field name = "Field21" type = "String" lbound = "1" ubound = "*"/>
<Field name = "Field22" type = "Integer" lbound = "1" ubound = "*"/>
</Type>
</Field>
<Field name = "Field15" type = "InsuranceProduct" lbound = "1" ubound = "*"/>
<Type>
<Type name = "Type3">
<Field name = "Field31" type = "Type1" lbound = "1" ubound = "*"/>
</Type>
</Types>
[Code 1]
Our task is to convert this file into the corresponding C # code. Let's take a look at the code of the conversion template:
1 <# ftl ns_prefixes = {"ns": "urn: DruleForm-Lite.xsd"}>
2 <# -- Define xml namespace for use in the following code. Note that the ftl command must use a separate line. -->
3 <@ pp. setOutputEncoding encoding = "gb2312"/> <# -- use the function provided by fmpp to set the output encoding -->
4
5 <# recurse doc> <# -- root entry. xml in part 1 of code is stored in the variable doc. Fill in the doc variable by fmpp according to the configuration in config. fmpp -->
6
7 <# macro "ns: types"> <# -- entry to xslt style matching processing -->
8 <# recurse> <# -- directly match in the types node -->
9 </# macro>
10
11 <# macro "ns: type"> <# -- match type nodes -->
12 class $ {. node. @ name} <# -- where. node is a reserved word, indicating the current node, and the referenced @ name Is An xslt style -->
13 {
14 <# recurse> <# -- continue matching -->
15}
16 </# macro>
17
18 <# macro "ns: field">
19 public $ {. node. @ type }$ {. node. @ name };
20 </# macro>
21
22 <# macro @ element> <# -- process all nodes with no matching definitions here -->
23 </# macro>
 
[Code 2]
 
The configuration file is set as follows:
 
SourceRoot: src
OutputRoot: out
LogFile: log. fmpp
Modes :[
Copy (common/*** // **/*. *, resource /*.*)
Execute (*. ftl)
Ignore (templates/*. *,. project, **/*. xml, xml/** // *. *, *. js)
]
RemoveExtensions: ftl
SourceEncoding: gb2312
Data :{
Doc: xml (freemaker. xml)
}
[Code 3]
Then run the command in dos mode:
E: \ work \ blogs \ freemaker> f: \ download \ freemaker \ fmpp \ bin \ fmpp
The final output result is as follows:
Class Type1 {
Public Float Field11;
Public String Field12;
Public Integer Field13;
Public Type2 Field14;
Public Float Field15;
}
 
Class Type3 {
Public Type1 Field31;
}
[Code 4]
Let's explain it first.FreemarkerThe basic syntax,
<#> Store allFreemarkerAnd all other content is output as is.
 
<@/> Is a function call.
 
In the content of the two delimiters, the first symbol represents the command or function name, followed by the parameter.FreemakerThe following controls are provided:
 
1: Condition judgment
 
<# If condition>
 
<# Else if condition>
 
<# Else>
 
</# If>
2: traverse the members of the hash table or collectionfreemarker called sequence)
 
<# List hash_or_seq as var>
 
</# List>
 
3: Macro, No Response Parameter
 
<# Macro name param1 param2>
<# Nested param>
</# Macro>
 
4: function, with return parameters
 
<# Function name param1 param2>
<# Return val>
</# Function>
 
5. Convert var using a function,FreemarkerIt is called build-ins. The actual internal implementation is similar to member_function (var ,...)
 
Var? Member_function ()
 
6: Take the sub-string, similar to substring (stringA, M, N)
 
StringA [M .. N]
 
7. Define a hash table directly
 
{Key: value, key2: value2}
 
8: Define a sequence directly
 
[Item0, item1, item2]
 
9: access the elements corresponding to the key in the hash table
 
Hash0 [key0]
 
10: access sequence specifies the underlying element
 
Seq0 [5]
 
11: Call function function1
 
<@ Function1 param0 param1/>
12: Call macros and process macro nesting
 
<@ Macro0 param0 param1; nest_param0 nest_param1>
Nest_body
</@ Macro>
13. Define variables and initialize them.
 
<# Assign var = value>
14. Define local variables in macro or function and initialize them.
 
<# Local var = value>
15. Define and initialize global variables
 
<# Global var = value>
16: Output and replace with the expression value
 
$ {Var}
17: Call macro to match the xmlnode itself and its subnodes
 
<# Visit xmlnode>
18: Call macro to match the sub-node of xmlnode
 
<# Recurse xmlnode>
 
After carefully comparing the xml file, do you find anything missing? By the way, if a Type2 definition is missing, we need to modify the ns: type in Code 2 to match the 11th rows:
 
<# Macro "ns: field">
Public $ {. node. @ type }$ {. node. @ name };
<# Recurse> <# -- deep processing of subnodes -->
</# Macro>
[Code 5]
 
The content in the result output file is changed to the following:
 
Class Type1 {
Public Float Field11;
Public String Field12;
Public Integer Field13;
Public Type2 Field14;
Class Type2 {
Public String Field21;
Public Integer Field22;
}
Public Float Field15;
}
 
Class Type3 {
Public Type1 Field31;
}
[Code 6]
 
If you are interested in putting Type2 at the same level as Type1 and Type3, we will continue to modify the code. Modify <# recurse doc> line 5th of Code 2 to the following:
 
<# Assign inner_types = pp. newWritableHash ()> <# -- call the fmpp function to generate a writable hash -->
<# Recurse doc> <# -- root entry. xml in code 1 is stored in the variable doc. The filling of the doc variable is performed by fmpp according to the configuration in config. fmpp. -->
<# If inner_types? Size gt 0> <# -- if the storage type exists -->
<# List inner_types? Values as node> <# -- traverse the value of the Hasse table -->
<# Visit node> <# -- activate the corresponding macro processing, similar to apply-template of xslt. Change visit TO recurse to see different results -->
</# List>
</# If>
[Code 7]
 
Modify macro ns: field row 18th as follows:
 
<# Macro "ns: field">
Public $ {. node. @ type }$ {. node. @ name };
<# If. node ["ns: type"]? Has_content> <# -- if the current node has a type node -->
<# Local t =. node ["ns: type"]>
<@ Pp. set hash = inner_types key = "$ {t. @ name} "value = t/> <# -- add content to the Hasse table. The key is the name attribute of the nested type, and the value is the node of this type. -->
</# If>
</# Macro>
[Code 8]
 
The output file obtained after running is similar to the following:
 
Class Type1 {
Public Float Field11;
Public String Field12;
Public Integer Field13;
Public Type2 Field14;
Public Float Field15;
}
 
Class Type3 {
Public Type1 Field31;
}
 
Class Type2 {
Public String Field21;
Public Integer Field22;
}
[Code 9]
 
Let's take a look at the effects of our changes? Remember to do another two things:
1. Modify the first line to <# ftl ns_prefixes = {"D": "urn: DruleForm-Lite.xsd"}>, and then set all <# macro "ns: type "> modified to <# macro type>, and all. node ["ns: type"]. node. type to see if it can run? Is it easy and convenient? Remember, the D in the first line indicates the meaning of default namespace.
2. Insert <# compress> In the second row and add </# compress> in the last row. Run the following command to check whether the results are different?
For exampleFreemarkerI have some feelings. to correct themFreemarkerThis is a misunderstanding of an xml processing tool. Let's start a simple experiment. What we need to do this time is a normal programming question. We need to develop a program with a length of less than 100 of the length of the Fibonacci series. The procedure is as follows:
Iterations:
<# List 1 .. 10 as n>
$ {N }=$ {fibo (n )}
</# List>
 
<# Compress>
<# Function fibo n>
<# If n lte 1>
<# Return 1>
<# Elseif n = 2>
<# Return 1>
<# Else>
<# Return fiber (n-1) + fiber (n-2)>
</# If>
</# Function>
</# Compress>
 
[Code 10]
 
In this example, there are some problems that need to be noted. Let's look at my # if n lte 1 line. Why do I write this? Generally, nodes larger than or smaller than numbers conflict with xml nodes. To avoid problems, gt (>) gte (>=) lt (<) lte (<=) is used for representation.
In addition, how to handle complex strings? Let's leave it as a homework assignment. You can remember that the substr method is str [first .. last. The following example may prompt you:
 
<# Assign str = "hello! $ World! ">
<# Assign mid = (str? Length + 1)/2-1>
<# List mid .. 0 as cnt>
$ {Str [(mid-cnt) .. (mid + cnt)]? Left_pad (mid * 2 )}
</# List>
[Code 11]
Finally, let's talk about the very useful macro nested command, without it, maybeFreemarkerWill lose most of the charm. I personally think This is alsoFreemarkerBeyond velocity. Let's take a look at the Code:
<# Assign msg = "hello">
<@ Macro0; index>
$ {Msg }$ {index}
</@ Macro0>
 
<# Macro macro0>
<# List 0 .. 10 as number>
<# Nested number>
</# List>
</# Macro>
[Code 12]
This code serves as a closure ). We use the java Anonymous class to implement the same function as follows:
Interface ICallback
{
Public void call (int index );
}
 
Void Main ()
{
String msg = "hello ";
Macro0 (
New ICallback ()
{
Public void call (int index)
{
System. out. println (msg + index. toString ());
}
}
);
}
 
Void macro0 (ICallback callback)
{
For (int I = 0; I <10; ++ I)
{
Callback. call (I );
}
}
PassFreemarkerIntroductionFreemarkerNow, I want to share my ownFreemarkerExperience.

This article is from the "oecp community" blog, please be sure to keep this source http://oecpby.blog.51cto.com/2203338/432026

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.