且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在XMLSlurper语句中使用变量引用

更新时间:2023-01-19 20:41:00

您需要分割字符串并依次处理每个属性。 ...

试试:

  def root = slurper.Body。 createShipmentResponse 
if(expectedResponse2 in testElement.tokenize('。').inject(root){v,p - >
v?。$ p
}?。collect {it。 text()}){
result =pass
}

使用[] 在groovy中访问对象属性

循环遍历 ['integrationFoo ter','errors','error','errorCode'] ,以 slurper.Body.createShipmentResponse 开头。所以第一次,注入返回 slurper.Body.createShipmentResponse.integrationFooter 。然后它在这个对象上调用 errors ,依此类推,直到获得可以调用 collect 的最终结果为止。
$ b ?。操作符意味着如果它碰到null(并返回null)给定一个这样的对象:

注解:



pre $ def obj = [prop1:[prop2:[prop3:'tim']]]

我们可以调用:

$ p $ assert obj.prop1.prop2.prop3 =='tim'

但是,如果我们将属性名称读为String:

  def props ='prop1.prop2.prop3'

然后这不起作用(因为没有关键'prop1.prop2.prop3'

  assert obj。$ props=='tim'// FAILS! 

但是我们可以在完整版中拆分 props 停止获取属性列表:

  def pList = props.tokenize('。')
assert pList = = ['prop1','prop2','prop3']

然后,我们可以通过这个列表,以 obj 开始:

  def result = pList.inject obj){currentObject,property  - > 
//从currentObject返回属性(如果currentObject为null,则返回null)
currentObject?。$ property
}
$因此,对于 pList 中的每个元素,我们都这样做:


 第1步:
currentObject == obj
属性=='prop1'
返回obj.prop1 - [prop2:[prop3:'tim ']]

第2步:
currentObject == [prop2:[prop3:'tim']]
属性=='prop2'
返回currentObj.prop2 - - [prop3:'tim']

Step3(最后一步,因为pList现在已经结束了):
currentObject == [prop3:'tim']
property == 'prop3'
返回currentObj.prop3 - 'tim'

所以最终的结果是'tim'



希望这可以解释它: - )


I am using a groovy with XMLSlurper to validate my web service responses in soap ui pro.

I have the following code which works (expectedResponse is var that stores expected errorcode e.g. E0023) ...

if(expectedResponse2 in slurper.Body.createShipmentResponse.integrationFooter.errors.error.errorCode.collect{it.text()})
{
        result = "pass" 
}

But I would like to replace the 'integrationFooter.errors.error.errorCode' with a reference to a variable that I could supply from a SoapUI Pro datasource, because I am not always validating on the same response element. i.e if I am expecting the test to pass I might want to check that the status element is populated with 'Allocated'. If I am expecting the request to fail I want to validate that the errorCode field is populated with the correct errorCode e.g. 'E0023'.

If I have a variable called testElement in my groovyscript and I assign it the path of the element e.g. integrationFooter.errors.error.errorCode how do I refer to the variable within my XMLSlurper statement?

I tried the below code but it didn't work..

if(expectedResponse2 in slurper.Body.createShipmentResponse."${testElement}".collect{it.text()})

You need to split the string and handle each property in turn yourself...

Try:

def root = slurper.Body.createShipmentResponse
if(expectedResponse2 in testElement.tokenize( '.' ).inject( root ) { v, p ->
                            v?."$p"
                        }?.collect{ it.text() } ) {
    result = "pass" 
}

See Access object properties in groovy using []

That loops over the list [ 'integrationFooter', 'errors', 'error', 'errorCode' ], starting with slurper.Body.createShipmentResponse. So first time round, the inject returns slurper.Body.createShipmentResponse.integrationFooter. Then it calls errors on this object, and so on until it gets the final result which you can call collect on.

The ?. operator just means it will keep going if it hits a null (and return null)

Inject explanation:

Given an object like this:

def obj = [ prop1:[ prop2:[ prop3: 'tim' ] ] ]

We can call:

assert obj.prop1.prop2.prop3 == 'tim'

However, if we were given the property name to read as a String:

def props = 'prop1.prop2.prop3'

Then this won't work (as there's no key 'prop1.prop2.prop3')

assert obj."$props" == 'tim'  // FAILS!

But we can split props on the full stop to get a list of properties:

def pList = props.tokenize( '.' )
assert pList == [ 'prop1', 'prop2', 'prop3' ]

Then, we can work through this list, starting with obj:

def result = pList.inject( obj ) { currentObject, property ->
    // Return the property from the currentObject (or null if currentObject is null)
    currentObject?."$property"
}

So for each element of pList, we do:

Step1:
    currentObject == obj
    property   == 'prop1'
    returns obj.prop1 -- [ prop2:[ prop3: 'tim' ] ]

Step2:
    currentObject == [ prop2:[ prop3: 'tim' ] ]
    property   == 'prop2'
    returns currentObj.prop2 -- [ prop3: 'tim' ]

Step3 (final step as pList is at an end now):
    currentObject == [ prop3: 'tim' ]
    property   == 'prop3'
    returns currentObj.prop3 -- 'tim'

So the final result is 'tim'

Hope this explains it :-)