2017-02-14 9 views
1

Мне нужно найти определенный узел с XMLSlurper от Groovy. Условие должно состоять в том, чтобы текст/значение дочерних узлов совпадали. В следующем примере я хочу найти книжный узел, где год «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

Вот еще один способ добиться того же.

Обратите внимание, что пользователь может легко изменить/добавить дополнительный and условие (ы) легко путем добавления, как показано ниже

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

Оператор может быть одним ниже:

  • EQ для равняется
  • LE по меньшей мере или равно
  • GE больше или равно к
  • GT для более
  • LT для менее
  • NE для не равна

Например:

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

В основном это создает closure на основе queryData и проход до 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.

Смежные вопросы