【问题标题】:How can I get #evaluate to put its results into the page scope?如何让#evaluate 将其结果放入页面范围?
【发布时间】:2019-04-08 20:01:13
【问题描述】:

我无法让#evaluate 使用我见过的任何可接受的解决方案来设置变量,以便在 Confluence 中使用 Velocity 将 JSON 字符串转换为地图。

我有一个来自另一个系统的 JSON 字符串,用于生成动态数据。在开发过程中,我可以直接使用地图:

#set($textMapRaw = [{"ace":"clubs"}])

$textMapRaw.get(0).ace

最后一行呈现为“俱乐部”。

我曾期望使用#evaluate 将实时数据转换为对象数组。但是,当我对它执行任何操作时,#evaluate 似乎并没有将声明的变量放回范围。这是以字符串形式出现的同一张地图:

#set($textMapHtml = '[{"ace":"clubs"}]')
#set($evalHtml = '#set($myMapHtml = '+ $textMapHtml +')')
evalHtml = $evalHtml<br/>
#evaluate($evalHtml)

$myMapHtml.get(0).ace

最后一行呈现为“$myMapHtml.get(0).ace”。

我知道 $myMapHtml 正在被评估,因为当我没有将 Html 附加到它的末尾以避免 Confluence 的自动转义恶作剧时,我得到了一个评估堆栈跟踪。

我已经尝试过使用 ${hash}set 转义 set 中的哈希值。我试过单引号和双引号。我已经尝试通过评估设置一个字符串:

#evaluate('#set($dippity = "doo")')
$dippity

#set($hash = '#')
#evaluate("${hash}set($blue = 'moon')")
$blue

无论我对任何已批准的#evaluate 代码做什么,它都不会被评估到 Confluence 的范围内。我总是得到与未定义变量相同的结果。

注意:在我们的环境中,我无法在 Java 中解决问题并将其推送到模板中。我需要找到一个纯粹的模板内解决方案。

【问题讨论】:

  • 如果我使用 Velocity 1.7 或 2.0 在我的测试环境中复制并粘贴您的代码,它可以工作...您使用的是哪个版本的 Velocity?
  • 您是否在 Confluence 中执行此操作?这就是诀窍。我相信 Confluence 6.13 使用的是 Velocity 1.6.4。但这似乎是 Confluence 的问题。

标签: velocity confluence


【解决方案1】:

Velocity 1.6.4 不允许从 #evaluate 指令中修改评估上下文。因此,在使用此版本时,无法使用动态名称创建上下文条目。

不过,您可以将它们存储在地图中:

#set( $stringMap = '[{"ace":"clubs"}]' )

#set( $myMap = {} )
#set( $eval = '#set($list = ' + $stringMap + ') #set ($myMap.ace = 
$list.get(0).ace)' )
#evaluate( $eval )

$myMap.ace ## prints 'clubs'

【讨论】:

  • 第 2 行出现错误,因为您没有为 set/put 指令放置一次性变量。添加它并运行代码并不能实现将字符串转换为可迭代映射数组的目标。 HTML 的值是一个字符串。
  • @Kevin - 根据您的 cmets 进行编辑。但是看到你的答案,显然你确实明白了......
  • 感谢您让我免于继续尝试将变量放回全局范围。
【解决方案2】:

由于您似乎无法将变量恢复到当前范围,因此我想出了一个解决方法。只需使用评估将数组/映射传递给宏。

如果您尝试在评估代码或它调用的宏之外操作变量,您仍然会遇到范围问题,但如果您小心,您可以围绕它编写代码。

在我的例子中,我在宏中移动了另一段代码,以利用本地范围来确定处理了多少项。

#macro(processMap $theMap)
  #set($count = 0)
  #foreach($item in $theMap)
    #set($count = $velocityCount)
    <p>This thing is $item.tweedle</p>
  #end
  <p><b>I did that $count times</b></p>
#end

#set($workaroundHtml = '[{"tweedle":"dee"},{"tweedle":"dum"}]')

#set($eval = '#processMap(' + $workaroundHtml + ')')

#evaluate($eval)

【讨论】:

    猜你喜欢
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多