Groovy使用带有certian子计数和表达式的gpath查找节点

时间:2016-08-09 10:02:25

标签: groovy xml-parsing xmlslurper gpath

假设我有一个 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>

我希望获得所有level0个节点(使用 GPath ):

  1. 如果level0/@t="0",则仅当所有level1个孩子@status="0"
  2. 时才选择此节点( level0
  3. 如果level0/@t!="0",则仅当最后 level1孩子有@status="0"时才选择此节点( level0 )。我最后说的是level1节点@att1中最大值的@att1节点(假设yyyy-mm-dd包含@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface VersioningProperties { Property[] value(); @interface Property { String version(); String value(); } } 格式的日期)。
  4. 使用 XPath 我会使用max()和count()等函数,但我无法使用 GPath 来了解它。

    谢谢

1 个答案:

答案 0 :(得分:1)

Groovy在Iterable上定义的max()count()函数可以在GPath表达式中使用,代替它们的XPath等价物。

// 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) 
}