Bhanuchander Udhayakumar
Bhanuchander Udhayakumar

Reputation: 1621

Why this simple code doesn't work? How to solve this?

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.

Update 1:

Expected output:

[Belgian Waffles]
[Strawberry Belgian Waffles]
[Berry-Berry Belgian Waffles]
[French Toast]
[Homestyle Breakfast]

Upvotes: 0

Views: 60

Answers (4)

tim_yates
tim_yates

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

Rao
Rao

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

aristotll
aristotll

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

rvargas
rvargas

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

Related Questions