Simplexml elements extracts only first element but i need all elements - php

i've this XML structure:
<response status="success">
<campaign>
<id>1</id>
<nameCampaign>Raccolta Punti CCN</nameCampaign>
<type>points</type>
<balances>
<balance>10.00 </balance>
</balances>
</campaign>
<campaign>
<id>6</id>
<nameCampaign>Abbonamenti</nameCampaign>
<type>subscription</type>
<balances>
<balance>6.00 Lampada solare</balance>
</balances>
<balances>
<balance>4.00 doccia solare</balance>
</balances>
<balances>
<balance>3.00 trifacciale</balance>
</balances>
</campaign>
</response>
And I need convert in array.
If i use
foreach($result->campaign as $bilancio) {
$balance[] = array ( 'nameCampaign' => (string)$bilancio->nameCampaign,
'balances' => (string)$bilancio->balances->balance );
} // foreach
I obtain this array
Array
(
[0] => Array
(
[nameCampaign] => Raccolta Punti CCN
[balances] => 10.00
)
[1] => Array
(
[nameCampaign] => Abbonamenti
[balances] => 6.00 Lampada solare
)
)
How could you note, id 6 has three sub-node (balances->balance) and not only one. How i could obtain a complete array?
Thank you to all and have a nice weekend!

Instead of reading (which will always give you the first element only with simeplxml), you iterate over all elements with foreach.
Here's a way:
$balance = array();
foreach ($result->campaign as $campaign)
{
$arr = array();
foreach ($campaign->balances as $campaignBalance)
{
$arr[] = (string) $campaignBalance->balance;
}
$balance[] = array(
'nameCampaign' => (string) $campaign->nameCampaign,
'balances' => $arr
);
}
print_r($balance);
Which will give you this result:
Array
(
[0] => Array
(
[nameCampaign] => Raccolta Punti CCN
[balances] => Array
(
[0] => 10.00
)
)
[1] => Array
(
[nameCampaign] => Abbonamenti
[balances] => Array
(
[0] => 6.00 Lampada solare
[1] => 4.00 doccia solare
[2] => 3.00 trifacciale
)
)
)

Related

Taking out just one value from an array

I have an array which is
Array ( [0] => Array ( [picture] => 5a55ed8d8a5c8910913.jpeg
[id] => 1284
[price_range] => Rs 12000 - 9000
[name] => Brown Beauty Office Chair )
[1] => Array ( [picture] => 5a55eefeb9a8e255836.jpeg
[id] => 1285
[price_range] => Rs 8989 - 7000
[name] => Chang Series Office Chair (Grey)
)
)
Now I am fetching the value of id on clicking a remove button, the value I fetch is 1284.
I want to take out just [id]=> 1284 from the above array and then display it using a foreach loop. How I can delete just the [id]=> 1284 without disturbing the other id values and other element.
In the above array I would like to delete one particular id value say just the [id]=> 1284 and keep all other elements intact and as it is.
Any help is welcome.
Use array_search and array_column, to find by id and remove by unset method,
<?php
$array = [
["id"=>123,"desc"=>"test1"],
["id"=>456,"desc"=>"test2"],
["id"=>789,"desc"=>"test3"],
];
$id = 456;
$index = array_search($id, array_column($array, 'id'));
unset($array[$index]);
print_r($array);
?>
Live Demo
Array
(
[0] => Array
(
[id] => 123
[desc] => test1
)
[2] => Array
(
[id] => 789
[desc] => test3
)
)
Since you asked how to achieve it using foreach, I came up with this.
$array = Array (Array ( 'picture' => '5a55ed8d8a5c8910913.jpeg','id' => 1284,'price_range' => 'Rs 12000 - 9000', 'name' => 'Brown Beauty Office Chair'),
Array ( 'picture' => '5a55eefeb9a8e255836.jpeg','id' => 1285,'price_range' => 'Rs 8989 - 7000','name' => 'Chang Series Office Chair (Grey)')
);
foreach($array as $key => $val) {
$id = $array[$key]['id'];
if($id === 1284){
unset($array[$key]['id']);
}
}
print_r($array)
?>
You can also use this too:
<?php
$element_to_remove = 1284;
$i = 0;
foreach($array as $this_arr){
$index = array_search($element_to_remove, $this_arr);
//unset($this_arr[$index]); this formate does not remove element from array
//but below works fine
if(isset($array[$i][$index])){
unset($array[$i][$index]);
}
}
print_r($array);
?>

