2017-02-14 80 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