2017-02-14 132 views
1

我需要使用Groovy的XMLSlurper查找特定节点。条件应该是子节点的文本/值必须匹配。在下面的示例中,我想要搜索年份为'2003'且价格为'39.95'的图书节点。Groovy XMLSlurper - 搜索特定节点

<bookstore name="Store A"> 
    <employee> 
     <id>546343</id> 
     <name>Dustin Brown</name> 
    </employee> 
    <employee> 
     <id>547547</id> 
     <name>Lisa Danton</name> 
    </employee> 
    <book category="cooking"> 
    <title lang="en">Everyday Italian</title> 
    <author>Giada De Laurentiis</author> 
    <year>2005</year> 
    <price>30.00</price> 
    </book> 
    <book category="children"> 
    <title lang="en">Harry Potter</title> 
    <author>J K. Rowling</author> 
    <year>2005</year> 
    <price>29.99</price> 
    </book> 
    <book category="web"> 
    <title lang="en">Learning XML</title> 
    <author>Erik T. Ray</author> 
    <year>2003</year> 
    <price>39.95</price> 
    </book> 
</bookstore> 
<bookstore name="Store B"> 
... 
</bookstore> 

回答

2

考虑:

def xml = '''<stores> 
    <bookstore name="Store A"> 
     <employee> 
      <id>546343</id> 
      <name>Dustin Brown</name> 
     </employee> 
     <employee> 
      <id>547547</id> 
      <name>Lisa Danton</name> 
     </employee> 
     <book category="cooking"> 
     <title lang="en">Everyday Italian</title> 
     <author>Giada De Laurentiis</author> 
     <year>2005</year> 
     <price>30.00</price> 
     </book> 
     <book category="children"> 
     <title lang="en">Harry Potter</title> 
     <author>J K. Rowling</author> 
     <year>2005</year> 
     <price>29.99</price> 
     </book> 
     <book category="web"> 
     <title lang="en">Learning XML</title> 
     <author>Erik T. Ray</author> 
     <year>2003</year> 
     <price>39.95</price> 
     </book> 
    </bookstore> 
    <bookstore name="Store B"> 
    </bookstore> 
</stores>''' 

然后

new XmlSlurper().parseText(xml).bookstore.book.findAll { it.year == '2003' && it.price == '39.95' } 
0

这里是另一种方式来达到同样的。

注意,如下所示

def queryData = [[<element>, <operator>, <element value>], [<element>, <operator>, <element value>], ...] 

操作员可以是一种下面的用户可以容易地改变/添加附加and条件(一个或多个)容易通过添加:

  • EQ为等于
  • LE小于或等于
  • GE大于或等于到
  • GT为大于
  • LT为小于
  • NE不等于

例如:

def queryData = [['year','EQ', '2003'], ['price', 'LE', '39.95']] 

基本上它创建一个基于queryData和通一个closure它到findAll

getQuery关闭建立查询到的条件上述列表作为

{ it -> it.year.text() == '2003' && it.price.text() <= '39.95' } 

我觉得它会更容易一些新的人试图常规使用上面所列内容的,而不是封闭物,以上这是建动态。

下面是脚本:

​def xml = """<stores> <bookstore name="Store A"> 
     <employee> 
      <id>546343</id> 
      <name>Dustin Brown</name> 
     </employee> 
     <employee> 
      <id>547547</id> 
      <name>Lisa Danton</name> 
     </employee> 
     <book category="cooking"> 
     <title lang="en">Everyday Italian</title> 
     <author>Giada De Laurentiis</author> 
     <year>2005</year> 
     <price>30.00</price> 
     </book> 
     <book category="children"> 
     <title lang="en">Harry Potter</title> 
     <author>J K. Rowling</author> 
     <year>2005</year> 
     <price>29.99</price> 
     </book> 
     <book category="web"> 
     <title lang="en">Learning XML</title> 
     <author>Erik T. Ray</author> 
     <year>2003</year> 
     <price>39.95</price> 
     </book> 
    </bookstore> 
    <bookstore name="Store B"> 
    </bookstore> 
</stores>""" 

//You may just add additional conditions into below list 
def queryData = [['year','EQ', '2003'], ['price', 'LE', '39.95']] 

enum Operator { 
    EQ('=='), LE('<='), GE('>='), GT('>'), LT('<'), NE('!=') 
    def value 
    Operator(String value){ 
    this.value = value 
    } 

    def getValue(){ 
    value 
    } 
} 

def getQuery = { list -> 
    def sb = new StringBuffer('{ it -> ') 
    list.eachWithIndex { sublist, index -> 
    index == 0 ?: sb.append(' && ') 
    Operator operator = sublist[1] 
    sb.append("it.${sublist[0]}.text() ${operator.value} '${sublist[2]}'") 
    } 
    def query = sb.append(' }').toString() 
    println "Query formed is : ${query}" 
    def sh = new GroovyShell() 
    sh.evaluate(query) 
} 

def getBooks = { stores, closure -> 
    stores.'**'.findAll { closure(it) } ?: 'Could not find matching book' 
} 

def stores = new XmlSlurper().parseText(xml) 

def result = getBooks(stores, getQuery(queryData)) 
println result 

你可以快速尝试Demo

还要注意,目前仅and的条件呢,不支持or