我有这个Groovy代码正在使用xpath字符串删除节点,但我在删除xpath导致多个节点实例的节点时遇到问题。
示例XML ...
<root>
<element1>foo</element1>
<element2>bar</element2>
<items>
<item>
<name>a</name>
<desc>b</desc>
<item>
<item>
<name>c</name>
<desc>x</desc>
</item>
</items>
</root>
删除节点的代码......
def resource = XmlSlurper().parseText(xml)
def xpathsToDelete = ['/root/element1','/root/items/item/name']
xpathsToDelete.each {
def pathTokens = it.path.tokenize '/'
def currentNode = resource
if ( currentNode.name() == pathTokens.first() ) {
def xpath = pathTokens.tail().join '/'
currentNode = currentNode."${xpath}"
currentNode.replaceNode{}
}
}
上面的代码使用xpath element1
删除节点/root/element1
,它评估为单个节点,但不适用于评估为多个节点的/root/items/name
。
答案 0 :(得分:2)
这是一个棘手的问题。它与this question有关,这对我的答案至关重要。
这是一个解决方案:
import groovy.util.*
import groovy.xml.*
def xml = """<root>
<element1>foo</element1>
<element2>bar</element2>
<items>
<item>
<name>a</name>
<desc>b</desc>
</item>
<item>
<name>c</name>
<desc>x</desc>
</item>
</items>
</root>"""
def removeNodes = { doc, path ->
def nodes = doc
path.split("\\.").each { nodes = nodes."${it}" }
nodes.each { it.replaceNode{} }
}
def resource = new XmlSlurper().parseText(xml)
def xpathsToDelete = ['/root/element1','/root/items/item/name']
xpathsToDelete.each { xpath ->
def trimXPath = xpath.replaceFirst( "/root/", "").replace("/",".")
removeNodes(resource, trimXPath)
}
println XmlUtil.serialize(new StreamingMarkupBuilder().bind {
mkp.yield resource
})
答案 1 :(得分:2)
这似乎也有效:
import groovy.xml.*
def xml = '''<root>
| <element1>foo</element1>
| <element2>bar</element2>
| <items>
| <item>
| <name>a</name>
| <desc>b</desc>
| </item>
| <item>
| <name>c</name>
| <desc>x</desc>
| </item>
| </items>
|</root>'''.stripMargin()
def newxml = new XmlSlurper().parseText( xml ).with { x ->
[ '/root/element1', '/root/items/item/name' ].each { path ->
def s = path.split( '/' ).drop( 2 ).inject( x ) { element, p ->
element."$p"
}?.replaceNode {}
}
x
}
println XmlUtil.serialize(new StreamingMarkupBuilder().bind {
mkp.yield newxml
})