Groovy:用 GPathResult.appendNode(节点)合并两个 XML 文件不起作用

Groovy: merging two XML files with GPathResult.appendNode(node) does not work

我需要编写一个脚本,它包含几个 XML 文件并根据它们的内容执行一些操作。为了更轻松地浏览所有元素,我想将所有文件合并到一棵 XML 树中(仅在内存中)。我试过使用 appendNode() 方法,但我遇到了非常奇怪的行为。这是我用来展示问题的片段:

def slurper = new XmlSlurper()
def a = slurper.parseText("<a></a>")
def b = slurper.parseText("<b>foo</b>")
a.appendNode(b)

println XmlUtil.serialize(a)

a."**".each { println (it.name()) }

它输出:

<?xml version="1.0" encoding="UTF-8"?><a>
  <b>foo</b>
</a>

a

序列化 XML 是正确的,但我没有从迭代器中得到 <b>

但是,如果我在附加后添加此行:

a = slurper.parseText(XmlUtil.serialize(a))

输出如下所示:

<?xml version="1.0" encoding="UTF-8"?><a>
  <b>foo</b>
</a>

a
b

<b> 如我所料。

我在这里错过了什么?为什么再次解析和序列化会改变输出?我是 Groovy 的新手,所以我想这可能是显而易见的事情,请帮助我理解为什么会这样。或者也许有更好的方法来合并 XML 个文件?

发生这种情况是因为 XmlSlurper.parse(String text) returns GPathResult 即:

Base class for representing lazy evaluated GPath expressions.

并且根据Groovy XML processing documentation

XmlSlurper evaluates the structure lazily. So if you update the xml you’ll have to evaluate the whole tree again.

这就是为什么你必须用

重新评估 XML 树
a = slurper.parseText(XmlUtil.serialize(a))

让你的表情发挥作用。

另一方面,如果您使用 XmlParser,则无需重新评估 XML 树即可使其正常工作,例如

import groovy.xml.XmlUtil

XmlParser root = new XmlParser()
def a = root.parseText("<a></a>")
def b = root.parseText("<b>foo</b>")

a.append(b)

println XmlUtil.serialize(a)

a."**".each { println (it.name()) }

输出

<?xml version="1.0" encoding="UTF-8"?><a>
  <b>foo</b>
</a>

a
b