带有文本节点的XmlTool节点列表的Velocity #foreach

时间:2018-01-30 10:21:09

标签: java templates dom foreach velocity

我正在尝试编写一个使用DOM对象的Velocity模板。特别是我的依赖项是Velocity 1.7和Velocity-tools 2.0。

在文档之后,这就是我将DOM传递给模板引擎的方式:

XmlTool tool = new XmlTool().parse(xmlString);
VelocityContext context = new VelocityContext();
context.put("xml", tool);
...

假设这是我原来的XML文档:

<root>
    <foo>
        <bar>
            <baz>10</baz>
            <qux>NO</qux>
        </bar>
        <bar>
            <baz>20</baz>
            <qux>YES</qux>
        </bar>
        <bar>
            <baz>30</baz>
            <qux>NO</qux>
        </bar>
    </foo>
</root>

这是我的模板文件:

#if($xml.foo)
<document>
    #foreach($bar in $xml.foo)
    <repeatableElement>
        <aaa>$bar.baz.text</aaa>
        <bbb>$bar.qux.text</bbb>
    </repeatableElement>
    #end
</document>

现在我的问题是,如果我运行它,输出看起来像:

<document>
    <repeatableElement>
        <aaa>102030</aaa>
        <bbb>NOYESNO</bbb>
    </repeatableElement>
    <repeatableElement>
        <aaa>102030</aaa>
        <bbb>NOYESNO</bbb>
    </repeatableElement>
    <repeatableElement>
        <aaa>102030</aaa>
        <bbb>NOYESNO</bbb>
    </repeatableElement>
</document>

如您所见,#foreach循环正确地为每个repeatableElement对象打印一个$bar。但是.text个孩子的$bar方法也会连接兄弟姐妹的文本节点!
我想要的是单独访问每个叶文本节点:

<repeatableElement>
    <aaa>10</aaa>
    <bbb>NO</bbb>
</repeatableElement>
<repeatableElement>
    <aaa>20</aaa>
    <bbb>YES</bbb>
</repeatableElement>
...

任何提示都表示赞赏。谢谢!

1 个答案:

答案 0 :(得分:1)

这是Tools 2.0 XmlTool的一个已知问题,其getter调用JDOM方法getPath()而不是getUniquePath()。所以$bar.baz返回所有节点。

要解决此问题,您可以直接使用基础JDOM API:

#if($xml.foo)
<document>
    #foreach($bar in $xml.foo.children())
    <repeatableElement>
        <aaa>$bar.node().element('baz').text</aaa>
        <bbb>$bar.node().element('qux').text</bbb>
    </repeatableElement>
    #end
</document>
#end

(另请注意,您应该循环$xml.foo.children())。