Issue with DOM element GetElementByTagName in PHP

<FlightSegment DepartureDateTime="2016-09-20T06:05:00" ArrivalDateTime="2016-09-20T08:05:00" FlightNumber="716" ResBookDesigCode="N">
<FlightDuration>2016-09-14T02:00:00</FlightDuration>
<DepartureAirport LocationCode="IST" Terminal="I" />
<ArrivalAirport LocationCode="KBP" />
<OperatingAirline Code="PS" />
<Equipment AirEquipType="73H" />
<MarketingAirline Code="PS" />
<BookingClassAvails>
<BookingClassAvail ResBookDesigCode="N" ResBookDesigQuantity="9" RPH="ADT" AvailablePTC="ADT" ResBookDesigCabinCode="M" FareBasis="NL1LTP4" />
</BookingClassAvails>
</FlightSegment>
<FlightSegment DepartureDateTime="2016-09-20T09:50:00" ArrivalDateTime="2016-09-20T11:55:00" FlightNumber="101" ResBookDesigCode="N">
<FlightDuration>2016-09-14T03:05:00</FlightDuration>
<DepartureAirport LocationCode="KBP" />
<ArrivalAirport LocationCode="AMS" />
<OperatingAirline Code="PS" />
<Equipment AirEquipType="73R" />
<MarketingAirline Code="PS" />
<BookingClassAvails>
<BookingClassAvail ResBookDesigCode="N" ResBookDesigQuantity="9" RPH="ADT" AvailablePTC="ADT" ResBookDesigCabinCode="M" FareBasis="NL1LTP4" />
</BookingClassAvails>
</FlightSegment>
There are two Flight Segments.
We don`t have any identificators in this code, so,
How could I divide this code by blocks to use attributes from first <FlightSegment> block?
Also I need to count <FlightSegments>.
Please HELP! )
You could use this function to convert an XML node to a (nested) array:
function domToArray($node) {
$arr = [];
// Add all attributes of this node as key/values:
foreach ($node->attributes as $attribute) {
$arr[$attribute->nodeName] = $attribute->nodeValue;
}
// Iterate through the child nodes
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_TEXT_NODE) {
// Assign the text content to a "value" key
if (trim($child->textContent)!== '') {
$arr['value'] = $child->textContent;
}
} else if ($child->nodeType === XML_ELEMENT_NODE) {
// Create key/value pairs for child nodes, using recursion.
// If the children are repeated elements, then build
// an indexed array, otherwise an associative array.
if (preg_replace("/y$/", "ie", $child->nodeName) ."s" === $node->nodeName) {
$arr[] = domToArray($child);
} else {
$arr[$child->nodeName] = domToArray($child);
}
}
}
return $arr;
}
You would first have to create a DOMDocument and read the XML string into it. Note that the piece of XML you provided needs to be wrapped in a single element, which I have called FlightSegments on purpose -- the multiple of FlightSegment of which you have 2:
$doc = new DOMDocument();
$doc->loadXML("<FlightSegments>$xml</FlightSegments>");
Once you have that, you can call the function I mentioned above:
// Convert XML to nested array:
$flightSegments = domToArray($doc->documentElement);
Here is some of the output you can get from that array:
// Number of FlightSegments:
echo "Number of FlightSegment elements: " . count($flightSegments) . "<br>";
echo "DepartureDateTime of first FlightSegment: " . $flightSegments[0]['DepartureDateTime'] . "<br>";
echo "All information:<br>";
print_r ($flightSegments);
See it run on eval.in.
With the sample XML you provided, the output of the above code would be:
Number of FlightSegment elements: 2
DepartureDateTime of first FlightSegment: 2016-09-20T06:05:00
All information:
Array
(
[0] => Array
(
[DepartureDateTime] => 2016-09-20T06:05:00
[ArrivalDateTime] => 2016-09-20T08:05:00
[FlightNumber] => 716
[ResBookDesigCode] => N
[FlightDuration] => Array
(
[value] => 2016-09-14T02:00:00
)
[DepartureAirport] => Array
(
[LocationCode] => IST
[Terminal] => I
)
[ArrivalAirport] => Array
(
[LocationCode] => KBP
)
[OperatingAirline] => Array
(
[Code] => PS
)
[Equipment] => Array
(
[AirEquipType] => 73H
)
[MarketingAirline] => Array
(
[Code] => PS
)
[BookingClassAvails] => Array
(
[0] => Array
(
[ResBookDesigCode] => N
[ResBookDesigQuantity] => 9
[RPH] => ADT
[AvailablePTC] => ADT
[ResBookDesigCabinCode] => M
[FareBasis] => NL1LTP4
)
)
)
[1] => Array
(
[DepartureDateTime] => 2016-09-20T09:50:00
[ArrivalDateTime] => 2016-09-20T11:55:00
[FlightNumber] => 101
[ResBookDesigCode] => N
[FlightDuration] => Array
(
[value] => 2016-09-14T03:05:00
)
[DepartureAirport] => Array
(
[LocationCode] => KBP
)
[ArrivalAirport] => Array
(
[LocationCode] => AMS
)
[OperatingAirline] => Array
(
[Code] => PS
)
[Equipment] => Array
(
[AirEquipType] => 73R
)
[MarketingAirline] => Array
(
[Code] => PS
)
[BookingClassAvails] => Array
(
[0] => Array
(
[ResBookDesigCode] => N
[ResBookDesigQuantity] => 9
[RPH] => ADT
[AvailablePTC] => ADT
[ResBookDesigCabinCode] => M
[FareBasis] => NL1LTP4
)
)
)
)
Edit after you provided complete XML
I am not sure what your problem is any more, because in comments you shared code where you walk through your XML successfully.
Just to note that you can use the above function to turn the complete XML into an array (I made one correction to the function to correctly identify the plural of a tag name that ends with "y").
Here is how you would call it on your XML:
$soap = domToArray($xmlDoc->documentElement);
The content of $soap would be (I truncated it):
Array
(
[soap:Body] => Array
(
[SearchFlightResponse] => Array
(
[OTA_AirLowFareSearchRS] => Array
(
[Version] => 0
[HasMoreResult] => Array
(
[value] => false
)
[Success] => Array
(
)
[PricedItineraries] => Array
(
[0] => Array
(
[Currency] => USD
[ProviderType] => AmadeusProvider
[SequenceNumber] => 0
[AirItinerary] => Array
(
[OriginDestinationOptions] => Array
(
[0] => Array
(
[RefNumber] => 0
[DirectionId] => 0
[ElapsedTime] => 0650
[FlightSegment] => Array
(
[DepartureDateTime] => 2016-09-20T09:50:00
[ArrivalDateTime] => 2016-09-20T11:55:00
[FlightNumber] => 101
[ResBookDesigCode] => N
[FlightDuration] => Array
(
[value] => 2016-09-14T03:05:00
)
[DepartureAirport] => Array
(
[LocationCode] => KBP
)
[ArrivalAirport] => Array
(
[LocationCode] => AMS
)
[OperatingAirline] => Array
(
[Code] => PS
)
[Equipment] => Array
(
[AirEquipType] => 73R
)
[MarketingAirline] => Array
(
[Code] => PS
)
[BookingClassAvails] => Array
(
[0] => Array
(
[ResBookDesigCode] => N
[ResBookDesigQuantity] => 9
[RPH] => ADT
[AvailablePTC] => ADT
[ResBookDesigCabinCode] => M
[FareBasis] => NL1LTP4
)
)
Now you can write code like:
$itineries = $soap['soap:Body']['SearchFlightResponse']['OTA_AirLowFareSearchRS']['PricedItineraries'];
foreach ($itineries as $itinery) {
// ... etc. Always array access.
}
now your function creates the massive from the last segment of xml document:
<?php
function domToArray($node) {
$arr = [];
// Add all attributes of this node as key/values:
foreach ($node->attributes as $attribute) {
$arr[$attribute->nodeName] = $attribute->nodeValue;
}
$useName = true;
// Iterate through the child nodes
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_TEXT_NODE) {
// Assign the text content to a "value" key
if (trim($child->textContent)!== '') {
$arr['value'] = $child->textContent;
}
} else if ($child->nodeType === XML_ELEMENT_NODE) {
// Create key/value pairs for child nodes, using recursion.
// If the children are repeated elements, then build
// an indexed array, otherwise an associative array.
if ($child->nodeName ."s" === $node->nodeName) {
$arr[] = domToArray($child);
} else {
$arr[$child->nodeName] = domToArray($child);
}
}
}
return $arr;
}
$xmlDoc = new DOMDocument();
$xmlDoc->load("response.xml");
$soap = domToArray($xmlDoc->documentElement);
print_r($soap);
?>
Here you can see all document entirely: response.xml
And here is what contains $soap: Array
Your decision was ideal:
// If the children are repeated elements, then build
// an indexed array, otherwise an associative array.
...but is doesn't build an indexed array when I'm trying to load an response.xml. It just build massive with last FlightSegment...
P.S. I`m not same person, we just working together. )

