1

Given the following XML:

<list version="1.0">
    <meta>...</meta>
    <resources start="0" count="167">
        <resource classname="Quote">
            <field name="name">USD/KRW</field>
            <field name="price">1024.400024</field>
            <field name="symbol">KRW=X</field>
        </resource>
        ...
     </resources>
</list>

In order to find the right <resource> and get it's price I do the following:

def slurper = new XmlSlurper()
def result = slurper.parse(XML_URL)
def node = result.depthFirst().find { it.text() == "KRW=X" }
println node.parent().find { it['@name'] == "price" }.text()

However the result is that parent() does not implement find(Closure) which doesn't quite match with the docs: http://groovy.codehaus.org/gapi/groovy/util/slurpersupport/GPathResult.html

More strange node.parent().size() returns 1 when I expect it to return 3 as per the above XML

My questions:

  1. Is my code correct and why is not working?

  2. Is this the shortest way of achieving the expected result?

  3. Why node.parent().size() is returning 1 ? The same goes for node.parent().parent().size(), node.parent().parent().parent().size() and so on...

Saba Ahang
  • 578
  • 9
  • 24

3 Answers3

1

Can you try

def resource = result.'**'.find { 
    it.field.@name == 'symbol' &&
    it.field.text() == 'KRW=X'
}

println resource?.'**'.find {
    it.@name == 'price'
}?.text()
tim_yates
  • 167,322
  • 27
  • 342
  • 338
0

Something quick and dirty, but this should work:

new XmlSlurper().parseText("""
<list version="1.0">
    <meta>...</meta>
    <resources start="0" count="167">
        <resource classname="Quote">
            <field name="name">USD/KRW</field>
            <field name="price">1024.400024</field>
            <field name="symbol">KRW=X</field>
        </resource>

        <resource classname="Quote">
            <field name="name">USD/KRW</field>
            <field name="price">2222</field>
            <field name="symbol">KRW=Y</field>
        </resource>

     </resources>
</list>
""").resources.resource.find{ 
    it.field.find {it.@name == "symbol" && it.text() == "KRW=X"}
}.field.find {it.@name == "price"}.text()
kdabir
  • 9,623
  • 3
  • 43
  • 45
  • this is basically another equivalent of my own solution. The error is `No such property: field for class: groovy.util.slurpersupport.Node` which surprises me because it should be `slurpersupport.NodeChild` – Saba Ahang Jul 23 '14 at 21:25
0

You can use:

def desiredPrice = new XmlSlurper().parse( XML_URL ).'**'.findResult { 
    it.name() == 'field' && it.@name == 'symbol' && it.text() == 'KRW=X' ? 
        it.parent().field.find { it.@name == 'price' }.text() : null
}
dmahapatro
  • 49,365
  • 7
  • 88
  • 117