Groovy GPath 根据多种条件查找节点
Groovy GPath find nodes by many conditions
假设有 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>
我必须根据条件找到 level1
节点(假设我们可以有很多 level0
兄弟姐妹):
- 对于每个
level0
找到具有最大 att1
值的所有 'level1' 个节点(在 yyyy-mm-dd 中解释为 Date
)
- 在那些
level1
个节点中找到一个在年和月属性中具有最大值的节点,解释为 int
s。
对于给定的示例,我希望找到具有 val
="113" 值的节点。
由于我不是 GPath 方面的专家,请帮助找到正确的 Groovish 解决方案。谢谢。
目前我已经找到了这个解决方案,我想知道是否有更多Groovish
的方法来做到这一点。
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',lev1.@att1.toString())
}
}
.each {level1 ->
level1.max { lev1 ->
lev1.@year.toString() as int
}
}.max {level1 ->
level1.@month.toString() as int
}.collect()
println "${nodes.count {it}}"
nodes.each { n ->
println "val = ${n.@val}"
}
预期的行为有点不清楚,请参阅我对 post 的评论。但是,我假设您要按 att1
、year
、month
对数据进行排序,然后找到最大值。
为了以 Groovy 的方式做到这一点,我将提取一些辅助方法,以便您了解发生了什么:
def date = { Date.parse('yyyy-MM-dd', it.@att1.toString()) }
def year = { it.@year.toString() }
def month = { it.@month.toString() }
然后可以对节点进行排序,使用"space-ship"运算符<=>
进行比较,使用"elvis"运算符?:
进行下一级比较,如果首先 returns 0(当比较相等时发生):
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
假设有 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>
我必须根据条件找到 level1
节点(假设我们可以有很多 level0
兄弟姐妹):
- 对于每个
level0
找到具有最大att1
值的所有 'level1' 个节点(在 yyyy-mm-dd 中解释为Date
) - 在那些
level1
个节点中找到一个在年和月属性中具有最大值的节点,解释为int
s。
对于给定的示例,我希望找到具有 val
="113" 值的节点。
由于我不是 GPath 方面的专家,请帮助找到正确的 Groovish 解决方案。谢谢。
目前我已经找到了这个解决方案,我想知道是否有更多Groovish
的方法来做到这一点。
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',lev1.@att1.toString())
}
}
.each {level1 ->
level1.max { lev1 ->
lev1.@year.toString() as int
}
}.max {level1 ->
level1.@month.toString() as int
}.collect()
println "${nodes.count {it}}"
nodes.each { n ->
println "val = ${n.@val}"
}
预期的行为有点不清楚,请参阅我对 post 的评论。但是,我假设您要按 att1
、year
、month
对数据进行排序,然后找到最大值。
为了以 Groovy 的方式做到这一点,我将提取一些辅助方法,以便您了解发生了什么:
def date = { Date.parse('yyyy-MM-dd', it.@att1.toString()) }
def year = { it.@year.toString() }
def month = { it.@month.toString() }
然后可以对节点进行排序,使用"space-ship"运算符<=>
进行比较,使用"elvis"运算符?:
进行下一级比较,如果首先 returns 0(当比较相等时发生):
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