Parsing array values into multidimensional array

I have some data I retrieve from a JSON feed that currently is being parsed into an array like this: (simplifying for demonstration purposes)
So pretty much an array returns a movie theater name, with the showtimes associated with that particular theater.
[0] => American Theater
[1] => 2014-06-04T13:10
[2] => 2014-06-04T15:10
[3] => Grand Theater
[4] => 2014-06-04T15:30
[5] => 2014-06-04T19:10
How would I parse this array to be multidimensional, for instance:
Array
(
[0] => Array
(
[theater] => Array
(
[name] => American Theater
)
[showtimes] => Array
(
[1] => 2014-06-04T13:10
[2] => 2014-06-04T15:10
)
)
[1] => Array
(
[theater] => Array
(
[name] => Grand Theater
)
[showtimes] => Array
(
[1] => 2014-06-04T15:30
[2] => 2014-06-04T19:10
)
)
)
I'm assuming you're trying to access some api and have no control over how the data is passed back to you? If you do then the API should be responsible for returning a sensible schema.
But if you're forced to work with this array and the amount of showtimes are unknown to you, then you can do something like this:
$array = array(
'American Theater',
'2014-06-04T13:10',
'2014-06-04T15:10',
'Grand Theater',
'2014-06-04T15:30',
'2014-06-04T19:10'
);
$i = 0;
foreach ($array as $key => $value) {
if (strtotime($value)) {
$theaters[$i - 1]['showtimes'][] = $value;
}
else {
$theaters[$i]['theater']['name'] = $value;
$i++;
}
}
Outcome
To walk you through it, $array is whatever the returned dataset is. We set an index in the $i value and want to only increment it if we determine we've detected a theater name. Within the loop we first try to determine if the string can be converted to a php time value. If it cannot we add the theater name to our new schema structure, and increment our index value. Since times are always added to theater names, we are expecting the first index number to always be one higher than what we want to add the showtime to.
This will fail to be accurate in cases when a theater name is convertible to a time value in such cases like Next Month. There are a couple of other ways to solve this with regex or by inspecting the string for certain characters and their position since the time format will remain the same.
You could replace the strtotime() with:
$str = str_split($value);
if (($str[4] && $str[7]) == '-' && $str[10] == 'T' && $str[13] == ':' ) {
$theaters[$i - 1]['showtimes'][] = $value;
}
If you want such structure, you need to create a new copy of it. You may also need to chunk/group them by three's using array_chunk first, and then, from there, you can loop it now and start creating the desired format.
Consider this example:
$old_values = array('American Theater', '2014-06-04T13:10', '2014-06-04T15:10', 'Grand Theater', '2014-06-04T15:30', '2014-06-04T19:10');
$old_values = array_chunk($old_values, 3);
$new_values = array();
foreach($old_values as $key => $value) {
$new_values[] = array(
'theater' => array('name' => $value[0]),
'showtimes' => array(1 => $value[1], 2 => $value[2]),
);
}
Edit: As mentioned, one theater can have many showtimes, therefore this current solution will fail. This may be an alternative (you may need to check each element if its a theater name or a date). Consider this example:
$old_values = array(
'American Theater',
'2014-06-04T13:10',
'2014-06-04T15:10',
'Grand Theater',
'2014-06-04T15:30',
'2014-06-04T19:10',
'Magic Johnson Theater',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
'Mall of America Theater',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
);
$new_values = array();
$current_key = 0;
foreach($old_values as $key => $value) {
$current_value = $value;
$pieces = explode('T', $current_value);
$dates = explode('-', $pieces[0]);
if(count($dates) == 3) {
$new_values[$current_key]['showtimes'][] = $current_value;
} else {
$current_key++;
$new_values[$current_key]['theater']['name'] = $current_value;
}
}
Sample Output:
Array
(
[1] => Array
(
[theater] => Array
(
[name] => American Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T13:10
[1] => 2014-06-04T15:10
)
)
[2] => Array
(
[theater] => Array
(
[name] => Grand Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T15:30
[1] => 2014-06-04T19:10
)
)
[3] => Array
(
[theater] => Array
(
[name] => Magic Johnson Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T19:10
[1] => 2014-06-04T19:10
[2] => 2014-06-04T19:10
)
)
[4] => Array
(
[theater] => Array
(
[name] => Mall of America Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T19:10
[1] => 2014-06-04T19:10
[2] => 2014-06-04T19:10
[3] => 2014-06-04T19:10
)
)
)
Sample Fiddle

