Suppose I have an XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<level0 id="1" t="0">
<level1 id="lev1id01" att1="2015-05-12" val="12" status="0"/>
<level1 id="lev1id02" att1="2015-06-13" val="13" status="0"/>
<level1 id="lev1id03" att1="2015-07-10" val="13" status="0"/>
</level0>
<level0 id="2" t="0">
<level1 id="lev1id11" att1="2015-05-12" val="121" status="0"/>
<level1 id="lev1id12" att1="2015-06-13" val="132" status="0"/>
<level1 id="lev1id13" att1="2015-07-11" val="113" status="0"/>
</level0>
<level0 id="2" t="1">
<level1 id="lev1id21" att1="2015-05-12" val="121" status="0"/>
<level1 id="lev1id22" att1="2015-06-13" val="132" status="0"/>
<level1 id="lev1id23" att1="2015-07-11" val="113" status="0"/>
<level1 id="lev1id23" att1="2015-07-11" val="113" status="0"/>
</level0>
</data>
I want to get all level0
nodes (using GPath) which are:
level0/@t="0"
then select this node (level0) only if all its level1
children has @status="0"
level0/@t!="0"
then select this node (level0) only if the last level1
child has @status="0"
. When I say last I mean the level1
node with maximum value in @att1
(assuming @att1
contains date in yyyy-mm-dd
format).With XPath I would use functions like max() and count(), but I can't get how it could be done using GPath.
Thanks
The max()
and count()
functions defined by Groovy on Iterable
can be used within GPath expressions in place of their XPath equivalents.
// This closure is for level0[t=0] elements.
// It selects the level0 if the count of its level1[status=0] children is 0.
def t0Select = { level0 ->
level0.level1.count { level1 -> level1.@status != '0' } == 0
}
// This closure is for level1[t=1] elements.
// It selects the level0 if its level1 element with the maximum date has a status of "0"
def t1Select = { level0 ->
level0.level1.max { level1 -> Date.parse('yyyy-MM-dd', level1.@att1.toString()) }?.@status == '0'
}
// Parse the XML and delegate to the appropriate closure above as per the t attribute
def selected = new XmlSlurper().parseText(xml).level0.findAll { level0 ->
level0.@t == '0' ? t0Select(level0) : t1Select(level0)
}