我尝试通过删除在保留这些元素的所有子项(嵌套元素和文本)时错误添加的标记(下例中的b标记)来修改XML文件。我希望用XMLParser做到这一点,因为这是一个更大的脚本的一部分,其中元素的顺序在后期发挥作用。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<b>
<c />
Test 1
</b>
<b>
<c />
Test 2
</b>
</a>
我想要的东西类似于:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<c />
<c />
Test 1
Test 2
</a>
到目前为止,我尝试了以下(args [0]是一个包含上述示例的文件),目的是简单地将所有子节点附加到父节点:
import groovy.xml.XmlUtil
def f = new File(args[0])
def parser = new XmlParser()
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
parser.setFeature("http://xml.org/sax/features/namespaces", false)
def log = parser.parse(f)
def bs = log.'**'.findAll { node -> (node instanceof Node) && node.name() == 'b' }
bs.each { b ->
Node bparent = b.parent()
def bchildren = b.children()
bchildren.each { child ->
if (child instanceof Node) {
bparent.append(child)
}
}
b.replaceNode{}
}
def xmlu = new XmlUtil()
def result = XmlUtil.serialize(log)
println result
但是使用此代码,我丢失了元素的实际文本内容,因为XMLParser返回Node和String对象。所以输出看起来:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<c />
<c />
</a>
有没有办法将String对象添加到父节点?或者到目前为止我可能忽略了一种更为简单的方法?
答案 0 :(得分:1)
这似乎有效......克隆节点并将它们添加到父节点,然后从它的父节点中删除b:
def xmlText = '''<?xml version="1.0" encoding="UTF-8"?>
<a>
<b>
<c />
Test 1
</b>
<b>
<c />
Test 2
</b>
</a>'''
import groovy.xml.*
def xml = new XmlParser().parseText(xmlText)
def bs = xml.'*'.findAll { it.name() == 'b' }
bs.each { b ->
b.children().collect { it instanceof Node ? it.clone() : it }.each { b.parent().children().add(it) }
b.parent().remove(b)
}
println XmlUtil.serialize(xml)
答案 1 :(得分:0)
以下将输出
<?xml version='1.0' encoding='UTF-8'?>
<a foo='bar'>
<c blub='bla' />
Test 1
<c />
Test 2
</a>
import groovy.xml.*
def parser = new XmlParser()
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
parser.setFeature("http://xml.org/sax/features/namespaces", false)
def log = parser.parseText('''<?xml version="1.0" encoding="UTF-8"?>
<a foo="bar">
<b bii="boo">
<c blub="bla" />
Test 1
</b>
<b>
<c />
Test 2
</b>
</a>''')
def recurse
recurse = { builder, element ->
element.children().each { child ->
switch (child) {
case { (it instanceof Node) && (it.name() == 'b') }:
recurse builder, child
break
case { it instanceof Node }:
builder."${child.name()}"(child.attributes()) {
recurse builder, child
}
break
default:
builder.mkp.yield child
break
}
}
}
def builder = new MarkupBuilder(new PrintWriter(System.out))
builder.mkp.xmlDeclaration version: '1.0', encoding: 'UTF-8'
builder."${log.name()}"(log.attributes()) {
recurse builder, log
}