0

I am working on a groovy script in which I have to take values from request XML file and write those into XML response file.

I know how to read values from normal XML as given below:

def text = '''
<list>
    <technology>
        <name>Groovy</name>
    </technology>
</list>
'''

def list = new XmlParser().parseText(text) 
println list.technology.name.text()

I can easily access nodes using above syntax. But in my case the request file have 'keyword:label' syntax. Consider below mentioned request file for currency converter:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
  <web:ConversionRate>
     <web:FromCurrency>USD</web:FromCurrency>
     <web:ToCurrency>INR</web:ToCurrency>
  </web:ConversionRate>
</soap:Body>
</soap:Envelope>

How to read value of FromCurrency in this case? Instead of using XMLParser, is there any other efficient and good way to handle larger XML files?

Also, while writing values in the response I am writing by creating multiple variables in script and using their values in response using syntax "${var_name}.

If I want to write many values (suppose 20+) from request into response, then variable for individual writing is not good way. So is there any good and efficient way for this?

jalopaba
  • 8,039
  • 2
  • 44
  • 57
Madhusudan
  • 4,637
  • 12
  • 55
  • 86

3 Answers3

3

You can get FromCurrency like so (using XmlSlurper):

def text = '''<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
  <web:ConversionRate>
     <web:FromCurrency>USD</web:FromCurrency>
     <web:ToCurrency>INR</web:ToCurrency>
  </web:ConversionRate>
</soap:Body>
</soap:Envelope>'''

def list = new XmlSlurper().parseText(text) 
println list.Body.ConversionRate.FromCurrency.text()

Not sure I understand the rest of your question

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • how can I do the same using XMLParser? – Madhusudan Oct 29 '15 at 11:15
  • Just posted an answer with XmlParser example, but I agree with @tim_yates: What's wrong with XmlSlurper? – jalopaba Oct 29 '15 at 11:41
  • I arrive late to the party... however I also post as @jalopaba a example using XMLParser and add specific info for soapui case. Of course I'm totally agree with tim_yates about use xmlSlurper for this. – albciff Oct 29 '15 at 11:43
  • @tim_yates Thanks for response :). Actually I am trying to copy values from SOAP request into response. So suppose I want to copy value of 'FromCurrency' then how I will take it from request context for above xml syntax? – Madhusudan Oct 29 '15 at 14:54
  • I have no idea what that means... Is this a SoapUI thing? – tim_yates Oct 29 '15 at 15:08
1

With XmlParseryou have to explicitly use namespaces, within a string or declaring them:

import groovy.xml.*

def text = '''<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
  <web:ConversionRate>
     <web:FromCurrency>USD</web:FromCurrency>
     <web:ToCurrency>INR</web:ToCurrency>
  </web:ConversionRate>
</soap:Body>
</soap:Envelope>'''

def s = new Namespace('http://www.w3.org/2003/05/soap-envelope', 'soap')
def w = new Namespace('http://www.webserviceX.NET/', 'web')
def parsed = new XmlParser().parseText(text) 

assert 'USD' == parsed.'soap:Body'.'web:ConversionRate'.'web:FromCurrency'.text()
assert '' == parsed.Body.ConversionRate.FromCurrency.text()
assert 'USD' == parsed[s.Body][w.ConversionRate][w.FromCurrency].text()

Whereas with XmlSlurper namespaces are ignored if not declared:

def slurped = new XmlSlurper().parseText(text)
assert 'USD' == slurped.Body.ConversionRate.FromCurrency.text()
assert '' == slurped.'soap:Body'.'web:ConversionRate'.'web:FromCurrency'.text()

slurped = new XmlSlurper().parseText(text).declareNamespace([soap: 'http://www.w3.org/2003/05/soap-envelope', web: 'http://www.webserviceX.NET/'])
assert 'USD' == slurped.Body.ConversionRate.FromCurrency.text()
assert 'USD' == slurped.'soap:Body'.'web:ConversionRate'.'web:FromCurrency'.text()
jalopaba
  • 8,039
  • 2
  • 44
  • 57
1

To do so using XMLParser instead of XmlSlurper (by the way I prefer to use slurper):

def text = '''<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
  <web:ConversionRate>
     <web:FromCurrency>USD</web:FromCurrency>
     <web:ToCurrency>INR</web:ToCurrency>
  </web:ConversionRate>
</soap:Body>
</soap:Envelope>'''

def list = new XmlParser().parseText(text) 
log.info list.'soap:Body'.'web:ConversionRate'.'web:FromCurrency'.text() // prints Thu Oct 29 12:27:31 CET 2015:INFO:USD

Then instead to add multiple properties in the request and setting one by one in your script, if you want an alternative way you can construct your complete xml and set the request property of your testStep directly using the follow approach:

def text = '''<myNewRequest><someField1/><someField2/></myNewRequest>'''
def request = new XmlParser(true,true).parseText(text) 
request.someField1[0].setValue('my new value')
request.someField2[0].setValue('another value')

// converts the xml to string
StringWriter sw = new StringWriter()
new XmlNodePrinter(new PrintWriter(sw)).print(request)
def modifiedRequest = sw.toString()
// get the testStep and set the request
context.testCase.getTestStepByName('SOAP Request').setPropertyValue('request',modifiedRequest)

Hope it helps,

albciff
  • 18,112
  • 4
  • 64
  • 89