入职第二周了,在熟悉了公司自动化测试脚本的编写(使用什么数据库,使用哪种语言,框架带了哪些方法)后,现在开始熟悉模拟器,我们把请求发到服务器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的使用的更多相关文章

  1. HTML5标签嵌套规则

    × 目录 [1]分类 [2]子元素 [3]总结 前面的话 在html5中,<a>元素的子元素可以是块级元素,这在以前是被认为不符合规则的.本文将详细介绍html5的标签嵌套规则 分类 ht ...

  2. IE浏览器下a标签嵌套img标签默认带有边框

    最近写在线主页时发现IE浏览器下a标签嵌套img标签默认带有边框: 解决办法:img{border:0 none;} 注意,严格意义上0和none都要加上!

  3. riot.js教程【五】标签嵌套、命名元素、事件、标签条件

    前文回顾 riot.js教程[四]Mixins.HTML内嵌表达式 riot.js教程[三]访问DOM元素.使用jquery.mount输入参数.riotjs标签的生命周期: riot.js教程[二] ...

  4. a标签嵌套解决方案

    在实际网页布局之中,我们有时候需要一整块点击区域中间还要有部分按钮点击,也就是需要a标签嵌套a标签,如下: <!-- a标签进行嵌套的时候 --><a href="#hao ...

  5. web@HTML常用标签分类,标签嵌套规则

    一.html标签又叫做html元素,它分为块级元素和内联元素(也可以叫做行内元素),都是html规范中的概念.1.块级元素块级元素是指本身属性为display:block;的元素.因为它自身的特点,我 ...

  6. a标签嵌套a标签在实际项目开发中遇到的坑

    大家都知道HTML的嵌套规范,其中一个规范是块元素嵌套行内元素,块元素嵌套块元素,行内元素嵌套行内元素,行内元素不能嵌套块元素. 其中需要注意的是行内元素嵌套行内元素,a标签虽然是行内元素,但是a标签 ...

  7. 转:前端页面a标签嵌套a标签效果的两种解决方案

      这是由工作中的一个小改动需求得到的这个解决方案的:那个需求是这样的,如图: 需求原来是球队名字没有点击功能的,而蓝色方框两队之间的比赛点击的时候会跳转到比赛文字直播页面.现在需要要求点击球队名字要 ...

  8. 前端 HTML 标签嵌套规则

    标签嵌套规则 块元素可以包含内联元素或某些块元素,但内联元素却不能包含块元素,它只能包含其它的内联元素,例如: <div><div></div><h1> ...

  9. 第153天:关于HTML标签嵌套的问题详解

    HTML标签 1.块级元素 div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.menu.noframe ...

随机推荐

  1. php中count获取多维数组长度的方法

    转自:http://www.jb51.net/article/57021.htm 本文实例讲述了php中count获取多维数组长度的实现方法.分享给大家供大家参考.具体分析如下: 先来看看下面程序运行 ...

  2. mac OS X操作--快捷键

  3. Codeforces 86C Genetic engineering(AC自动机+DP)

    题目大概是给几个DNA片段,求构造一个长度n的字符串的方案数,要求这个字符串每个位置的字符都属于某个包含于此字符串的DNA片段. 把那些DNA片段建一个AC自动机.考虑状态的表示: dp[len][x ...

  4. HDU4135 Co-prime(容斥原理)

    题目求[A,B]区间内与N互质数的个数. 可以通过求出区间内与N互质数的个数的前缀和,即[1,X],来得出[A,B]. 那么现在问题是求出[1,X]区间内与N互质数的个数,考虑这个问题的逆问题:[1, ...

  5. 在python包管理中使用easy_install软件的步骤

    本文主要介绍的是让python包管理变得更加容易的实际应用方法,就是运用easy_install这一软件,下面是文章的具体介绍. easy_install让python包管理变得 如果你想对Pytho ...

  6. CodeForces Round 192 Div2

    This is the first time I took part in Codeforces Competition.The only felt is that my IQ was contemp ...

  7. 【BZOJ】1818: [Cqoi2010]内部白点(树状数组+离散+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1818 这一题一开始我就看错了,bzoj的那个绝对值109简直坑人,应该是10^9,我直接写了个暴力. ...

  8. Java实现FTP文件上传与下载

    实现FTP文件上传与下载可以通过以下两种种方式实现(不知道还有没有其他方式),分别为:1.通过JDK自带的API实现:2.通过Apache提供的API是实现. 第一种方式 package com.cl ...

  9. python 面向对象的三大特征之 继承

    #继承 #object 基类,是python定义的所有类的父类 #经典类:不继承object的类称作经典类 #新式类:继承object的类称作新式类 #python 3.x统一为新式类 #经典类是类对 ...

  10. Geronimo应用服务器和MySQL数据库服务器

    就是Web 2.0的全部,尽管该术语出现才几乎一年的时间,但现在好像只有烹饪杂志还没有加入到讨论Web 2.0未来出路的行列中.自从出现了里程碑式的文章"What Is Web 2.0:De ...