I'm trying to change this soap response into php variables and failing!

I am trying this like:

$return = $response->DownloadDataByUserStringResult->UserId;

But this doesn't work

            $options = array( 
                'soap_version'=>SOAP_1_1, 
                'exceptions'=>true, 
                'trace'=>1, 
                'cache_wsdl'=>WSDL_CACHE_NONE               
            ); 
            $client = new SoapClient('http://client.Service.asmx?WSDL', $options); 

        } catch (Exception $e) { 
            echo "<h2>Exception Error!</h2>"; 
            echo $e->getMessage(); 
        }

            $params = array(
                'domain' => 'mydomain',
                'username' => 'myuser',
                'password' => 'mypass',
                'xmlMessage' => '<data clientid="10588"> <Report.Disposition.Summary3 reportid="3" startdatetime="2015-08-01 00:00:00" enddatetime="2015-08-10 00:00:00"/> </data>'
                );

$response = $client->__soapCall('DownloadDataByUserString', array($params));

var_dump($response);



Response: 

<?xml version="1.0" encoding="utf-8"?> <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> <DownloadDataByUserStringResponse xmlns="http://**.net/"> <DownloadDataByUserStringResult>
<?xml version="1.0" encoding="utf-16"?>
<results>
<data>
<Report.Disposition.Summary3 rows="258">
<row UserId="104" Name="Agent Template" Code="9999 " Count="8" TalkDuration="28" AvgTalkDuration="3" WrapDuration="0" AvgWrapDuration="0" PercentageOfTotalCalls="100" />
<row UserId="123" Name="Gareth Wright" Code="106 DUPLICATE" Count="7" TalkDuration="193" AvgTalkDuration="27" WrapDuration="110" AvgWrapDuration="15" PercentageOfTotalCalls="0.8" />
<row UserId="123" Name="Gareth Wright" Code="109 NI -FEES TOO HIGH" Count="14" TalkDuration="5539" AvgTalkDuration="395" WrapDuration="456" AvgWrapDuration="32" PercentageOfTotalCalls="1.6" />
<row UserId="123" Name="Gareth Wright" Code="111 NI -WENT WITH COMPETITOR " Count="17" TalkDuration="1125" AvgTalkDuration="66" WrapDuration="405" AvgWrapDuration="23" PercentageOfTotalCalls="2" /><

Recommended Answers

All 10 Replies

What is very strange with your question is that this web service method (DownloadDataByUserString) returns an XML inside (that more over has different encoding !!!). I have worked with web services methods that returned XML but in a CDATA wrapper , not that way. If you have something to do with the provider , thing seriously refactoring , if your app is only the consumer – client than lets figure out a way to parse those data (you didn't provided the full response so I had to speculate and create one from your example).

<?php
$response = <<<XML
<?xml version="1.0" encoding="utf-8"?> 
    <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> 
    <DownloadDataByUserStringResponse xmlns="http://**.net/"> 
        <DownloadDataByUserStringResult>
            <?xml version="1.0" encoding="utf-16"?>
                <results>
                    <data>
                        <Report.Disposition.Summary3 rows="4">
                            <row UserId="104" Name="Agent Template" Code="9999 " Count="8" TalkDuration="28" AvgTalkDuration="3" WrapDuration="0" AvgWrapDuration="0" PercentageOfTotalCalls="100" />
                            <row UserId="123" Name="Gareth Wright" Code="106 DUPLICATE" Count="7" TalkDuration="193" AvgTalkDuration="27" WrapDuration="110" AvgWrapDuration="15" PercentageOfTotalCalls="0.8" />
                            <row UserId="123" Name="Gareth Wright" Code="109 NI -FEES TOO HIGH" Count="14" TalkDuration="5539" AvgTalkDuration="395" WrapDuration="456" AvgWrapDuration="32" PercentageOfTotalCalls="1.6" />
                            <row UserId="123" Name="Gareth Wright" Code="111 NI -WENT WITH COMPETITOR " Count="17" TalkDuration="1125" AvgTalkDuration="66" WrapDuration="405" AvgWrapDuration="23" PercentageOfTotalCalls="2" />
                        </Report.Disposition.Summary3>
                    </data>
                </results>
        </DownloadDataByUserStringResult>    
    </DownloadDataByUserStringResponse>
    </soap:Body>
    </soap:Envelope>
XML;


$response = trim($response);
$response = str_ireplace(array("soap:","<?xml version=\"1.0\" encoding=\"utf-16\"?>")
    , "", $response);
$xml = new SimpleXMLElement($response);
print_r($xml);

?>

That gets me an error:

Warning: trim() expects parameter 1 to be string, object given in /home//public_html/soap.php on line 58

Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in /home/public_html/soap.php:61 Stack trace: #0 /home/public_html/soap.php(61): SimpleXMLElement->__construct('') #1 {main} thrown in /home/public_html/soap.php on line 61

What is the result when you var_dump or var_export the $response ? Is it string as you wrote in the first post or is it an object ?

var_dump:

object(stdClass)#4 (1) { ["DownloadDataByUserStringResult"]=> string(50421) "" } 

If the $response->DownloadDataByUserStringResult is the string you have after the <DownloadDataByUserStringResult> tag in your first post then the only thing you have to do is:

$xml = new SimpleXMLElement( $response->DownloadDataByUserStringResult );
print_r($xml);

If it is the string of your first post then follow the first example I gave but instead of:

$response = trim($response);

use:

$response = trim($response->DownloadDataByUserStringResult);

You're a genius :)

Ok so the output looks like this now, how do I call individual rows:

SimpleXMLElement Object ( [data] => SimpleXMLElement Object ( [Report.Disposition.Summary3] => SimpleXMLElement Object ( [@attributes] => Array ( [rows] => 258 ) [row] => Array ( [0] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 104 [Name] => Agent Template [Code] => 9999 [Count] => 8 [TalkDuration] => 28 [AvgTalkDuration] => 3 [WrapDuration] => 0 [AvgWrapDuration] => 0 [PercentageOfTotalCalls] => 100 ) ) [1] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 106 DUPLICATE [Count] => 7 [TalkDuration] => 193 [AvgTalkDuration] => 27 [WrapDuration] => 110 [AvgWrapDuration] => 15 [PercentageOfTotalCalls] => 0.8 ) ) [2] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 109 NI -FEES TOO HIGH [Count] => 14 [TalkDuration] => 5539 [AvgTalkDuration] => 395 [WrapDuration] => 456 [AvgWrapDuration] => 32 [PercentageOfTotalCalls] => 1.6 ) ) [3] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 111 NI -WENT WITH COMPETITOR [Count] => 17 [TalkDuration] => 1125 [AvgTalkDuration] => 66 [WrapDuration] => 405 [AvgWrapDuration] => 23 [PercentageOfTotalCalls] => 2 ) ) [4] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 113 WRONG NUMBER [Count] => 7 [TalkDuration] => 300 [AvgTalkDuration] => 42 [WrapDuration] => 120 [AvgWrapDuration] => 17 [PercentageOfTotalCalls] => 0.8 ) ) [5] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 114 NOT INTERESTED -OTHER [Count] => 22 [TalkDuration] => 1611 [AvgTalkDuration] => 73 [WrapDuration] => 929 [AvgWrapDuration] => 42 [PercentageOfTotalCalls] => 2.6 ) ) [6] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 121 LEFT MESSAGE [Count] => 1 [TalkDuration] => 93 [AvgTalkDuration] => 93 [WrapDuration] => 24 [AvgWrapDuration] => 24 [PercentageOfTotalCalls] => 0.1 ) ) [7] => SimpleXMLElement Object ( [@attributes] => Array ( [UserId] => 123 [Name] => Gareth Wright [Code] => 125 CALL BACK - 5HRS [Count] => 36 [TalkDuration] => 2552 [AvgTalkDuration] => 70 [WrapDuration] => 1289 [AvgWrapDuration] => 35 [PercentageOfTotalCalls] => 4.2 ) ) 

