Nested SimpleXML Attributes To Associative Array - php

I am integrating a payment gateway into a website and their API is returning an xml object where the values I require are nested.
SimpleXMLElement Object
(
[form] => SimpleXMLElement Object
(
[input] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SessionStored
[value] => True
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SessionStoredError
[value] =>
)
)
[2] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SST
[value] => e19e8abe-a2d6-4ce7
)
)
)
)
)
Using php how can I get the nested attributes into an associative array like the following format?
$array['SessionStored'] = 'True'
$array['SessionStoredError'] = ''
$array['SST'] = 'e19e8abe-a2d6-4ce7'
Its a bit messy but after reading other articles online I have put together the following which throws a 'Fatal error: Call to a member function attributes()'
$xmlData = simplexml_load_string($result);
$aXml = json_decode( json_encode($xmlData) , 1);
$testArray = $aXml['form']['input'];
for($i = 0; $i < count($testArray); $i++)
{
foreach($testArray[$i]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
}

Do not try to convert the XML.
Converting XML to JSON means loosing information. Generic conversion does not use the semantic structure. You don't have "nested attributes" just some input element nodes with attribute nodes.
Read it and generate the array from the data.
$result = [];
$element = new SimpleXMLElement($xml);
foreach ($element->form->input as $input) {
$result[(string)$input['name']] = (string)$input['value'];
}
var_dump($result);
Output:
array(3) {
["SessionStored"]=>
string(4) "True"
["SessionStoredError"]=>
string(0) ""
["SST"]=>
string(18) "e19e8abe-a2d6-4ce7"
}
This is easy with DOM, too:
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$result = [];
foreach ($xpath->evaluate('//form/input') as $input) {
$result[$input->getAttribute('name')] = $input->getAttribute('value');
}
var_dump($result);

Related

XML into MySql Database (SimpleXML)

I've this XML file taked from post method :
<?xml version="1.0" encoding="utf-8"?>
<impianto id="id1">
<misure>
<misura time="1900-01-01T01:01:01+01:00" quantita="1"/>
<misura time="0001-01-01T00:00:00+01:00" quantita="-79228162514264337593543950335"/>
<misura time="9999-12-31T23:59:59.9999999+01:00" quantita="79228162514264337593543950335"/>
</misure>
</impianto>
I've create with $xml = simplexml_load_string($xmlpost); in my POST.php this array :
SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => id1
)
[misure] => SimpleXMLElement Object
(
[misura] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[time] => 2016-01-01T01:01:01
[quantita] => 1234
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[time] => 2016-01-01T01:01:01
[quantita] => 3456
)
)
)
)
)
And i have to put ID, TIME , AND VALUE in to Database Table with foreach
Please Help ! Thank You !
Consider using SimpleXML's xpath() with a for loop on each node position of <misura>:
$xml = simplexml_load_string($xmlpost);
$count = count($xml->xpath('//misura'));
for($i = 1; $i <= $count; $i++){
$id = $xml->xpath('/impianto/#id')[0];
$qty = $xml->xpath('//misura['.$i.']/#time')[0];
$value = $xml->xpath('//misura['.$i.']/#quantita')[0];
echo $id.' '.$qty.' '.$value."\n"; // PASS VALUES INO MYSQL
}
# id1 1900-01-01T01:01:01+01:00 1
# id1 0001-01-01T00:00:00+01:00 -79228162514264337593543950335
# id1 9999-12-31T23:59:59.9999999+01:00 79228162514264337593543950335

PHP - simplexml_load_string doesn't work as expected

When converting xml to object, everything seems fine according to print_r($result);. But if I use $result->title it returns object instead of string and when looping $result->documents it gets really strange..
$xml = '<return>
<id>65510</id>
<title>SMART</title>
<info/>
<documents>
<name>file_1.pdf</name>
<path>http://www.domain.com/documents/file_1.pdf</path>
</documents>
<documents>
<name>file_2.pdf</name>
<path>http://www.domain.com/documents/file_2.pdf</path>
</documents>
<documents>
<name>file_3.pdf</name>
<path>http://www.domain.com/documents/file_3.pdf</path>
</documents>
</return>';
$result = simplexml_load_string($xml);
print_r($result); /* returns:
SimpleXMLElement Object
(
[id] => 65510
[title] => SMART
[info] => SimpleXMLElement Object
(
)
[documents] => Array
(
[0] => SimpleXMLElement Object
(
[name] => file_1.pdf
[path] => http://www.domain.com/documents/file_1.pdf
)
[1] => SimpleXMLElement Object
(
[name] => file_2.pdf
[path] => http://www.domain.com/documents/file_2.pdf
)
[2] => SimpleXMLElement Object
(
[name] => file_3.pdf
[path] => http://www.domain.com/documents/file_3.pdf
)
)
)
*/
$_VALUE['title'] = $result->title;
print_r($_VALUE); /* returns:
Array
(
[title] => SimpleXMLElement Object
(
[0] => SMART
)
)
*/
foreach ($result->documents as $key=>$value) {
echo $key . "<br/>";
} /* returns:
documents
documents
documents
instead of returning:
1
2
3
*/
I need $result->title to return string and $result->documents to be an array with indexes 1,2,3.
There are difference between print_r and echo in this context. Instead Print try echo
echo (string) $result->title;
It will work and output as SMART
and array
$p = 1;
foreach ($result->documents as $value) {
echo $value->name . "<br/>";
//for key
echo $p++.'</br>';
}

