参数与Java类名匹配的Groovy模板引擎

参数与Java类名匹配的Groovy模板引擎,groovy,Groovy,我相信这很简单 我们使用Groovy模板引擎将XML文档格式化为人类可读的形式。代码扫描XML并为XML中的每个项目创建一个带有条目的映射,然后将其传递给Groovy模板引擎 当XML包含与类名匹配的属性时会出现问题- 类似这样的内容:某个日期。如果模板文件指定Date为$Date(例如),而不是实际的日期字符串,我们将得到类java.util.Date。我们尝试了$Date的变体,如${Date}和${Date.toString()}等,但没有成功 我们认为问题在于Groovy混淆了Date输

我相信这很简单

我们使用Groovy模板引擎将XML文档格式化为人类可读的形式。代码扫描XML并为XML中的每个项目创建一个带有条目的映射,然后将其传递给Groovy模板引擎

当XML包含与类名匹配的属性时会出现问题- 类似这样的内容:
某个日期
。如果模板文件指定
Date为$Date
(例如),而不是实际的日期字符串,我们将得到
类java.util.Date
。我们尝试了
$Date
的变体,如
${Date}
${Date.toString()}
等,但没有成功

我们认为问题在于Groovy混淆了Date输入变量和java.util.Date类,但我确信有某种语法可以使其正常工作。因为我们通过这个方法提供任意用户定义的XML,所以我们实际上无法控制XML中的属性名称之类的东西

这里有几行代码可以复制这个问题:

def map = [:]
map.putAt("Date",  new Date())  // Fails
map.putAt("Date2", new Date())  // Works
def tf = new File("Test.template")
def gte = new GStringTemplateEngine()
def tpl = gte.createTemplate(tf).make(map.withDefault{null})
println tpl.toString()
“Test.template”文件包含:

Date is ${Date.toString()}.
Date is ${Date2.toString()}.
我们得到的结果是:

Date is class java.util.Date.
Date is Tue Jun 06 20:22:16 EDT 2017.

是的,groovy似乎在绑定名为
Date

那么,为什么不将所有xml属性作为一个绑定变量传递呢

def map = [:]
map.putAt("Date",  new Date())  // Fails
map.putAt("Date2", new Date())  // Works
def gte = new groovy.text.GStringTemplateEngine()
def tpl = gte.createTemplate('''
Date  :: ${ctx.Date.toString()}
Date2 :: ${ctx.Date2.toString()}
''').make( [ctx:map].withDefault{null})

println tpl.toString()
也可以通过这种访问器
委托访问变量。“我的奇怪变量”

def map = [:]
map.putAt("Date",  new Date())  // Fails
map.putAt("Date2", new Date())  // Works
def gte = new groovy.text.GStringTemplateEngine()
def tpl = gte.createTemplate('''
Date  :: ${delegate.'Date'.toString()}
Date2 :: ${Date2.toString()}
''').make( map.withDefault{null})

println tpl.toString()

在这里回答我自己的问题,以防万一其他人也有类似的问题

我们发现Groovy“getVariable()”方法是一种适合我们的解决方案。getVariable()方法返回任何变量的值,并在模板引擎中公开。将上面示例中的模板更改为:

Date is ${getVariable("Date")}

为我们解决了这个问题

我相信模板引擎是区分大小写的,对吗?在将标记值放入地图之前,是否可以尝试将其大写?否则,将其设置为可以访问另一个对象的子对象。比如myThing.Date.toString。这将确保您拥有正确的日期。可能存在数百个现有模板的副本,因此您的建议需要更改它们,我们希望避免这种情况。您可以以旧样式和新样式传递变量。对于您提到的情况,请使用新样式访问器,或者对于所有新模板,请使用新访问器。因此,您可以同时支持这两种方法。顺便说一句,当您的变量在中被命名为关键字
如果
。。。