Groovy XMLSlurper - 搜索特定节点
Groovy XMLSlurper - searching sepecific node
我需要使用 Groovy 的 XMLSlurper 查找特定节点。条件应该是子节点的 text/value 必须匹配。在下面的示例中,我想搜索年份为“2003”且价格为“39.95”的图书节点。
<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>
鉴于:
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' }
这是实现相同目的的另一种方法。
请注意,用户可以通过添加如下所示轻松更改/添加其他 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']]
基本上它会根据 queryData
创建一个 closure
并将其传递给 findAll
。
getQuery
closure 构建对上述条件列表的查询
{ it -> it.year.text() == '2003' && it.price.text() <= '39.95' }
我觉得对于一些尝试 groovy 的新手来说,使用上面的列表而不是上面动态构建的闭包会更容易。
脚本如下:
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
.
我需要使用 Groovy 的 XMLSlurper 查找特定节点。条件应该是子节点的 text/value 必须匹配。在下面的示例中,我想搜索年份为“2003”且价格为“39.95”的图书节点。
<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>
鉴于:
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' }
这是实现相同目的的另一种方法。
请注意,用户可以通过添加如下所示轻松更改/添加其他 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']]
基本上它会根据 queryData
创建一个 closure
并将其传递给 findAll
。
getQuery
closure 构建对上述条件列表的查询
{ it -> it.year.text() == '2003' && it.price.text() <= '39.95' }
我觉得对于一些尝试 groovy 的新手来说,使用上面的列表而不是上面动态构建的闭包会更容易。
脚本如下:
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
.