使用动态 GPath 表达式按属性值查找 XML 元素
Find XML Element by attribute value using dynamic GPath Expression
以下是示例 XML:
<root>
<persons>
<person gender="female">X</person>
<person gender="female">Y</person>
<person gender="male">Z</person>
</persons>
</root>
我想使用 GPath 获取具有 gender="male"
的元素数。
我有以下代码:
def xml =
'''
<root>
<persons>
<person gender="female">X</person>
<person gender="female">Y</person>
<person gender="male">Z</person>
</persons>
</root>
'''
def slurper = new XmlSlurper()
def parsedText = slurper.parseText(xml)
def locator = 'persons.person[@gender="male"]'
def elements = Eval.x(parsedText, "x.${locator}")
println elements.size()
它给我错误:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script1.groovy: 1: unexpected token: = @ line 1, column 25.
x.persons.person[@gender="male"]
^
1 error
该代码仅用于演示问题。在实际情况下,我有一个实用程序方法,它接受一个 XML 和一个 GPath 和 returns 如果给定的 GPath 可以找到任何元素。
更新:1
以下是实际的实用方法,它以 xml 和定位器 (GPath) 作为参数,并检查是否有任何元素的路径与提供的定位器匹配。
public static void verifyElementExists(String xml, String locator) throws NoElementFoundException {
def slurper = new XmlSlurper()
def parsedText = slurper.parseText(xml)
def elements = Eval.x(parsedText, "x.${locator}")
if(elements.size() == 0) {
throw new NoElementFoundException()
}
}
认为你需要
def locator = "persons.person.findAll { it.@gender == 'male' }"
我会尽可能避免这种情况,使用 Eval
不是安全的步行路径
不确定您要实现的确切用例。
如果您需要一种方法可以 return 如果某些元素或提供的 GPath
可用或不可用,则可以通过以下方式实现:
虽然解决方案确实没有太大变化。
而不是字符串作为定位器,用户需要传递与Closure
相同的东西并且它不使用Eval
。
//Method to find if element exists.
static def isElementExists (String xmlStr, Closure closure){
def xml = new XmlSlurper().parseText(xmlStr)
def elements = closure(xml)
elements.size() ? true : false
}
def xmlString = '''<root>
<persons>
<person gender="female">X</person>
<person gender="female">Y</person>
<person gender="male">Z</person>
</persons>
</root>'''
//Call to the above method, use either of the way to make a call; both are same
//In the below example, the same string used as locator is being passed as Closre
println isElementExists(xmlString) {x -> x.'**'.findAll { it.name()=='person' && it.@gender == 'male' } }
或
println isElementExists(xmlString, {x -> x.'**'.findAll { it.name()=='person' && it.@gender == 'male' } } )
如果你只想检查 person
元素是否存在,那么你可以按如下方式使用它:
println isElementExists(xmlString) {x -> x.persons.person }
您可以快速在线试用demo
编辑:提高可读性或简化。
您甚至可以按照以下方式进行操作。当然,最后一条语句和下面语句的结果是一样的。
def locator = {x -> x.persons.person }
println isElementExists(xmlString, locator)
以下是示例 XML:
<root>
<persons>
<person gender="female">X</person>
<person gender="female">Y</person>
<person gender="male">Z</person>
</persons>
</root>
我想使用 GPath 获取具有 gender="male"
的元素数。
我有以下代码:
def xml =
'''
<root>
<persons>
<person gender="female">X</person>
<person gender="female">Y</person>
<person gender="male">Z</person>
</persons>
</root>
'''
def slurper = new XmlSlurper()
def parsedText = slurper.parseText(xml)
def locator = 'persons.person[@gender="male"]'
def elements = Eval.x(parsedText, "x.${locator}")
println elements.size()
它给我错误:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script1.groovy: 1: unexpected token: = @ line 1, column 25.
x.persons.person[@gender="male"]
^
1 error
该代码仅用于演示问题。在实际情况下,我有一个实用程序方法,它接受一个 XML 和一个 GPath 和 returns 如果给定的 GPath 可以找到任何元素。
更新:1
以下是实际的实用方法,它以 xml 和定位器 (GPath) 作为参数,并检查是否有任何元素的路径与提供的定位器匹配。
public static void verifyElementExists(String xml, String locator) throws NoElementFoundException {
def slurper = new XmlSlurper()
def parsedText = slurper.parseText(xml)
def elements = Eval.x(parsedText, "x.${locator}")
if(elements.size() == 0) {
throw new NoElementFoundException()
}
}
认为你需要
def locator = "persons.person.findAll { it.@gender == 'male' }"
我会尽可能避免这种情况,使用 Eval
不是安全的步行路径
不确定您要实现的确切用例。
如果您需要一种方法可以 return 如果某些元素或提供的 GPath
可用或不可用,则可以通过以下方式实现:
虽然解决方案确实没有太大变化。
而不是字符串作为定位器,用户需要传递与Closure
相同的东西并且它不使用Eval
。
//Method to find if element exists.
static def isElementExists (String xmlStr, Closure closure){
def xml = new XmlSlurper().parseText(xmlStr)
def elements = closure(xml)
elements.size() ? true : false
}
def xmlString = '''<root>
<persons>
<person gender="female">X</person>
<person gender="female">Y</person>
<person gender="male">Z</person>
</persons>
</root>'''
//Call to the above method, use either of the way to make a call; both are same
//In the below example, the same string used as locator is being passed as Closre
println isElementExists(xmlString) {x -> x.'**'.findAll { it.name()=='person' && it.@gender == 'male' } }
或
println isElementExists(xmlString, {x -> x.'**'.findAll { it.name()=='person' && it.@gender == 'male' } } )
如果你只想检查 person
元素是否存在,那么你可以按如下方式使用它:
println isElementExists(xmlString) {x -> x.persons.person }
您可以快速在线试用demo
编辑:提高可读性或简化。
您甚至可以按照以下方式进行操作。当然,最后一条语句和下面语句的结果是一样的。
def locator = {x -> x.persons.person }
println isElementExists(xmlString, locator)