I have the following xml:
<list>
<cars>
<model>2012</model>
<make>GM</make>
</cars>
</list>
I want to print these values as path:value as shown below.
list/cars/model : 2012
list/cars/make : GM
How can I achieve this? I tried the name()
method but it only prints the name of child item. I want to print the whole path till the element.
I can only use xmlSlurper parser to do this.
Thanks.
import groovy.util.XmlSlurper
import groovy.util.slurpersupport.NodeChild;
def rootNode = new XmlSlurper().parseText('<root><one a1="uno!"/><two>Some text!</two></root>' )
def printMap
printMap = {node, path->
if(node.getClass() == NodeChild){
node.childNodes().each{
printMap(it, (path ? path + "/" : "") + node.name())
}
} else {
println "${path}/${node.name()}:${node.text()}"
}
}
printMap(rootNode, "")
def xml = '''
<list>
<cars>
<model>2012</model>
<make>GM</make>
<color>Gold</color>
</cars>
</list>
'''
def item = new XmlSlurper().parseText(xml)
item.'**'.inject([]) { acc, val ->
def localText = val.localText()
acc << val.name()
if( localText ) {
println "${acc.join('/')} : ${localText.join(',')}"
acc = acc.dropRight(1) // or acc = acc[0..-2]
}
acc
}
This would print as required. Above is using a depthFirst()
search on the tree and using inject (just not to mutate any other list) and looks for localText()
. If localText()
is encountered indicating the value of the leaf node, then print the path and the value. The path has been accumulated in a list which was used in inject. A simple join()
would give the required format.
Above has been tested successfully in Groovy 2.4.5. If localText()
is not available in NodeChild
then a version of Groovy older than 2.3.0 would be reason because that method has been added since 2.3.0
来源:https://stackoverflow.com/questions/34711262/groovy-print-path-and-value-of-elements-in-xml