Reputation: 1986
Suppose having XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<level0 id="2" t="1">
<level1 id="lev1id21" att1="2015-05-12" val="121" status="0" year="2015" month="05" />
<level1 id="lev1id22" att1="2015-06-13" val="132" status="0" year="2015" month="06" />
<level1 id="lev1id23" att1="2015-07-11" val="113" status="0" year="2015" month="08" />
<level1 id="lev1id23" att1="2015-07-11" val="114" status="0" year="2015" month="07" />
</level0>
</data>
I have to find level1
node by conditions (assuming we could have many level0
siblings):
level0
find all 'level1' nodes which have maximal att1
value (interpreted as Date
in yyyy-mm-dd)level1
nodes find one that has maximal value in year and month attributes, interpreted as int
s.For given example, I expect node with val
="113" value to be found.
Since I'm not an expert in GPath, please help to find a correct and Groovish solution. Thanks.
Upvotes: 2
Views: 1372
Reputation: 1312
The expected behavior is a bit unclear, see my comment on the post. However, I'm working off the assumption you want to sort the data by att1
, then by year
, then by month
, and find the max value.
To do it in a Groovy way, I'd extract some helper methods so you can see what is going on:
def date = { Date.parse('yyyy-MM-dd', [email protected]()) }
def year = { [email protected]() }
def month = { [email protected]() }
Then you can sort the nodes using the "space-ship" operator <=>
to do comparison, and using the "elvis" operator ?:
to do the next level comparison if the first returns 0 (which happens when the comparison is equal):
def nodes = new XmlSlurper().parseText(xml).level0.level1
def max = nodes.sort { a, b ->
date(a) <=> date(b) ?:
year(a) <=> year(b) ?:
month(a) <=> month(b)
} .collect { it.@val } .last()
println max
// Prints "113", given your data above
Upvotes: 3
Reputation: 1986
For now I've found this solution, I'd like to know if there is a more Groovish
way to do this.
def xml='''<?xml version="1.0" encoding="UTF-8"?>
<data>
<level0 id="2" t="1">
<level1 id="lev1id21" att1="2015-05-12" val="121" status="0" year="2015" month="05" />
<level1 id="lev1id22" att1="2015-06-13" val="132" status="0" year="2015" month="06" />
<level1 id="lev1id23" att1="2015-07-11" val="113" status="0" year="2015" month="08" />
<level1 id="lev1id23" att1="2015-07-11" val="114" status="0" year="2015" month="07" />
</level0>
</data>'''
def nodes = new XmlSlurper().parseText(xml).level0.level1.findAll {level1 ->
level1.max {lev1->
Date.parse('yyyy-MM-dd',[email protected]())
}
}
.each {level1 ->
level1.max { lev1 ->
[email protected]() as int
}
}.max {level1 ->
[email protected]() as int
}.collect()
println "${nodes.count {it}}"
nodes.each { n ->
println "val = ${n.@val}"
}
Upvotes: 1