I'm working with a web service that is submitting an HTTP POST to a PHP page as follows:
FORM/POST PARAMETERS:
None
HEADERS:
Content-Type: text/xml
BODY:
<?xml version="1.0"?>
<mogreet>
<event>message-in</event>
<type>command_sms</type>
<campaign_id>12345</campaign_id>
<shortcode>123456</shortcode>
<msisdn>15552345678</msisdn>
<carrier><![CDATA[T-Mobile]]></carrier>
<carrier_id>2</carrier_id>
<message><![CDATA[xxxx testing]]></message>
</mogreet>
I need to be able to convert each of the XML elements into PHP variables so I can update a database. I've never had to work with an incoming POST with XML data before and not sure where to starT - I am familiar with processing incoming GET/POST requests but not raw xml.
I think you'll need to use $HTTP_RAW_POST_DATA. After that then you could use SimpleXMLElement as #ChristianGolihardt suggested.
Note that HTTP_RAW_POST_DATA is only available if the always_populate_raw_post_data setting has been enabled in php.ini. Otherwise, it may be easiest to do this:
$postData = file_get_contents("php://input");
...
$xml = new SimpleXMLElement($postData);
...
This will eliminate all the SimpleXMLElement objects and return your array:
from an xml string:
<?php
$xml='<?xml version="1.0"?>
<mogreet>
<event>message-in</event>
<type>command_sms</type>
<campaign_id>12345</campaign_id>
<shortcode>123456</shortcode>
<msisdn>15552345678</msisdn>
<carrier><![CDATA[T-Mobile]]></carrier>
<carrier_id>2</carrier_id>
<message><![CDATA[xxxx testing]]></message>
</mogreet>';
$xml = simplexml_load_string($xml);
$xml_array = json_decode(json_encode((array) $xml), 1);
print_r($xml_array);
?>
from an xml file:
$xml = simplexml_load_file("mogreet.xml");
$xml_array = json_decode(json_encode((array) $xml), 1);
print_r($xml_array);
output:
Array
(
[event] => message-in
[type] => command_sms
[campaign_id] => 12345
[shortcode] => 123456
[msisdn] => 15552345678
[carrier] => Array
(
)
[carrier_id] => 2
[message] => Array
(
)
)
Take a look at SimpleXMLElement:
http://php.net/manual/de/class.simplexmlelement.php
$xmlstr = $_POST['key'];
$xml = new SimpleXMLElement($xmlstr);
//work with $xml like this:
$event = $xml->mogreet->event;
You can see the key if you do this:
print_r($_POST);
Most times, we work with this kind of api, we want to log it, because we can not see it:
$debugFile = 'debug.log'
file_put_contents($debugFile, print_r($_POST, true), FILE_APPEND);
Take also a look at the Answer from Matt Browne, for getting Raw Input.
Related
I am getting a soap response as expected and then converting to an array. Here is my code:
$response = $client->__getLastResponse();
$response = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $response);
$xml = new SimpleXMLElement($response);
$body = $xml->xpath('//soapBody')[0];
$array = json_decode( str_replace('#', '', json_encode((array)$body)), TRUE);
print_r($array);
here is the output:
Array (
[GetCompanyCodeResponse] => Array (
[GetCompanyCodeResult] => Array (
[Customers] => Array (
[Customer] => Array (
[attributes] => Array (
[CustomerNo] => 103987
[CustomerName] => epds api testers Inc
[ContactId] => 219196
)
)
)
)
)
How do i echo the ContactId? Ive tried the following:
$att = $array->attributes();
$array->attributes()->{'ContactId'};
print_r($array);
I get the following error:
Fatal error: Uncaught Error: Call to a member function attributes() on array
Also tried:
$array->Customer['CustomerId'];
I get following error:
Notice: Trying to get property 'Customer' of non-object
Expecting to get 219196
I found the solution to the above problem. Not sure if it is the most elegant way to do it, but it returns result as expected. If there is a more efficient way to get the ContactId, I am open to suggestions.
print_r($array['GetCompanyCodeResponse']['GetCompanyCodeResult']
['Customers']['Customer']['attributes']['ContactId']);
You have followed some very bad advice on how to parse the XML, and completely thrown away the functionality of SimpleXML.
Specifically, the reason you can't run the attributes() method is that you've converted the SimpleXML object to a plain array using this ugly hack:
$array = json_decode( str_replace('#', '', json_encode((array)$body)), TRUE);
To use SimpleXML as its authors intended, I suggest you read:
The examples in the PHP manual
This reference answer on handling XML namespaces
Since you didn't paste the actual XML in the question, I'm going to take a guess that it looks like this:
<?xml version = "1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope">
<soap:Body xmlns="http://www.example.org/companyInfo">
<GetCompanyCodeResponse>
<GetCompanyCodeResult>
<Customers>
<Customer CustomerNo="103987" CustomerName="epds api testers Inc" ContactId="219196" />
</Customers>
</GetCompanyCodeResult>
</GetCompanyCodeResponse>
</soap:Body>
</soap:Envelope>
If that is in $response, we don't need to do any weirdness with str_replace or json_encode, we can use the methods built into SimpleXML to navigate around the XML:
$xml = new SimpleXMLElement($response);
// The Body is in the SOAP Envelope namespace
$body = $xml->children('http://www.w3.org/2001/12/soap-envelope')->Body;
// The element inside that is in some other namespace
$innerResponse = $body->children('http://www.example.org/companyInfo')->GetCompanyCodeResponse;
// We need to traverse the XML to get to the node we're interested in
$customer = $innerResponse->GetCompanyCodeResult->Customers->Customer;
// Unprefixed attributes aren't technically in any namespace (an oddity in the XML namespace spec!)
$attributes = $customer->attributes(null);
// Here's the value you were looking for
echo $attributes['ContactId'];
Unlike your previous code, this won't break if:
The server starts using a different local prefix instead of soap:, or adding a prefix on the GetCompanyCodeResponse element
The response comes back with more than one Customer (the ->Customer always means the same as ->Customer[0], the first child element with that name)
The Customer element has child elements or text content as well as attributes
It also allows you to use other features of SimpleXML, like using an xpath expression to search the document or even switching to the full DOM API for more complex operations.
How do I get the entire result from XML using simplexml_load_string?
My XML looks like this
<xml>
<code>
<codedesc>Code Name</codedesc>
100
</code>
<code>
<codedesc>Code Name 2</codedesc>
200
</code>
</xml>
When I load it with PHP using this code
$XML = simplexml_load_string($data);
print_r($XML);
I only get codedesc and not the code number as you can see here
https://eval.in/51562
You need to wrap your values in XML so that they can be accessed.
<xml>
<code>
<codedesc>Code Name</codedesc>
<value>100</value>
</code>
<code>
<codedesc>Code Name 2</codedesc>
<value>200</value>
</code>
</xml>
You can then access them like so:
$xml = simplexml_load_string($data);
echo $xml->code[0]->value; //100
echo $xml->code[1]->value; //200
echo $xml->code[1]->codedesc; //Code Name 2
If you can't change your xml, the following should work:
echo $xml->code[0]; //100
echo $xml->code[1]; //200
I'm not sure what you're trying to get SimpleXML correctly parses your XML string, and returns a class with an array called 'code', that has 2 objects called codedesc:
SimpleXMLElement Object
(
[code] => Array
(
[0] => SimpleXMLElement Object
(
[codedesc] => Code Name
)
[1] => SimpleXMLElement Object
(
[codedesc] => Code Name 2
)
)
)
If you're trying to get to the values (100, 200) - try putting them in XML elements.
If you're trying to print the entire XML, try print_r($XML->asXML()) (see this)
what i want to do is : i have an CRM API which produce data in xml format,
i am using DOMDocument() to fetch the data into pieces. The problem is when i tried to load the data like : $dom->loadXML($data);
i got the error :
DOMDocument::loadXML() [domdocument.loadxml]: Input is not proper UTF-8
i google i got an alternative solution to use with file_get_contents() but still i am getting warning like:
here is the code that i am using to fetch the xml data:
$text = file_get_contents(stripslashes(utf8_decode($data)));
$doc = new DOMDocument();
$doc->loadXML($text);
and here i put my XML return data, not complete but just a small piece:
<?xml version="1.0" encoding="utf-8"?>
<whmcsapi version="5.0.3">
<action>getticket</action>
<result>success</result>
<ticketid>5767</ticketid>
<tid>409865</tid>
<c>NwLldOG6</c>
<deptid>2</deptid>
<deptname>Technical</deptname>
<userid>27476</userid>
<name>shirley b broyles (home)</name>
<email>sbroyles1#stx.rr.com</email>
<cc></cc>
<date>2012-08-27 19:52:12</date>
<subject>printer not working</subject>
<status>Customer-Reply</status>
<priority>High</priority>
<admin></admin>
<lastreply>2012-08-28 23:34:17</lastreply>
<flag>0</flag>
<service></service>
<replies>
<reply>
can anyone please tell me where is the problem? or any alternative ??
Okay, so let's strip down the problem. If $data contains invalid UTF-8, you should be thinking how to make it valid; one way (not sure if that works for you) is with utf8_encode() rather than utf8_decode() (which is used to turn UTF-8 into ISO-8859-1):
$doc = new DOMDocument();
$doc->loadXML(utf8_encode($data));
Otherwise you will need to find out which part of the text includes the bad input. I'll see what I can come up with.
Resources
Ensuring valid utf-8 in PHP
you can try simplexml_load_file php function..
$xml = simplexml_load_file("addinsrss.xml");
echo "<pre>";print_r($xml);echo "</pre>";
If you already have the xml source then dont pass it to FGC. Pass it directly to domDocument.
Or you can also use simplexml_load_string(),
<?php
$xml = '<?xml version="1.0" encoding="utf-8"?>
<whmcsapi version="5.0.3">
<action>getticket</action>
<result>success</result>
<ticketid>5767</ticketid>
<tid>409865</tid>
<c>NwLldOG6</c>
<deptid>2</deptid>
<deptname>Technical</deptname>
<userid>27476</userid>
</whmcsapi>
';
$xml = simplexml_load_string($xml);
print_r($xml);
/*
SimpleXMLElement Object
(
[#attributes] => Array
(
[version] => 5.0.3
)
[action] => getticket
[result] => success
[ticketid] => 5767
[tid] => 409865
[c] => NwLldOG6
[deptid] => 2
[deptname] => Technical
[userid] => 27476
...
...
)
*/
echo $xml->tid; //409865
?>
Or directly use $xml = simplexml_load_file('http://example.com/somexml.xml'); to load from an external url.
I've got an XML output that produces code such as:
<loadavg>
<one>0.00</one>
<five>0.02</five>
<fifteen>0.02</fifteen>
</loadavg>
<!-- whostmgrd -->
I would like to know how I can use PHP to parse that file, and grab the contents between <one>,<five> and <fifteen>. It would be useful if it were to be stored as $loadavg[1] an array.
Thanks
Yep, SimpleXML can do it:
$xml = <<<XML
<loadavg>
<one>0.00</one>
<five>0.02</five>
<fifteen>0.02</fifteen>
</loadavg>
XML;
$root = new SimpleXMLElement($xml);
$loadavg = array((string) $root->one,
(string) $root->five,
(string) $root->fifteen);
print_r($loadavg);
prints
Array (
[0] => 0.00
[1] => 0.02
[2] => 0.02
)
The easiest way to parse an XML file is using SimpleXML. It should be easy to load the XML as a SimpleXML object and get the data using that. If you could post a sample of a complete XML file I could offer some sample code.
I have an xml file
<?xml version="1.0" encoding="utf-8"?>
<xml>
<events date="01-10-2009" color="0x99CC00" selected="true">
<event>
<title>You can use HTML and CSS</title>
<description><![CDATA[This is the description ]]></description>
</event>
</events>
</xml>
I used xpath and and xquery for parsing the xml.
$xml_str = file_get_contents('xmlfile');
$xml = simplexml_load_string($xml_str);
if(!empty($xml))
{
$nodes = $xml->xpath('//xml/events');
}
i am getting the title properly, but iam not getting description.How i can get data inside
the cdata
SimpleXML has a bit of a problem with CDATA, so use:
$xml = simplexml_load_file('xmlfile', 'SimpleXMLElement', LIBXML_NOCDATA);
if(!empty($xml))
{
$nodes = $xml->xpath('//xml/events');
}
print_r( $nodes );
This will give you:
Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[date] => 01-10-2009
[color] => 0x99CC00
[selected] => true
)
[event] => SimpleXMLElement Object
(
[title] => You can use HTML and CSS
[description] => This is the description
)
)
)
You are probably being misled into thinking that the CDATA is missing by using print_r or one of the other "normal" PHP debugging functions. These cannot see the full content of a SimpleXML object, as it is not a "real" PHP object.
If you run echo $nodes[0]->Description, you'll find your CDATA comes out fine. What's happening is that PHP knows that echo expects a string, so asks SimpleXML for one; SimpleXML responds with all the string content, including CDATA.
To get at the full string content reliably, simply tell PHP that what you want is a string using the (string) cast operator, e.g. $description = (string)$nodes[0]->Description.
To debug SimpleXML objects and not be fooled by quirks like this, use a dedicated debugging function such as one of these: https://github.com/IMSoP/simplexml_debug
This could also be another viable option, which would remove that code and make life a little easier.
$xml = str_replace("<![CDATA[", "", $xml);
$xml = str_replace("]]>", "", $xml);