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 兄弟姐妹):

  1. 对于每个 level0 找到具有最大 att1 值的所有 'level1' 个节点(在 yyyy-mm-dd 中解释为 Date
  2. 在那些 level1 个节点中找到一个在年和月属性中具有最大值的节点,解释为 ints。

对于给定的示例,我希望找到具有 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 的评论。但是,我假设您要按 att1yearmonth 对数据进行排序,然后找到最大值。

为了以 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