【问题标题】:Template recursive structure with apache velocity具有 apache 速度的模板递归结构
【发布时间】:2013-07-16 04:54:23
【问题描述】:

我有一个递归数据结构,基本上是一棵树,其中一个节点可能有子节点等等。我正在尝试生成该结构的类似 JSON 的文件。对于使用 #parse 指令的想法。在上下文中,我存储根节点,在 templateName 中存储模板的名称。

{
    "name" = "$node.name",
    "value" = "$node.value"

    #if ($node.childrens.size() > 0)
    ,
    "childrens" = {
        #foreach ($child in $node.childrens)
            ## The next statement does not work
            #parse ($child.type + ".vm", $child)
        #end
    }
    #end
}

apache 速度文档指出#parse 指令only takes one argument

在示例中,我已经看到在调用另一个模板之前使用了 #set 指令,但是如果树的深度高于 2,这将不起作用,因为 #set 指令中使用的变量存储在相同的上下文,所以当从深度 1 到 2 时,变量将被覆盖。

使用#parse 而不是@Sergiu Dumitriu 建议的宏的原因是因为每个节点可能会根据其属性$node.type 以不同的方式呈现。我想为每种类型都有一个模板,这样为特定类型添加模板的人不必与任何其他模板混淆,我的意思是,也许这可以通过打开 type 属性来实现;但这意味着所有的渲染方式都将在同一个文件中定义。

有没有办法使用 Velocity 将模板应用于递归数据结构?


解决方案 根据 Sergiu Dumitriu 的两个答案,最终模板如下所示:

#macro ( displayNode $node)
{
    #set ( $parseNode = $node )
    #set ( $parseTemplate = $parseNode.type + ".vm" )
    #parse ( $parseTemplate )
    #set ( $parseNode = $node )
    #set ( $parseTemplate = "Common.vm" )
    #parse ( $parseTemplate )
}
#end

Common.vm 具有问题中所示的结构。

【问题讨论】:

    标签: java velocity


    【解决方案1】:

    您不应该使用#parse,因为它的操作成本有点高。 Define a macro and use it recursively 代替。

    #macro(displayNode $node)
    {
        "name" = "$node.name",
        "value" = "$node.value"##
        #if ($node.childrens.size() > 0),
        "childrens" = {
            #foreach ($child in $node.children)
                #displayNode($child)
            #end
        }
        #end
    }
    #end
    

    如果模板名也是可变的,可以使用#evaluate动态构造模板名:

            #set ($d = '$')
            #foreach ($child in $node.children)
                #evaluate("#display${child.type}Node(${d}child)")
            #end
    

    【讨论】:

    • 我不认为如果那样的话,它可能会完成工作。我使用 parse 的原因是因为每个节点可能以不同的方式显示,具体取决于节点的类型属性。这就是我使用#parse 的原因。问题中没有明确说明这一点,因此我已更新以反映这一事实。
    • 递归宏有效,宏参数似乎是该宏调用的本地。我还在您的其他答案中提供的#parse 之前使用了#set,所以最终解决方案是两者的混合。
    【解决方案2】:

    要克服默认情况下 Velocity 变量是全局变量的事实,您可以在当前范围内使用局部变量。 Velocity 有several options 用于启用不同的本地范围,包括在渲染模板时创建的模板范围template.provide.scope.control。问题是默认情况下这是禁用的,因此您必须配置 Velocity 才能将其激活。激活此功能后,您将自动拥有一个 $template 变量,您可以使用它来存储局部变量。

    ## The first thing to do is to copy the $node value into a local scope
    ## that won't be overwritten by nested calls
    #set ($template.node = $node)
    {
        "name" = "$template.node.name",
        "value" = "$template.node.value"##
        #if ($template.node.childrens.size() > 0),
        "childrens" = {
            #foreach ($child in $template.node.children)
                ## $template.node doesn't change, so now $node can be freely reassigned
                #set ($node = $child)
                #parse("${child.type}.vm")
            #end
        }
        #end
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-09
      • 2023-03-19
      相关资源
      最近更新 更多