tags:

views:

91

answers:

2

I have spent the last few days trying to parse a soap response but I can't get it to work. I would like to be able to get all the "oproduct" objects.

EDIT: I am doing it this way instead of using the built in soap client because I need to do parallel requests using multi_curl.

Here is my code:

$xml = simplexml_load_string($response);
$xml->registerXPathNamespace('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/');
foreach ($xml->xpath('//oproduct') as $item)
{
  // do something
}

Here is the response:

<soap-env:envelope xmlns:ns1="http://v3.core.com.productserve.com/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"&gt;
  <soap-env:body>
    <ns1:getproductlistresponse>
      <oproduct>
        <iid>113133802</iid>
        <icategoryid>270</icategoryid>
        <imerchantid>1547</imerchantid>
        <iadult>0</iadult>
        <sname>The Ashes / 5th Test - England v Australia - Day 1</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=113133802&amp;amp;a=111402&amp;amp;m=1547&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/1547/113133802.jpg&lt;/sawthumburl&gt;
        <fprice>119.99</fprice>
      </oproduct>
      <oproduct>
        <iid>113133791</iid>
        <icategoryid>270</icategoryid>
        <imerchantid>1547</imerchantid>
        <iadult>0</iadult>
        <sname>The Ashes / 1st Test - England v Australia - Day 1</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=113133791&amp;amp;a=111402&amp;amp;m=1547&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/1547/113133791.jpg&lt;/sawthumburl&gt;
        <fprice>69.99</fprice>
      </oproduct>
      <oproduct>
        <iid>51155349</iid>
        <icategoryid>428</icategoryid>
        <imerchantid>513</imerchantid>
        <iadult>0</iadult>
        <sname>Rapitest DTM 118 Damp Test Meter</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=51155349&amp;amp;a=111402&amp;amp;m=513&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/513/51155349.jpg&lt;/sawthumburl&gt;
        <fprice>18.35</fprice>
      </oproduct>
      <oproduct>
        <iid>187948</iid>
        <icategoryid>474</icategoryid>
        <imerchantid>496</imerchantid>
        <iadult>0</iadult>
        <sname>Rapitest Dm 10 Electrical Multimeter</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=187948&amp;amp;a=111402&amp;amp;m=496&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/496/187948.jpg&lt;/sawthumburl&gt;
        <fprice>26.71</fprice>
      </oproduct>
      <oproduct>
        <iid>51155353</iid>
        <icategoryid>428</icategoryid>
        <imerchantid>513</imerchantid>
        <iadult>0</iadult>
        <sname>Rapitest DM 10 Electrical Multimeter</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=51155353&amp;amp;a=111402&amp;amp;m=513&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/513/51155353.jpg&lt;/sawthumburl&gt;
        <fprice>22.7</fprice>
      </oproduct>
      <oproduct>
        <iid>49152850</iid>
        <icategoryid>474</icategoryid>
        <imerchantid>1366</imerchantid>
        <iadult>0</iadult>
        <sname>Testboy Profi LED Plus</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=49152850&amp;amp;a=111402&amp;amp;m=1366&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/1366/49152850.jpg&lt;/sawthumburl&gt;
        <fprice>44.99</fprice>
      </oproduct>
      <oproduct>
        <iid>51155350</iid>
        <icategoryid>428</icategoryid>
        <imerchantid>513</imerchantid>
        <iadult>0</iadult>
        <sname>Rapitest ETP 116 Electrical Test Probe</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=51155350&amp;amp;a=111402&amp;amp;m=513&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/513/51155350.jpg&lt;/sawthumburl&gt;
        <fprice>17.55</fprice>
      </oproduct>
      <oproduct>
        <iid>51155351</iid>
        <icategoryid>428</icategoryid>
        <imerchantid>513</imerchantid>
        <iadult>0</iadult>
        <sname>Rapitest ET 111 Electrical Test Meter</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=51155351&amp;amp;a=111402&amp;amp;m=513&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/513/51155351.jpg&lt;/sawthumburl&gt;
        <fprice>13.55</fprice>
      </oproduct>
      <oproduct>
        <iid>72326941</iid>
        <icategoryid>474</icategoryid>
        <imerchantid>496</imerchantid>
        <iadult>0</iadult>
        <sname>Rapitest Etp 116 Electrical Test Probe</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=72326941&amp;amp;a=111402&amp;amp;m=496&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/496/72326941.jpg&lt;/sawthumburl&gt;
        <fprice>20.66</fprice>
      </oproduct>
      <oproduct>
        <iid>49338340</iid>
        <icategoryid>206</icategoryid>
        <imerchantid>80</imerchantid>
        <iadult>0</iadult>
        <sname>Ladies Protest Zekke Jacket True Black</sname>
        <sawdeeplink>http://www.awin1.com/pclick.php?p=49338340&amp;amp;a=111402&amp;amp;m=80&amp;amp;platform=cs&lt;/sawdeeplink&gt;
        <sawthumburl>http://images.productserve.com/thumb/80/49338340.jpg&lt;/sawthumburl&gt;
        <fprice>54.99</fprice>
      </oproduct>
      <itotalcount>6350</itotalcount>
    </ns1:getproductlistresponse>
  </soap-env:body>
