Iterate all children with a given name using GPathResult returned by XmlSlurper
I've parsed some html using XmlSlurper. Now I want to iterate all the children with a given element name.
What I've got now is the following code snippet
html.'**'.findAll { it.name() == 'a' }.each {
println it
}
It works but just isn't groovy enough. I would like to simply write something like this
html.'**'.a.each {
println it
}
If I do it this way, GPath complains that there is no property with name 'a'. Any idea if there is an easy syntax to formulate this iter开发者_JAVA技巧ation?
Unfortunately, there is currently no way in Groovy to perform what you're asking.
When you perform such operation on a GPathResult (or any of its children)
html."**".a.b.c
What is done is that for each "." a call to the GPathResult.getProperty() method is made. And this method as only a few valid syntactic sugar (*, **, .. and @). This means that if you don't use one of them, it assume that the property really exist for each node you're targeting.
If you would like to have a conditional null-safe operator for traversing your tree, it would request either the addition of a syntactic sugar prefix (e.g. "?a" ) in the GPathResult class. Maybe that you can achieve that using the expando metaclass and overriding the getProperty method, but I did not try it.
Use recursive closure:
def out = new StringBuffer()
def printNode
printNode = { o,node ->
o << '<' + node.name()
node.attributes().each{ o << ' ' + it.key + '="' + it.value + '"' }
o << '>'
node.children().each{ printNode(out,it) }
o << '</' + node.name() + '>'
}
html.'**'.findAll { it.name() == 'a' }.each { printNode(out,it) }
println out.toString()
精彩评论