0

I am trying to get values from a web service response in readyAPI, so i can pass it to another web service request, so i can create a automated test flow.

I have tried different code pieces most of them was a single line of code, which i prefer if it possible. I can take value from a node by typing the parent node by its attribute value. I also can get parent node by child nodes attribute value and use it to get another child value.

Here some examples:

First Format that I can use it to get childs value:

<webserviceResponse>
<documentslist>
<document @id="1">
        <payment @currency="USD" >
        <amount>1250.00</amount>
        </payment>
</document>
<document @id="2">
        <payment @currency="JPY" >
        <amount>150.00</amount>
        </payment>
</document>
<document @id="3">
        <payment @currency="EUR" >
        <amount>1170.00</amount>
        </payment>
</document>
<!-- etc. -->
</documentslist>

-----> To get currency for a specific document

def webServiceResponse = "webservice#Response"
int index=2
def currency = context.expand('${'+webServiceResponse+'//*:document[@id="['+index+']"]//*:payment/@currency}')

-----> Result of this is "JPY"


<webserviceResponse>
<documentslist>
<document @id="1">
        <payment @currency="USD" >
        <amount>1250.00</amount>
        </payment>
        <refund>true</refund>
</document>
<document @id="2">
        <payment @currency="JPY" >
        <amount>150.00</amount>
        </payment>
</document>
<document @id="3">
        <payment @currency="EUR" >
        <amount>1170.00</amount>
        </payment>
        <refund>false</refund>
</document>
<!-- etc. -->
</documentslist>

-------> To get a currency dependent on existence of a specific node In this example we are looking the file from up to down and we are finding every refund nodes, and taking currency value that is in the same block with the second time we see a refund node.

def webServiceResponse = "webservice#Response"
int index=2
def currrency= context.expand('${'+webServiceResponse+'(//*:refund)['+index+']//parent::*//*:payment/@currency}')

--------> Result for this is "EUR"


This one is that i cant take child value with the same way.

<webserviceResponse>
<documentslist>
<document>
    <key>D_Computer</key>
    <currency>USD</currency>
    <amount>1250.00</amount>
    <refund>true</refund>
</document>
<document>
    <key>D_Keyboard</key>
    <currency>JPY</currency>
    <amount>150.00</amount>
</document>
<document>
    <key>D_Monitor</key>
    <currency>EUR</currency>
    <amount>1170.00</amount>
    <refund>false</refund>
</document>
<!-- etc. -->
</documentslist>

My problem with this one it doesn't have any attributes, has only values of the nodes. I know that it doesnt have an integer by the way but maybe i am doing wrong that i dont realize.

I want to get the amount value only dependent to the "key" nodes value which i am going to specify in the script.

result should show :150.00

2 Answers2

0

Thank you for the very detailed and well written question.

You can use the below. Your problem is easy as there are no namespace in it.

Technique is same which you have dispalyed, its just that you need not to use @ as its for attributes

def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def xml=groovyUtils.getXmlHolder("NameOfRequest#Response");
def currency=xml.getNodeValue("//*:documentslist/*:document[key='${key}']/*:amount");
log.info "Value of $key  is " + currency

key="D_Monitor"
currency=xml.getNodeValue("//*:documentslist/*:document[key='${key}']/*:amount");
log.info "Value of $key  is " + currency

Replace NameOfRequest with your Request's name

enter image description here

There is an alternative way too. I will post it as a separate answer so not to cause confusion. This one is still better than other one

Gaurav Khurana
  • 3,423
  • 2
  • 29
  • 38
  • 1
    Thank you for your answer. I couldn't manage to implement your code directly to mine but it helped me find the solution. Maybe Groovy doesn't work this way, i don't know. – Muhammet Aytekin Feb 01 '19 at 10:31
  • 1
    First i defined a property named key then used that property to get the amount value. I used a code piece like this one : currency=xml.getNodeValue("//*:documentslist/*:document[key="${#TestCase#key}"]/*:amount") Second way to do this was giving the value directly inside the xpath like this: currency=xml.getNodeValue("//*:documentslist/*:document[key="D_Monitor"]/*:amount") – Muhammet Aytekin Feb 01 '19 at 11:02
  • Let me know the line of code which is not working for you. I will check that out. Also you can see the other answer i posted and can upvote if that helps too – Gaurav Khurana Feb 04 '19 at 02:50
0

There is an alternate way of doing things using Hashmap if the other answer is not working due to namespaces in your XML

Try this method

We are getting all values first by using getNodeValues and then since we have pair we are putting in hashmap.

Now you can retrieve anything.

def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def xml=groovyUtils.getXmlHolder("Request1#Response");

def keys=xml.getNodeValues("//*:documentslist/*:document/*:key")
def amounts=xml.getNodeValues("//*:documentslist/*:document/*:amount")

log.info keys.toString()
log.info amounts.toString()

HashMap h1=[:]
// Add the pair into hashmap and then retrieve
for(int i=0;i<keys.size();i++)
{
    h1.put(keys[i],amounts[i])
}
def whichone="D_Computer"
log.info "Value for $whichone is " + h1.get(whichone)

enter image description here

Lets say you want to retrieve more than one value then you can use arrays. i.e. take arrays as key,currency,amount,refund

so if you want to retrieve the refund for a key='Z' So using a for loop you can know that Z is present at 3 location in the array

then your refund should be refund[3]. Similarly currency[3] and amount[3]

Both the answers have their own relevance

Gaurav Khurana
  • 3,423
  • 2
  • 29
  • 38