Reputation: 1621
Groovy code:
def root = new XmlParser().parseText(new File("sample.xml").getText())
void row (def path,q)
{
q.path.each {
println it.value()
}
}
row ("food.name",root)
The sample xml file link is here.
Normally, root.food.name.each{}
works. but in above shown code it is not working. It prints nothing.
Expected output:
[Belgian Waffles]
[Strawberry Belgian Waffles]
[Berry-Berry Belgian Waffles]
[French Toast]
[Homestyle Breakfast]
Upvotes: 0
Views: 60
Reputation: 171144
You can split and walk the path using inject
:
void row(path, node) {
path.split('\\.').inject(node) { n, p -> n."$p" }.each {
println it.value()
}
}
def root = new XmlParser().parse('https://www.w3schools.com/xml/simple.xml')
row('food.name', root)
Upvotes: 3
Reputation: 21379
You can achieve the same using below script to extract all the food names as shown below (follow inline comments):
//Parse from file
def xml = new XmlSlurper().parse(new File('simple.xml'))
//Get all food nodes
def foods = xml.'**'.findAll {it.name() == 'food'}
//Get food names
def foodNames = foods.collect{it.name.text()}
//Print them
foodNames.each {println it}
Of course, you can even achieve the same in one liner:
println xml.'**'.findAll{it.name() == 'food'}?.name*.text()
Upvotes: 0
Reputation: 9175
By calling
q.path.each {
println it.value()
}
You do not use the path
variable actually, you just try to get path
element of the root node.
root.food.name.each{}
is fine and clean I think.
Or you can use variable in a loop
path.split('.').each { q = q[it] }
q.each { println it.value() }
Upvotes: 0
Reputation: 635
I don't think you can do that in the way you are trying it. root.food.name.each{}
is not the same as root."food.name".each{}
(there is not "food.name" but "food"). An alternative way get the same results for root.food.name.each{}
is root["food"]["name"].each{}
. In this way is more readable that you are accessing level by level of the xml.
Upvotes: 1