Forum Discussion

toniboi's avatar
toniboi
Occasional Contributor
13 years ago

How to retrieving a specific node from a soap response?

Hello all, this is my first post here and I am new to SoapUI and SoapUI Pro. I came across a property transfer problem recently, and I tried with no luck in googling it for the solution.
So I was practising with a web service from webservicex.net call "country codes", and when I run the ""GetCountry" test request I will get a list of countries as the response.


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetCountriesResponse xmlns="http://www.webserviceX.NET">
<GetCountriesResult><![CDATA[<NewDataSet>
<Table>
<Name>Afghanistan, Islamic State of</Name>
</Table>
<Table>
<Name>Albania</Name>
</Table>
<Table>
<Name>Algeria</Name>
</Table>
<Table>
<Name>American Samoa</Name>
</Table>
...
</NewDataSet>]]></GetCountriesResult>
</GetCountriesResponse>
</soap:Body>
</soap:Envelope>


That is all good until the point that I want to retrieve only one of the countries from the data set, Algeria for instance. It's because I want to transfer the country name to the next test step which is a service taking a country name as a request. I tried to select the node from the response, however I noticed that the XPath I got was pointing to whole response instead of one of those nodes


declare namespace ns1='http://www.webserviceX.NET';
//ns1:GetCountriesResponse[1]/ns1:GetCountriesResult[1]


I guess it is probably very simple question to some of you here, but my XPath skills kind of limit my ability to solve it myself. Much appreciated if anyone could help.

Tony
  • M_McDonald's avatar
    M_McDonald
    Super Contributor
    A CDATA section hides it's content from any XML parser, so you need an intermediate step to get the NewDataSet XML. If you put the following in a Groovy script step

    def gu = new com.eviware.soapui.support.GroovyUtils( context )
    def responseAsXml = context.expand( '${MyRequest#ResponseAsXml}' )
    def holder = gu.getXmlHolder( responseAsXml )
    holder.namespaces["ns"] = "http://www.webserviceX.NET"
    return holder.getNodeValue( "//ns:GetCountriesResult[1]" )


    the step will return

    <NewDataSet>
    <Table>
    <Name>Afghanistan, Islamic State of</Name>
    </Table>
    <Table>
    <Name>Albania</Name>
    </Table>
    <Table>
    <Name>Algeria</Name>
    </Table>
    <Table>
    <Name>American Samoa</Name>
    </Table>
    </NewDataSet>

    Then you can point to the Groovy step as the source for your PropertyTransfer.

    //NewDataSet[1]/Table[1]/Name[1]
  • toniboi's avatar
    toniboi
    Occasional Contributor
    Hi M McDonald, thanks a lot for the reply. It looks very logical and easy to understand to me, however, when I run the script I get an error message saying that: "org.apache.xmlbeans.XmlException: error: Unexpected element CDATA". I am not sure if you know what goes wrong here.
  • M_McDonald's avatar
    M_McDonald
    Super Contributor
    Did you change "MyRequest" to be the name of your request step?
  • toniboi's avatar
    toniboi
    Occasional Contributor
    Yes, I did. It is called "GetCountriesRequest" which is the request sends me back the CDATA, and the Groovy Script step follows.
  • toniboi's avatar
    toniboi
    Occasional Contributor
    Here is the error log:
    Thu May 10 13:01:07 NZST 2012:ERROR:org.apache.xmlbeans.XmlException: error: Unexpected element: CDATA
    org.apache.xmlbeans.XmlException: error: Unexpected element: CDATA
    at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3486)
    at org.apache.xmlbeans.impl.store.Locale.parse(Locale.java:712)
    at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:696)
    at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:683)
    at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:208)
    at org.apache.xmlbeans.XmlObject$Factory.parse(XmlObject.java:580)
    at com.eviware.soapui.support.xml.XmlUtils.createXmlObject(XmlUtils.java:263)
    at com.eviware.soapui.support.XmlHolder.<init>(XmlHolder.java:38)
    at com.eviware.soapui.support.XmlHolder.<init>(XmlHolder.java:54)
    at com.eviware.soapui.support.GroovyUtils.getXmlHolder(GroovyUtils.java:72)
    at com.eviware.soapui.support.GroovyUtils$getXmlHolder.call(Unknown Source)
    at Script1.run(Script1.groovy:3)
    at com.eviware.soapui.support.scripting.groovy.SoapUIGroovyScriptEngine.run(SoapUIGroovyScriptEngine.java:96)
    at com.eviware.soapui.support.scripting.groovy.SoapUIProGroovyScriptEngineFactory$SoapUIProGroovyScriptEngine.run(SourceFile:89)
    at com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep.run(WsdlGroovyScriptTestStep.java:149)
    at com.eviware.soapui.impl.wsdl.panels.teststeps.GroovyScriptStepDesktopPanel$RunAction$1.run(GroovyScriptStepDesktopPanel.java:274)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    Caused by: org.xml.sax.SAXParseException; systemId: file:; lineNumber: 1; columnNumber: 1; Unexpected element: CDATA
    at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportFatalError(Piccolo.java:1038)
    at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:723)
    at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3454)
    ... 18 more
  • toniboi's avatar
    toniboi
    Occasional Contributor
    Hi M, this is the exported project for your review. Cheers.
  • toniboi's avatar
    toniboi
    Occasional Contributor
    Hi M McDonald

    I have solved problem using the tutorial form here:
    http://www.soapui.org/Functional-Testin ... cdata.html

    My case is even simpler than the one shown - I only need one temp property transfer instead of two as shown on that page. I am still working on the groovy script solution and it doesn't look so bad so far.

    Thanks a lot for your help! If you do get the groovy script working, please let me know.

    PS: I have also included my project here just in case anyone wants to know how I did it. Eventually, it looks so simple!
  • M_McDonald's avatar
    M_McDonald
    Super Contributor
    OK, I had been using a HTTP Request instead of a Test Request to work out the script, so instead of

    def responseAsXml = context.expand( '${GetCountriesRequest#ResponseAsXml}' ) 
    use
    def responseAsXml = context.expand( '${GetCountriesRequest#Response}' )