Удаление узлов в XML с помощью Xpath в 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{}
}
}
Приведенный выше код удаляет узел
element1 с помощью xpath /root/element1, который вычисляется для одного узла, но не работает для /root/items/name, который вычисляется для нескольких узлов. 2 ответов:
Это очень сложно. Это связано с этим вопросом, который жизненно важен для моего ответа.
Вот решение:
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 })
Это, кажется, тоже работает:
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 })
Comments