gpathresult - Groovy XMLSlurper-búsqueda de nodo específico
xml-parsing (2)
Necesito encontrar un nodo específico con XMLSlurper de Groovy. La condición debe ser que el texto / valor de los nodos hijos tenga que coincidir. En el siguiente ejemplo, quiero buscar un nodo de libro donde el año es ''2003'' y el precio es ''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>
Aquí hay otra manera de lograr lo mismo.
Tenga en cuenta que el usuario puede cambiar / agregar fácilmente el adicional and
condiciones fácilmente agregando como se muestra a continuación
def queryData = [[<element>, <operator>, <element value>], [<element>, <operator>, <element value>], ...]
El operador puede ser uno de los siguientes:
-
EQ
para iguales a -
LE
por menos o igual a -
GE
para mayor o igual a -
GT
para mayor que -
LT
por menos de -
NE
para no es igual a
Por ejemplo:
def queryData = [[''year'',''EQ'', ''2003''], [''price'', ''LE'', ''39.95'']]
Básicamente, crea un closure
basado en queryData
y lo pasa a findAll
.
getQuery
cierre de getQuery
construye la consulta a la lista de condiciones anterior como
{ it -> it.year.text() == ''2003'' && it.price.text() <= ''39.95'' }
Sentí que sería más fácil para algunos nuevos que intenten usar Groovy la lista anterior en lugar del cierre, como se explicó anteriormente, que está construida dinámicamente.
Aquí está el guión:
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
Puede probar Demo rápidamente
También tenga en cuenta que actualmente solo hace and
de condiciones, no admite or
.
Dado:
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>''''''
Entonces
new XmlSlurper().parseText(xml).bookstore.book.findAll { it.year == ''2003'' && it.price == ''39.95'' }