For example if I wanted all of the UserId from this how would I call them, would it be like this:

foreach($xml->UserId as $id){
    echo $id.'<br />';
}

Once again thanks for your help!!!!! :)

Hello and thank you , probably you have figured it out , but here is a simple way to iterate through this SimpleXMLElement object (guess from the output that you are in DownloadDataByUserStringResponse->DownloadDataByUserStringResult->results)

$xmlArray = xml2array($xml);
if( isset($xmlArray["data"]) 
    && isset($xmlArray["data"]["Report.Disposition.Summary3"]) 
    && isset($xmlArray["data"]["Report.Disposition.Summary3"]["row"]) )
{
    $rows = $xmlArray["data"]["Report.Disposition.Summary3"]["row"];
    if( count($rows) > 0 )
    {
        foreach($rows as $row)
        {
            $userDataArray = $row["@attributes"];
            var_export($userDataArray);
            echo "<br/><br/>";
            // you will have for each user something like 
            // array ( 'UserId' => '104', 'Name' => 'Agent Template'
            // , 'Code' => '9999 ', 'Count' => '8', 'TalkDuration' => '28'
            // , 'AvgTalkDuration' => '3', 'WrapDuration' => '0'
            // , 'AvgWrapDuration' => '0', 'PercentageOfTotalCalls' => '100', )
        }
    }
}

/**
 * Takes a SimpleXMLElement as argument and returns the array of its data 
 * and attributes
 * @param SimpleXMLElement $xmlObject
 * @param array $out . Optional array() by default
 * @return array
 * @see http://php.net/manual/en/ref.simplexml.php#111227
 */
function xml2array ( SimpleXMLElement $xmlObject, $out = array () )
{
    foreach ( (array) $xmlObject as $index => $node )
    {
        $out[$index] = ( is_object ( $node ) ||  is_array ( $node ) ) 
        ? xml2array ( $node ) : $node;
    }
    return $out;
}

The same thing we did here with arrays we could have done it with objects instantiators and objects list but of course the first step is to understand how SOAP is working in general. (For the specific method that your app had to consume I keep my doubts that maybe it wasn't designed well on the provider side or it wasn't designed for Web Services at all (sometimes , some people in order not having more providers they add a plain method from post (from example) inside a service ( I don't think that is a good way either but would explain the xml inside the xml response) )

I have to agree that it hasn't been designed well, compared to other soapclients this one has been horrible! Again thank you for your help, my brain has been hurting over this for a while.

The example you have just sent to me returns this error:

Catchable fatal error: Argument 1 passed to xml2array() must be an instance of SimpleXMLElement, array given, called in

The output that you had were SimpleXMLElement Object was this from var_export or var_dump ?

ok ... this might be correct (this method added the || is_array)
So try:

/**
 * Takes a SimpleXMLElement as argument and returns the array of its data 
 * and attributes
 * @param SimpleXMLElement | array $xmlObject
 * @param array $out . Optional array() by default
 * @return array
 * @see http://php.net/manual/en/ref.simplexml.php#111227
 */
function xml2array ( $xmlObject, $out = array () )
{
    foreach ( (array) $xmlObject as $index => $node )
    {
        $out[$index] = ( is_object ( $node ) ||  is_array ( $node ) ) 
        ? xml2array ( $node ) : $node;
    }
    return $out;
}

(if you aren't in the node I guessed you can use this function to understand where you are and do the rest from there)

That my friend is perfect, I can now call each individual element of that array with $row['@attributes']['element']. Thanks so much for your help. Kudos to you!!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.