</soap-env:envelope>
+2  A: 

PHP comes with a SOAP client that should make it so you don't have to manually parse SOAP XML. See here: http://php.net/manual/en/book.soap.php

Edit: For clarity, the SOAP client is not part of PHP, rather an extension.

raeb
This is correct, starting with PHP5.
brendan
Sorry guys, I should have been more clear. I am doing this way because I need to use multi_curl so I can do parallel requests.
Joe
Is there a way to use the soap client only to parse a soap response?
Joe
A: 

Could you clarify which version of PHP you're using (4 or 5)? Also is there a particular reason why you don't want to/can't use PHP 5's SOAP extension? Knowing this information should help us to give you a better answer.

The reason the code sample above isn't working is that you're looking in the wrong namespace for the oproduct nodes. While the root node is contained in the SOAP namespace the oproduct ones are under the "http://v3.core.com.productserve.com/" namespace. You also need to use the namespace alias in the XPath query. Try this, although I haven't tested it:

$xml = simplexml_load_string($response);
$xml->registerXPathNamespace('ns', 'http://v3.core.com.productserve.com/');
foreach ($xml->xpath('//ns:oproduct') as $item)
{
  // do something
}

Hopefully that will solve your immediate problem.

EDIT Thanks for the clarification. Again, untested but maybe this would work:

$xml = simplexml_load_string($response);
$xml->registerXPathNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('ns', 'http://v3.core.com.productserve.com/');
foreach ($xml->xpath('/soapenv:envelope/soapenv:body/ns:getproductlistresponse/ns:oproduct') as $item)
    {
      // do something
    }

Perhaps you need to go from the root node to the soap-Env:body to the oproduct nodes in the query. Hopefully that will work.

Further edit: I think I've just cracked this. Try the following code:

$xml = simplexml_load_string($response);
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['soap-env']);
$getproductlistresponse = $soap->body->children($ns['ns1']);
foreach ($getproductlistresponse->children() as $item)
{
  //This example just accesses the iid node but the others are all available.
  echo (string) $item->iid . '<br />';
}

Not the prettiest code but it works. I was hoping to get this to work with an XPath query but it was beyond my rudimentary knowledge of XPath. Perhaps someone else can post an answer using XPath?

Jeremy
Thanks Jeremy for replying. I am using PHP5. The reason I am doing it this way is because I need to do parallel requests with multi_curl. I tried what you suggested but it is returning false now.
Joe
Hi Joe, forget my last edit. I thought I would crack open a code editor and try this but the issue I'm having is that I can't get simplexml_load_string() to parse the response string. It just returns an empty SimpleXML object. I'll keep trying and will post back if I get the answer.
Jeremy
Thanks for your help Jeremy. I will try to mess around with the code you added above and see if I can get it to work.
Joe
Thanks Jeremy. Now I have another issue. The code works when the response is hard-coded but when I try to use the real soap response it's not working. I am getting the error: SimpleXMLElement::children() [simplexmlelement.children]: Node no longer exists.
Joe
I should have mentioned that that error is coming from the foreach.
Joe
I figured it out. That soap response was copied from within Firebug and all namespaces are lower-cased. The actual soap response has some uppercase namespaces and that was causing the issue. Anyways, thanks a lot Jeremy for all your help.
Joe
You're welcome Joe and I'm glad we got it figured out.
Jeremy