PHP: SOAP response sort results

I'm trying to sort the results by ROOMPRICE of a soap response :
stdClass Object (
[GetHotelsResult] => stdClass Object (
[SEARCH_RESPONSE] => Array (
[0] => stdClass Object (
[HOTELNAME] => Hotel1
[ROOMNAME] => Room2
[ROOMPRICE] => 144.50
)
[1] => stdClass Object (
[HOTELNAME] => Hotel1
[ROOMNAME] => Room1
[ROOMPRICE] => 231.10
)
[2] => stdClass Object (
[HOTELNAME] => Hotel1
[ROOMNAME] => Room3
[ROOMPRICE] => 94.00
)
)
)
);
I've made many solutions, but they didn't work...
MY ACTUAL CODE:
$sClient = new SoapClient($wsdl, array('trace' => 1));
$response = $sClient->GetHotels($data);
$ghdata = $sClient->__getLastResponse();
$doc = new DOMDocument();
$doc->loadXML($ghdata);
$x = $doc->documentElement;
$rooms = $x->getElementsByTagName( "SEARCH_RESPONSE" );
foreach( $rooms as $SEARCH_RESPONSE )
{ // show results
Assuming $response is your outer stdClass object, I guess you're getting and error like that:
Warning: usort() expects parameter 1 to be array, object given in ...
This is because usort works with array and not objects. What you actually want to sort is a SEARCH_RESPONSE array. Also, pay attention that elements in this array are stdClass objects themselves, so you have to use $a->{$key} notation instead of []:
function build_sorter($key) {
return function ($a, $b) use ($key) {
// pay attention to `{$key}` notation
return strnatcmp($a->{$key}, $b->{$key});
};
}
// Get array to sort
usort($response->GetHotelsResult->SEARCH_RESPONSE, build_sorter('ROOMPRICE'));
foreach ($response->GetHotelsResult->SEARCH_RESPONSE as $item) {
echo $item->ROOMNAME . ', ' . $item->ROOMPRICE . "\n";
}

how to put a different objects inside each array element of an array in php?

I have two arrays, e.g
$mainArray = array('a','b','c','d','e','f','g');
$subArray = it contains an array of objects e.g
array( objec1, objec2, object3, object4) ...
within each of the objects, holds the value that matches one of the keys in the
$mainArray.
my Question now is, how am i gonna match and put the correct objects to the mainArray, so that
it should appear like this e.g
$mainArray = array('a'=> array(object3,object2), 'b' => array(object4,object1));
$result = array();
foreach ($subArray as $obj) {
if (!isset($result[$obj->keyOfMainArray])) {
$result[$obj->keyOfMainArray] = array();
}
$result[$obj->keyOfMainArray][] = $obj;
}
Assuming val is your object's property
$mainArray = array('a','b','c','d','e','f','g');
$subArray = array(...);
$result = array();
foreach($subArray as $object) {
$result[$object->val][] = $object;
}
Example result
Array
(
[a] => Array
(
[0] => stdClass Object
(
[val] => a
)
[1] => stdClass Object
(
[val] => a
)
)
[b] => Array
(
[0] => stdClass Object
(
[val] => b
)
)
)

how to access array objects differently and dynamically

there is a xml document that i'm parsing to array..
how can i access those array objects and save them in new variables..?
this is piece of php code that is parsing
$contents = file_get_contents('test.xml');
$xml = simplexml_load_string($contents);
print_r($xml);
here is the xml that is being parsed
<?xml version='1.0'?>
<document>
<txtmsg>
<smstel>1234567</smstel>
<smstxt></smstxt>
<smsdir>Send</smsdir>
<smstime>06/01/2010 7:54:48 am</smstime>
</txtmsg>
<txtmsg>
<smstel>33333333</smstel>
<smstxt>Test sms hhTes12222222</smstxt>
<smsdir>Send</smsdir>
<smstime>06/01/2010 7:54:48 am</smstime>
</txtmsg>
<Contacts>
<conttime>06/01/2010 8:19:05 am</conttime>
<cnt>
<fn>Abc</fn>
<ln>Def</ln>
<cnttel>123456</cnttel>
<cntmtel>3333333</cntmtel>
<cntemail>abc#hotmail.com</cntemail>
</cnt>
<cnt>
<fn>def</fn>
<ln>ghi</ln>
<cnttel>234234</cnttel>
<cntmtel>2424</cntmtel>
<cntemail>df#hotmail.com</cntemail>
</cnt>
</Contacts>
</document>
and this is output.
SimpleXMLElement Object ( [txtmsg] => Array ( [0] => SimpleXMLElement Object ( [smstel] => 1234567 [smstxt] => SimpleXMLElement Object ( ) [smsdir] => Send [smstime] => 06/01/2010 7:54:48 am ) [1] => SimpleXMLElement Object ( [smstel] => 33333333 [smstxt] => Test sms hhTes12222222 [smsdir] => Send [smstime] => 06/01/2010 7:54:48 am ) ) [Contacts] => SimpleXMLElement Object ( [conttime] => 06/01/2010 8:19:05 am [cnt] => Array ( [0] => SimpleXMLElement Object ( [fn] => Abc [ln] => Def [cnttel] => 123456 [cntmtel] => 3333333 [cntemail] => abc#hotmail.com ) [1] => SimpleXMLElement Object ( [fn] => def [ln] => ghi [cnttel] => 234234 [cntmtel] => 2424 [cntemail] => df#hotmail.com ) ) ) )
how can i access each element of xml individually.. like smstel,smstxt,smsdir etc
Maybe I'm over simplifying it, but a loop.
foreach($xml->txtmsg as $txtmsg) {
echo $txtmsg->smstel;
echo $txtmsg->smstxt;
// more elements...
}
Note: When using XML it helps to be aware of the schema. Meaning the above example is specific to those elements you mentioned. Nonetheless, it should help you get started.
this is the best way you can do that..
foreach($xml->txtmsg as $txtmsg) {
echo $txtmsg->smstel;
// more elements...
}
Easy
(string)$xml->txtmsg->smstel
Same goes for params and lists.. its either an object property, or an array
echo $xml->txtmsg[0]->smstel; // 1234567
echo $xml->txtmsg[1]->smstel; // 3333333
$smsTel = (string) $xml->txtmsg[0]->smstel; // 1234567
To literally convert the <txtmsg> sections to a multidimensional array, you could do:
$array = array();
foreach ($xml->txtmsg as $msg) {
$array[] = array (
'smstel' => (string) $msg->smstel,
'smstxt' => (string) $msg->smstxt,
'smsdir' => (string) $msg->smsdir,
'smstime' => (string) $msg->smstime
);
}
print_r($array);
/*
Array
(
[0] => Array
(
[smstel] => 1234567
[smstxt] =>
[smstel] => Send
[smstime] => 06/01/2010 7:54:48 am
)
[1] => Array
(
[smstel] => 33333333
[smstxt] => Test sms hhTes12222222
[smstel] => Send
[smstime] => 06/01/2010 7:54:48 am
)
)
*/
here is the code.
it will be convert you SimpleXML Object to Array
function convertXmlObjToArr($obj, &$arr)
{
$children = $obj->children();
foreach ($children as $elementName => $node)
{
$nextIdx = count($arr);
$arr[$nextIdx] = array();
$arr[$nextIdx]['#name'] = strtolower((string)$elementName);
$arr[$nextIdx]['#attributes'] = array();
$attributes = $node->attributes();
foreach ($attributes as $attributeName => $attributeValue)
{
$attribName = strtolower(trim((string)$attributeName));
$attribVal = trim((string)$attributeValue);
$arr[$nextIdx]['#attributes'][$attribName] = $attribVal;
}
$text = (string)$node;
$text = trim($text);
if (strlen($text) > 0)
{
$arr[$nextIdx]['#text'] = $text;
}
$arr[$nextIdx]['#children'] = array();
convertXmlObjToArr($node, $arr[$nextIdx]['#children']);
}
return;
}
you will get output in this format
Array
(
#name => books
#attributes => array ( )
#children => array
(
array
(
#name => novel
#attributes => array ( author => John Doe )
#children => array
(
array ( #name => title, #attributes => array ( ), #text => John's Novel )
)
)
)
)

Categories