3

I'm trying to analyse an XML tree using XmlSlurper and GPath, and the behaviour of the findAll method confuses me.

Say, for example, that you have the following XML tree:

<html>
    <body>
        <ul>
            <li class="odd"><span>Element 1</span></li>
            <li class="even"><span>Element 2</span></li>
            <li class="odd"><span>Element 3</span></li>
            <li class="even"><span>Element 4</span></li>
            <li class="odd"><span>Element 5</span></li>
        </ul>
    </body>
</html>

Assuming that xml has been initialised through one of XmlSlurper's parse methods, the following code executes as one would expect:

// Prints:
// odd
// odd
// odd
xml.body.ul.li.findAll {it.@class == 'odd'}.@class.each {println it.text()}

On the other hand:

// Doesn't print anything.
xml.body.ul.li.findAll {it.@class == 'odd'}.span.each {println it.text()}

I'm struggling to understand why I can use the special @ property (as well as others, such as **), but not 'normal' ones.

I've looked at the API code, and what confuses me even more is that the getProperty implementation (found in GPathResult) seems to support what I'm trying to do.

What am I missing?

Nicolas Rinaudo
  • 6,068
  • 28
  • 41

1 Answers1

3

You need to iterate over every span, so you can use the spread-dot operator:

xml.body.ul.li.findAll {it.@class == 'odd'}*.span.each {println it.text()}
tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • +1 for the spread-dot operator, it solves the specific problem nicely! It doesn't explain the difference of behaviour between the `@class` property and the `span` one though, or am I missing something? – Nicolas Rinaudo Apr 10 '13 at 14:17
  • @NicolasRinaudo Not 100% sure, and delving into the code hasn't helped massively. `.@class` follows [a different path](https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-xml/src/main/java/groovy/util/slurpersupport/GPathResult.java#L124) to just [accessing the property](https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-xml/src/main/java/groovy/util/slurpersupport/GPathResult.java#L136) though... it's as if something is missing from FilteredNodeList... I'll investigate some more when I get time... – tim_yates Apr 10 '13 at 14:35
  • thanks for the time you're sinking into this. I'm reaching the same conclusion myself - [this](https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-xml/src/main/java/groovy/util/slurpersupport/GPathResult.java#L136) looks like it's meant to support the `.span` call, but doesn't seem to work. I'd probably file a bug report if it was a language I felt more confident with, but Groovy has a tendency to not behave the way I expect it to in a perfectly logical and correct fashion. – Nicolas Rinaudo Apr 10 '13 at 14:48
  • 1
    @NicolasRinaudo I think this bug is the same thing, so hopefully it will be fixed soon https://jira.codehaus.org/browse/GROOVY-6122 – tim_yates Apr 26 '13 at 22:39