How to iterate over a multidimensional array?

I have array like this. This array is created dynamically
Array
(
[Data NotUploading] => Array
(
[items] => Array
(
[0] => Array
(
[date] => 2013-04-02
[issue_id] => 1
[phone_service_device] => A
[phone_service_model] =>
[phone_service_os] =>
[phone_service_version] =>
[issue_name] => Data NotUploading
)
[1] => Array
(
[date] => 2013-04-02
[issue_id] => 1
[phone_service_device] => I
[phone_service_model] =>
[phone_service_os] =>
[phone_service_version] =>
[issue_name] => Data NotUploading
)
)
)
[Battery Problem] => Array
(
[items] => Array
(
[0] => Array
(
[date] => 2013-04-03
[issue_id] => 3
[phone_service_device] => I
[phone_service_model] =>
[phone_service_os] =>
[phone_service_version] =>
[issue_name] => Battery Problem
)
)
)
)
What I need to do is to use 2 foreach or 1 foreach & 1 for loop so that I can get each value of date I did like this
foreach($gResultbyName as $key1 => $rec){
for($j = 0;$j<count($rec);$j++ ){
echo $rec['items'][$j]['date'];
}
}
but its only retrieving 2013-04-02 & 2013-04-03 that is 0 index date of data NotUploading & 0 index date of Battery Problem. Basically I need to compare each value and others stuff but I just cant get each date value.
Forgive me for ignorance but I tried a lot :(
try this:
foreach ($data as $d)
{
foreach($d['items'] as $item)
{
echo $item['date'];
}
}
Your for-loop loops count($rec) times, but should count($rec['items']).
This should load the dates into an array sorted by the issue_name. The you can step through them for further processing.
$dates= array();
foreach ($gResultbyName AS $events){
foreach ($events['items'] AS $item){
$dates[$item['issue_name']][] = $item['date'];
}
}
var_dump($dates);

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