Freemarker的初次使用之FTL标签嵌套与map的使用
入职第二周了,在熟悉了公司自动化测试脚本的编写(使用什么数据库,使用哪种语言,框架带了哪些方法)后,现在开始熟悉模拟器,我们把请求发到服务器1,服务器1根据请求参数处理后将结果发给模拟器,模拟器根据服务器1的处理结果再次调用脚本进行处理,然后将结果返回。我需要做的就是编写模拟器所调用的脚本。前两天使用的是SimpleTemplateEngine模版,进行简单的处理,然后周三的时候换成FreemarkerTemplate模版来进行处理。
Freemarker这个我以前根本就没接触,赶紧从官网下载资料学习,而在这个过程中,我看到网上有几篇帖子批评Freemarker(比如这个帖子:http://flym.iteye.com/blog/750454),其中有一点是“3.2 map问题,即freemarker中不能支持非string的key值,这样在进行一些复杂迭代时就需要作一些其他的转换,如将一个map拆分为两个或多个map。”唉,当时眼花了,以为是freemarker中不能支持非String的value值。然后又从官网文档中看到FTL标签不可以在其他FTL标签和插值中使用。而我要完成的任务是分别将RoomTypeCandidates、RatePlanCandidates、LOSCandidate的子节点的文本保存成列表,
<RoomTypeCandidates>
<RoomTypeCandidate>2QueenBalconyOr</RoomTypeCandidate>
<RoomTypeCandidate>1King</RoomTypeCandidate>
<RoomTypeCandidate>1KingAccessible</RoomTypeCandidate>
</RoomTypeCandidates>
<RatePlanCandidates>
<RatePlanCandidate>HiltonFlexibleRetail</RatePlanCandidate>
<RatePlanCandidate>HiltonAdvanceLongRetail</RatePlanCandidate>
</RatePlanCandidates>
<LOSCandidates>
<LOSCandidate>1</LOSCandidate>
<LOSCandidate>2</LOSCandidate>
<LOSCandidate>3</LOSCandidate>
然后将结果<RoomStay RoomTypeCode="RoomTypeCandidate" RatePlanCode="RatePlanCandidate" LengthOfStay="LOSCandidate" RoomCount="9">中。从给我的结果文件来看,需要输出RoomTypeCandidates、RatePlanCandidates、LOSCandidate的所有排列组合,也就是3*2*3次。模版文件只能有这一行。 这样的话我就不得不在模版中使用list,而map的value也不可避免要使用list类型,并且FTL标签肯定要嵌套。当时心里只有个想法,这完全不科学啊,于是我在将文本取出存入list后就不知道该怎么办了,赶紧问带我的师傅拿份模版和脚本的样例。
在看那份脚本的样例时,我心凉了半截,因为连我这个门外汉都看出来这个脚本太不正规了,有一个方法跟另一个方法功能重复(不是重载),还有一个方法,居然在迭代循环中把同样的key和不同的value存入hashMap中。没办法,硬着头皮看下去,发现对方直接将json存入map中然后用Freemarker调用,Freemarker模版也是FTL标签嵌套(<#list ...><#list ...></#list></#list>).赶紧向师傅提出疑问,师傅只是让我试试。我想试试就试试吧。我于是往map的value中存入list,然后也是用FTL标签嵌套。结果居然成了。
现在看看官网文档
FTL标签不可以在其他FTL标签和插值中使用。下面这样写就是错的:
<#if <#include 'foo'>='bar'>...</#if> 也许<#include 'foo'>是在<#if和>中间,而不是<#if>和</#if>中间,官网才说它是错的
我把我写的脚本贴上来,感兴趣的朋友可以试试,文件路径自己改。
Groovy脚本:
import freemarker.template.Configuration
import freemarker.template.Template
import groovy.text.SimpleTemplateEngine
import org.dom4j.DocumentException
import org.dom4j.DocumentHelper
import org.jaxen.JaxenException
import org.jaxen.SimpleNamespaceContext
import org.jaxen.XPath
import org.jaxen.dom4j.Dom4jXPath
import org.dom4j.Element
import org.dom4j.io.SAXReader
import org.dom4j.Document
import org.joda.time.LocalDate
import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory
import com.derby.nuke.common.module.config.ApplicationConfiguration
public class XMLUtil {
private static final HashMap<String, String> NAMESPACES = new HashMap<String, String>()
static {
NAMESPACES.put("ari", "http://www.XXX.com/nuke/ari")
NAMESPACES.put("rac", "http://www.XXX.com/dswitch/rac")
NAMESPACES.put("ota", "http://www.XXX.org/OTA/2003/05")
NAMESPACES.put("", "")
}
public static List<Element> getElements(Document document,
String xpathString) throws JaxenException {
XPath xpath = new Dom4jXPath(xpathString)
xpath.setNamespaceContext(new SimpleNamespaceContext(NAMESPACES))
return xpath.selectNodes(document)
}
public static String getElementAttribute(String attribute,
Document document, String xpathString) throws JaxenException {
XPath xpath = new Dom4jXPath(xpathString)
xpath.setNamespaceContext(new SimpleNamespaceContext(NAMESPACES))
Element element = (Element) xpath.selectSingleNode(document)
if (element == null) {
return null
}
return element.attributeValue(attribute)
}
public List<String> getElementTextList(Document doc,String xpathString){
List<String> ls=new ArrayList()
List<Element> le=XMLUtil.getElements(doc, xpathString)
if(le.size()!=0){
for(Element e:le){
ls.add(e.getText())
}
return ls
}else{
return null
}
}
public String useFreemarkerTemplate(request){
Document doc=DocumentHelper.parseText(request)
List roomTypeCandidateList=getElementTextList(doc,"//ari:RoomTypeCandidate")
List ratePlanCandidateList=getElementTextList(doc,"//ari:RatePlanCandidate")
List lOSCandidateList=getElementTextList(doc,"//ari:LOSCandidate")
String hotelCode=XMLUtil.getElementAttribute("HotelCode",doc,"//ari:RetrieveChangeCriteria")
String start=XMLUtil.getElementAttribute("Start",doc,"//ari:DateSpan")
String end=XMLUtil.getElementAttribute("End",doc,"//ari:DateSpan")
Map responsemap=new HashMap();
responsemap.put("HotelCode",hotelCode);
responsemap.put("Start",start);
responsemap.put("End",end);
responsemap.put("roomTypeCandidateList",roomTypeCandidateList);
responsemap.put("ratePlanCandidateList",ratePlanCandidateList);
responsemap.put("lOSCandidateList",lOSCandidateList);
Configuration config=new Configuration();
// String resourceHome = ApplicationConfiguration.get().getApplicationConfigDirectory() + "/dispatch/";
String resourceHome ="D:/testTool/apache-tomcat-7.0.61/person/simulator/dispatch"
config.setDirectoryForTemplateLoading(new File(resourceHome));
config.setDefaultEncoding("UTF-8");
Template templateFile=config.getTemplate("_simulator_justtest.xml");
StringWriter writer = new StringWriter();
templateFile.process(responsemap, writer);
return writer.toString();
}
String request="""<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope xmlns="http://www.derbysoft.com/nuke/ari" xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<soap11:Body>
<GetDailyChangeRequest Token="293FE0D7-CBB7-4035-B76A-DE6E24FEFF0D">
<Contract ChannelCode="AA9011CA33A2E854774EA76F2EBF423336C6" SupplierCode="HILTON"/>
<RetrieveChangeCriteria HotelCode="code01" Type="All">
<DateSpan Start="2016-04-04" End="2016-04-16"/>
<RoomTypeCandidates>
<RoomTypeCandidate>2QueenBalconyOr</RoomTypeCandidate>
<RoomTypeCandidate>1King</RoomTypeCandidate>
<RoomTypeCandidate>1KingAccessible</RoomTypeCandidate>
</RoomTypeCandidates>
<RatePlanCandidates>
<RatePlanCandidate>HiltonFlexibleRetail</RatePlanCandidate>
<RatePlanCandidate>HiltonAdvanceLongRetail</RatePlanCandidate>
</RatePlanCandidates>
<LOSCandidates>
<LOSCandidate>1</LOSCandidate>
<LOSCandidate>2</LOSCandidate>
<LOSCandidate>3</LOSCandidate>
<LOSCandidate>4</LOSCandidate>
<LOSCandidate>5</LOSCandidate>
</LOSCandidates>
<Properties/>
</RetrieveChangeCriteria>
</GetDailyChangeRequest>
</soap11:Body>
</soap11:Envelope>
"""
println useFreemarkerTemplate(request)
下面是Freemarker的模版
<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope xmlns="http://www.XXX.com/nuke/ari" xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<soap11:Body>
<GetAvailabilityChangeResponse>
<#-- input hotelcode -->
<AvailabilityUpdate HotelCode="${HotelCode}">
<RoomStays>
<#list roomTypeCandidateList as rtcList>
<#list ratePlanCandidateList as rpcList>
<#list lOSCandidateList as loscList>
<RoomStay RoomTypeCode="${rtcList}" RatePlanCode="${rpcList}" LengthOfStay="${loscList}" RoomCount="9">
<#-- input startdate and enddate -->
<DateSpan Start="${Start}" End="${End}"/>
</RoomRate>
</DateSpan>
</RoomStay>
</#list>
</#list>
</#list>
</RoomStays>
</GetAvailabilityChangeResponse>
</soap11:Body>
</soap11:Envelope>
Freemarker的初次使用之FTL标签嵌套与map的使用的更多相关文章
- HTML5标签嵌套规则
× 目录 [1]分类 [2]子元素 [3]总结 前面的话 在html5中,<a>元素的子元素可以是块级元素,这在以前是被认为不符合规则的.本文将详细介绍html5的标签嵌套规则 分类 ht ...
- IE浏览器下a标签嵌套img标签默认带有边框
最近写在线主页时发现IE浏览器下a标签嵌套img标签默认带有边框: 解决办法:img{border:0 none;} 注意,严格意义上0和none都要加上!
- riot.js教程【五】标签嵌套、命名元素、事件、标签条件
前文回顾 riot.js教程[四]Mixins.HTML内嵌表达式 riot.js教程[三]访问DOM元素.使用jquery.mount输入参数.riotjs标签的生命周期: riot.js教程[二] ...
- a标签嵌套解决方案
在实际网页布局之中,我们有时候需要一整块点击区域中间还要有部分按钮点击,也就是需要a标签嵌套a标签,如下: <!-- a标签进行嵌套的时候 --><a href="#hao ...
- web@HTML常用标签分类,标签嵌套规则
一.html标签又叫做html元素,它分为块级元素和内联元素(也可以叫做行内元素),都是html规范中的概念.1.块级元素块级元素是指本身属性为display:block;的元素.因为它自身的特点,我 ...
- a标签嵌套a标签在实际项目开发中遇到的坑
大家都知道HTML的嵌套规范,其中一个规范是块元素嵌套行内元素,块元素嵌套块元素,行内元素嵌套行内元素,行内元素不能嵌套块元素. 其中需要注意的是行内元素嵌套行内元素,a标签虽然是行内元素,但是a标签 ...
- 转:前端页面a标签嵌套a标签效果的两种解决方案
这是由工作中的一个小改动需求得到的这个解决方案的:那个需求是这样的,如图: 需求原来是球队名字没有点击功能的,而蓝色方框两队之间的比赛点击的时候会跳转到比赛文字直播页面.现在需要要求点击球队名字要 ...
- 前端 HTML 标签嵌套规则
标签嵌套规则 块元素可以包含内联元素或某些块元素,但内联元素却不能包含块元素,它只能包含其它的内联元素,例如: <div><div></div><h1> ...
- 第153天:关于HTML标签嵌套的问题详解
HTML标签 1.块级元素 div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.menu.noframe ...
随机推荐
- hbase shell中log4j重复问题
[root@centos ~]# hbase shellSLF4J: Class path contains multiple SLF4J bindings.SLF4J: Found binding ...
- TYVJ 1011 NOIP 2008&&NOIP 2000 传纸条&&方格取数 Label:多线程dp
做题记录:2016-08-15 15:47:07 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...
- 【NOI2015】荷马史诗
追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由<奥德赛>和& ...
- asp.net 微信企业号办公系统-流程设计--流程步骤设置-数据设置
数据设置是控制在流程处理过程中,当前步骤的数据显示与编辑状态,控制当前步骤哪些字段为只读,隐藏或可编辑.需要配合表单设计器使用.
- FreeMarker教程
一.什么是模板引擎,为什么要用模板引擎 在B/S程式设计中,常常有美工和程序员二个角色,他们具有不同专业技能:美工专注于表现——创建页面.风格.布局.效果等等可视元素:而程序员则忙于创建程式的商业流程 ...
- JAVA图片处理--缩放,切割,类型转换
import java.io.*; import java.awt.*; import java.awt.image.*; import java.awt.Graphics; import java. ...
- HTML中为何P标签内不可包含块元素?
起因:在做项目时发现原本在DW中无误的代码到了MyEclipse6.0里面却提示N多错误,甚是诧异.于是究其原因,发现块级元素P内是不能嵌套DIV的. 深究:我们先来认识in-line内联元素和blo ...
- OpenCV 3.0 VS2010 Configuration
Add in the system Path: C:\opencv\build\x86\vc10\bin; Project->Project Property->Configuration ...
- Go学习记录
操作系统:Windows 一.下载 go官网:https://golang.org/go下载地址:https://golang.org/dl/ 二.安装 安装包有msi安装版本,以及zip压缩包版本. ...
- [办公自动化]skydrive onedrive
国内暂时无法访问onedrive,请按如下步骤操作尝试:依次如下:在开始菜单里,单击“所有程序”,找到“附件”,单击找到里面的“记事本”,右键,然后选择“以管理员身份运行”,如果有对话框,选择“是”. ...