Page 1 of 1

Extracting SOAP Request data [SOLVED]

Posted: Mon Sep 24, 2007 8:54 pm
by jeffery
I have a SOAP request logger which logs all SOAP requests/responses being made on the system. What I want to do is extract the function name being called and the params passed to it. The following is an example XML Request:

Code: Select all

 
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope 
xmlns:env="http://www.w3.org/2003/05/soap-envelope" 
xmlns:ns1="urn:Gateway_Proxy" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Body>
  <ns1:make_proxy_payment env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
    <payment_id>61ecc268-1cd0-f468</payment_id>
    <payment_amount>15495</payment_amount>
    <callback_query_string>&payment_id=61ecc268-1cd0-f468</callback_query_string>
    <transaction_note>Order from Student Library Fees with Payment Id: 61ecc268-1cd0-f468</transaction_note>
  </ns1:make_proxy_payment>
</env:Body>
</env:Envelope>
As you can see the "<env:Body>" tag contains everything what I need to extract. "<ns1:make_proxy_payment>" tag contains the function name and the sub-elements contains the function params. What I have so far is:

Code: Select all

	$xml = new SimpleXMLElement(html_entity_decode($record['SoapRequestEnvelope']));
			
	foreach ($xml->xpath('//env:Body') as $body) 
	{
		print_r_pre($body);
	}
How do I reference the elements through the SimpleXMLElement Object?

Posted: Mon Sep 24, 2007 8:57 pm
by mrkite
you can do:

Code: Select all

$payment_id=$body->{'ns1:make_proxy_payment'}->payment_id;
Is that what you're asking?

Posted: Mon Sep 24, 2007 9:01 pm
by jeffery
mrkite wrote:you can do:

Code: Select all

$payment_id=$body->{'ns1:make_proxy_payment'}->payment_id;
Is that what you're asking?
thanks mrkite,

Before I get to the payment_id, I need to know what function was called. Each request could be a different function. It would be good if I could automate the process of "finding" which function was called and their params and values. That way in the future I don't have to maintain a case statement for each function list.

So basically how do I extract the value "make_proxy_payment" and the "payment_id" (and its value). etc.

Posted: Mon Sep 24, 2007 10:32 pm
by mrkite
jeffery wrote: So basically how do I extract the value "make_proxy_payment" and the "payment_id" (and its value). etc.

Code: Select all

foreach ($body->children() as $child)
{
     if ($child->getName()=="make_proxy_payment") .....
}
I can't remember how simplexml handles namespaces... so getName() may return either "make_proxy_payment" or "ns1:make_proxy_payment". You'll have to test it to find out.

Posted: Tue Sep 25, 2007 12:35 am
by jeffery
thats not going to help me.. as I wouldn't know what the "make_proxy_payment" value is going to be.

Posted: Tue Sep 25, 2007 7:55 am
by Begby
Try this

Code: Select all

foreach ($body->children() as $child)
{
     echo $child->getName() ;
}
and see if that clues you in

Posted: Tue Sep 25, 2007 6:19 pm
by jeffery
ok the problem seems to be with namespaces.

if I do the following:

Code: Select all

$xml_string = <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
 <movie>
  <title>PHP: Behind the Parser</title>
  <characters>
   <character>
    <name>Ms. Coder</name>
    <actor>Onlivia Actora</actor>
   </character>
   <character>
    <name>Mr. Coder</name>
    <actor>El ActÓr</actor>
   </character>
  </characters>
  <plot>
   So, this language. It is like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  </plot>
  <great-lines>
   <line>PHP solves all my web problems</line>
  </great-lines>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
</movies>
XML;
$xml = new SimpleXMLElement($xml_string);
print_r($xml);
I get the following output:

Code: Select all

SimpleXMLElement Object
(
    [movie] => SimpleXMLElement Object
        (
            [title] => PHP: Behind the Parser
            [characters] => SimpleXMLElement Object
                (
                    [character] => Array
                        (
                            [0] => SimpleXMLElement Object
                                (
                                    [name] => Ms. Coder
                                    [actor] => Onlivia Actora
                                )

                            [1] => SimpleXMLElement Object
                                (
                                    [name] => Mr. Coder
                                    [actor] => El ActÓr
                                )

                        )

                )

            [plot] => 
   So, this language. It is like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  
            [great-lines] => SimpleXMLElement Object
                (
                    [line] => PHP solves all my web problems
                )

            [rating] => Array
                (
                    [0] => 7
                    [1] => 5
                )

        )

)
But similar output cannot be achieved with the SOAP XML Request shown above. So far I have

Code: Select all

$soap_request_string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="urn:Gateway_Proxy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Body>
  <ns1:make_proxy_payment env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
    <payment_id>61ecc268-1cd0-f468</payment_id>
    <payment_amount>15495</payment_amount>
    <callback_query_string>&payment_id=61ecc268-1cd0-f468</callback_query_string>
    <transaction_note>Order from Student Library Fees with Payment Id: 61ecc268-1cd0-f468</transaction_note>
  </ns1:make_proxy_payment>
</env:Body>
</env:Envelope>
XML;


$xml = new SimpleXMLElement($soap_request_string, NULL, false);
print_r($xml);
$ns = $xml->getNamespaces(true);
print_r($ns);
foreach ($xml->xpath('//env:Body') as $body)
{
    //print_r($body);
    foreach ($body->children($ns['env'], true) as $child)
    {
        print_r($child);
    }
}
And there is not much output:

Code: Select all

SimpleXMLElement Object
(
)
Array
(
    [env] => http://www.w3.org/2003/05/soap-envelope
    [ns1] => urn:Gateway_Proxy
)
any more ideas?

Posted: Tue Sep 25, 2007 8:39 pm
by mrkite
SimpleXML elements are objects, not arrays. You can't use print_r.

Posted: Tue Sep 25, 2007 8:58 pm
by jeffery
mrkite wrote:SimpleXML elements are objects, not arrays. You can't use print_r.
I didn't say they were arrays. And why can't you print_r objects? Previous post has an example of print_r of an object. The syntax is:

Code: Select all

mixed print_r ( mixed $expression [, bool $return] )
and the documentation follows it up with:
Return Values

If given a string, integer or float, the value itself will be printed. If given an array, values will be presented in a format that shows keys and elements. Similar notation is used for objects.

Posted: Thu Sep 27, 2007 4:05 am
by jeffery
I solved it!!

Code: Select all

$soap_request_string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="urn:Gateway_Proxy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Body>
  <ns1:make_proxy_payment env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
    <payment_id>61ecc268-1cd0-f468</payment_id>
    <payment_amount>15495</payment_amount>
    <callback_query_string>&payment_id=61ecc268-1cd0-f468</callback_query_string>
    <transaction_note>Order from Student Library Fees with Payment Id: 61ecc268-1cd0-f468</transaction_note>
  </ns1:make_proxy_payment>
</env:Body>
</env:Envelope>
XML;


$xml = new SimpleXMLElement($soap_request_string, NULL, false, 'http://www.w3.org/2003/05/soap-envelope');
//print_r_pre($xml);
$ns = $xml->getNamespaces(true);
//print_r_pre($ns);

foreach ($xml->children($ns['env']) as $body) 
{
	//printf("%s<br />", $body->getName());
	
	foreach ($body->children($ns['ns1']) as $function)
	{
		printf("%s<br />", $function->getName());
		
		foreach ($function->children() as $parameters)
		{
			printf("%s => \"%s\"<br />", $parameters->getName(), $parameters);
		}
	}
}
:D