0

I am working on SoapUI where I have a Soap request which takes input in Json String format and after the processing I get a Soap Response in XML with JSON format enclosed in CDATA.

I am trying to extract the data from Soap Response using the below code but I get error "Content is not allowed in prolog"

import com.eviware.soapui.support.XmlHolder
import net.sf.json.groovy.JsonSlurper
import groovy.xml.Namespace

respXmlHolder = new XmlHolder(messageExchange.getResponseContentAsXml())
respXmlHolder.declareNamespace("ns1","http://tempuri.org/")
CDATAXml = respXmlHolder.getNodeValue("//ns1:ReportResult")
log.info(CDATAXml)


def data = new XmlParser().parseText(CDATAXml).Rpt
log info "data.findAll{it.'Name'}.size()"

The Soap Response looks this way as shown below:

<ReportResponse xmlns="http://tempuri.org/">
     <ReportResult><![CDATA[{
  "Report": [
    {
      "Name": "ABC",
      "Number": "123",
      "Type": "XYZ",
      "Desc": "EFGH",
      "Group Name": "Name123",
      "Group Number": "123",
      "End Date": "12/30/2014",
      "Due Date": "04/15/2015",
      "Completion Date": null,
      "Status": "Status1",
      "Received Date": "",
      "Delivery Date": "",
      "Location": "",
      "Role": "",
     },
     {
      "Name": "EFG",
       "Number": "123",
      "Type": "XYZ",
      "Desc": "EFGH",
      "Group Name": "Name123",
      "Group Number": "123",
      "End Date": "12/30/2014",
      "Due Date": "04/15/2015",
      "Completion Date": null,
      "Status": "Status1",
      "Received Date": "",
      "Delivery Date": "",
      "Location": "",
      "Role": "Manager",
     }
    ]
} ]]></ReportResult>
  </ReportResponse>
   </s:Body>
</s:Envelope>

Please help me in this regard.

SDhwaj
  • 1
  • 1
  • 4
  • 1
    You are trying to get `Result` using xpath, but where is it in the xml? You can see [this](http://stackoverflow.com/questions/36716317/script-assertion-for-json-response/36717797#36717797) similar example to extract json. – Rao Apr 27 '16 at 07:49
  • The example you mentioned has data not enclosed in CDATA tried extracting but it does not work. – SDhwaj Apr 27 '16 at 09:32

1 Answers1

1

As @Rao note in the comments, you're using //ns1:Result as an XPath however this node doesn't exist in your response. Anyway as an alternative instead of use and XmlHolder, I purpose to use first XmlSlurper to parse the SOAP and get the CDATA node, and then JSonSlurper to parse the JSON contained in CDATA and get the desired values (in your case seems that you're looking for Name value attribute), see the below example:

import groovy.json.JsonSlurper

def soapResponse = '''<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
<ReportResponse xmlns="http://tempuri.org/">
     <ReportResult><![CDATA[{
  "Report": [
    {
      "Name": "ABC",
      "Number": "123",
      "Type": "XYZ",
      "Desc": "EFGH",
      "Group Name": "Name123",
      "Group Number": "123",
      "End Date": "12/30/2014",
      "Due Date": "04/15/2015",
      "Completion Date": null,
      "Status": "Status1",
      "Received Date": "",
      "Delivery Date": "",
      "Location": "",
      "Role": "",
     },
     {
      "Name": "EFG",
       "Number": "123",
      "Type": "XYZ",
      "Desc": "EFGH",
      "Group Name": "Name123",
      "Group Number": "123",
      "End Date": "12/30/2014",
      "Due Date": "04/15/2015",
      "Completion Date": null,
      "Status": "Status1",
      "Received Date": "",
      "Delivery Date": "",
      "Location": "",
      "Role": "Manager",
     }
    ]
} ]]></ReportResult>
  </ReportResponse>
   </s:Body>
</s:Envelope>'''

// parse the soap
def xml = new XmlSlurper().parseText(soapResponse)
// get cdata node
def reportCDATA = xml.'**'.findAll{ it.name() == 'ReportResult' }
def jsonTxt = reportCDATA.pop().toString()
// parse CDATA value as JSON
def json = new JsonSlurper().parseText(jsonTxt)
// get the Name attribute values
def names = json.Report.collect { it.Name }
names.each { log.info it }

If as you comment, instead of "Name" value of your JSON you want to get "Completion Date" you can do it as:

def completionDates = json.Report.collect { it."Completion Date"}

Or if looks more clear:

def completionDates = json.Report.collect { it[Completion Date] }

Take in account that in your sample the Report array contain two objects which both has null as value for "Completion Date". So using your JSON sample def completionDates will be [null, null].

Hope it helps,

albciff
  • 18,112
  • 4
  • 64
  • 89
  • I am getting empty result for the below mentioned code : def names = json.Report.collect { it.Name } names.each { log.info it } In case if I want to extract value for Completion date I have to mention this way it."Completion Date" ?? – SDhwaj Apr 27 '16 at 12:58
  • 1
    If you get empty result is surely because your input data differs from the data in the example, check for the path correctness in `XmlSlurper` and `JsonSlurper`. To get the `"Completion date"` check the updated response `:)` – albciff Apr 27 '16 at 13:10
  • Yes I have tried the below def Dates = json.Report.collect { it."Completion date"} I get no result in the Script Assertion Actually I have more than 100 objects in the Report array. – SDhwaj Apr 27 '16 at 13:58
  • Agree with @albciff, data presented in the question does not have data for `Completion Date`. For example if you take `Due Date`, dates are listed which can seen in the [screen shot](http://s000.tinyupload.com/index.php?file_id=17554526615670735162). More over, SDhwaj is using incorrect property name i.e., using `Completion date` instead of `Completion Date`. Please try correcting it. – Rao Apr 27 '16 at 15:34
  • 1
    Looks a copy paste issue for the incorrect case. The first comment has wrong case and @albciff used incorrect case in the provided script and is copied by the other or vice- versa. – Rao Apr 27 '16 at 15:38
  • @Rao you're right again, thanks `: )`... mobile is not the good way to answer haha. – albciff Apr 27 '16 at 16:27
  • I have tried the above mentioned for data which exists I do not get any result. def GrpNum = json.Report.collect{it."Group Number"} GrpNum.each{ log.info it } – SDhwaj Apr 28 '16 at 13:07