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);
}
}
}
