XML parsing is not working when it's only one array - php

I am parsing the xml like following:
$result = '
<sms>
<status>0</status>
<message>
<contact_lists>
<contact_list><cl_id>11111</cl_id><phone>999999999</phone><name>Neu</name></contact_list>
<contact_list><cl_id>222222</cl_id><phone>888888888</phone><name>Alt</name></contact_list>
</contact_lists>
</message>
</sms>';
$xml = simplexml_load_string($result, "SimpleXMLElement", LIBXML_NOCDATA);
$json = json_encode($xml);
$array = json_decode($json,true);
$contact_lists = $array['contact_lists']['contact_list'];
A sometimes the array look like this, which is works.
Array ( [status] => 0 [message] => Array ( ) [contact_lists] => Array ( [contact_list] => Array ( [0] => Array ( [cl_id] => 11111 [phone] => 999999999 [name] => Neu ) [1] => Array ( [cl_id] => 222222 [phone] => 888888888 [name] => Alt ) ) ) )
B but sometime if the array has only one contact_list, it will look like following
Array ( [status] => 0 [message] => Array ( ) [contact_lists] => Array ( [contact_list] => Array ( [cl_id] => 11111 [phone] => 999999999 [name] => Neu ) ) )
when i use $contact_listsin foreach loop it works with A since there are multiple array keys like 0,1,2,etc... but with B it shows error Warning: Illegal string offset 'name' etc.. since there are no array key like 0,1,2,etc...
so parsing the xml is automatically removing the key numbering which causing the the issue.
1- is there a way to keep the key numbering if only one array?
2- tried to use if (count($contact_lists) >= 1) { , but its not working as well..
Any idea for a workaround to solve such issue ?
SOLUTION:
$contact_lists_found = isset($array['contact_lists']['contact_list']) ? $array['contact_lists']['contact_list'] : '';
if ($contact_lists_found !== '' ) {
if (array_key_exists('0', $contact_lists_found)) {
// more than contact list
$contact_lists = $array['contact_lists']['contact_list'];
} else {
// only one contact list
$contact_lists[0] = $array['contact_lists']['contact_list'];
}
} else {
$contact_lists = array();
}

You could just check, if the key 0 is set, and if not, then simply overwrite the element contact_list with itself wrapped into an array:
if(!isset($array['message']['contact_lists']['contact_list'][0])) {
$array['message']['contact_lists']['contact_list'] = [
$array['message']['contact_lists']['contact_list']
];
}
0 is not a valid tag name in XML, so you should never get that, unless there was more than one <contact_list> in the XML.

Related

remove empty Arrays from multidimensional Array generated with simplexml

I have an xml file with the following structure:
<categories>
<category>
<id>3</id>
<title><![CDATA[Testname]]></title>
<text><![CDATA[]]></text>
<keywords><![CDATA[]]></keywords>
<description><![CDATA[]]></description>
</category>
</categories>
Now I'm loading this file and creating an array of it:
$xmlData = simplexml_load_file( 'categories.xml', null, LIBXML_NOCDATA);
$array = json_decode(json_encode($xmlData), true);
That generates me the following Result (print_r Output):
Array
(
[#attributes] => Array
(
[version] => 1.0
)
[categories] => Array
(
[category] => Array
(
[0] => Array
(
[id] => 3
[title] => Testname
[text] => Array
(
)
[keywords] => Array
(
)
[description] => Array
(
)
)
)
)
)
Here is my question, how could I remove those empty arrays? I tried it with array Filter, but this didn't work. (I need the keys, but they should be empty)
I know there would be a way, in my next step where I'm renaming the array keys as needed, i could check for empty arrays in the foreach loop, but I think there is an easier way, because every field (except id) could be empty in the xml file.
foreach($array['categories']['category'] as $key => $category){
$results[$key]['id'] = $category['id'];
$results[$key]['headline'] = $category['title'];
$results[$key]['content'] = $category['text'];
$results[$key]['metaKeywords'] = $category['keywords'];
$results[$key]['metaDescription'] = $category['description'];
}
Does someone has an idea, what i could do after the json_decode? Or is there an easier way for all I'm trying to accomplish here?
Thanks!
Every time I see someone use that json_decode(json_encode()) hack, it makes me sad. You don't need to turn the SimpleXML object into an array to loop over it, just read the usage examples in the manual.
If you loop over the SimpleXML object directly, you will never get those arrays, so will never need to remove them:
$xmlData = simplexml_load_file('categories.xml'); // LIBXML_NOCDATA is NOT needed
foreach($xmlData->categories->category as $key => $category){
$results[$key]['id'] = (string)$category->id;
$results[$key]['headline'] = (string)$category->title;
$results[$key]['content'] = (string)$category->text;
$results[$key]['metaKeywords'] = (string)$category->keywords;
$results[$key]['metaDescription'] = (string)$category->description;
}
The (string) tells SimpleXML you want the text content of a particular element (including CDATA), and will give you an empty string for the empty elements.
Hope this will work. PHP code demo
<?php
$result=Array
(
"categories" => Array
(
"category" => Array
(
0 => Array
(
"id" => 3,
"title" => "Testname",
"text" => Array
(
),
"keywords" => Array
(
),
"description" => Array
(
)
)
)
)
);
$results=array();
foreach($result['categories']['category'] as $key => $category){
$results[$key]['id'] = $category['id'];
$results[$key]['headline'] = $category['title'];
$results[$key]['content'] = is_array($category['text']) && count($category['text'])>0 ? $category['text'] : false;
$results[$key]['metaKeywords'] = is_array($category['keywords']) && count($category['keywords'])>0 ? $category['keywords'] : false;
$results[$key]['metaDescription'] = is_array($category['description']) && count($category['description'])>0 ? $category['description'] : false;
$results[$key]=array_filter($results[$key]);
}
print_r($results);

XML to one level php array

I want to convert this xml output:
<?xml version="1.0" encoding="UTF-8"?>
<levela xmlns="https://restapi" version="1.0.0">
<levelb>
<levelc>
<var1>01</var1>
<var2>String1</var2>
</levelc>
<levelc>
<var1>02</var1>
<var2>String2</var2>
</levelc>
<levelc>
<var1>08</var1>
<var2>String3</var2>
</levelc>
</levelb>
</levela>
to this php array:
array(
'01' => 'String1',
'02' => 'String2',
'08' => 'String3'
)
I tried in many ways, but it's more difficult than I thought (for me). I hope someone can help me. Many thanks in advance!
It's an easy task with SimpleXML:
Load the XML into a SimpleXML object:
$xml = simplexml_load_string( $string );
Perform a foreach() loop through all <issuer> nodes and add <issuername> child node text value to your array using <issuerid> as key:
$result = array();
foreach( $xml->directory->issuer as $node )
{
$result[ $node->issuerid->__toString() ] = $node->issuername->__toString();
}
print_r( $result );
The output is:
Array
(
[01] => ABN Amro Bank
[02] => ASN Bank
[08] => Friesland Bank
)
SimpleXML return an object, so you need to cast as string node values with ->toString() method to add it as string.
Read more about SimpleXML
You can use the follwong little trick to first get an array.
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
The result of this will be an array representing exactly the XML structure, like that :
Array
(
[#attributes] => Array
(
[version] => 1.0.0
)
[directory] => Array
(
[issuer] => Array
(
[0] => Array
(
[issuerid] => 01
[issuername] => ABN Amro Bank
)
[1] => Array
(
[issuerid] => 02
[issuername] => ASN Bank
)
[2] => Array
(
[issuerid] => 08
[issuername] => Friesland Bank
)
)
)
)
With just a little bit of work, you will be able to build the array you want.

In PHP how can I read subvalue of an XML line? [duplicate]

Sorry if this seems like an easy question, but I've started pulling hair out on this...
I have a XML file which looks like this...
<VAR VarNum="90">
<option>1</option>
</VAR>
I'm trying to get the VarNum.
So far I've been successful using the follow code to get the other information:
$xml=simplexml_load_file($file);
$option=$xml->option;
I just can't get VarNum (the attribute value I think?)
Thanks!
You should be able to get this using SimpleXMLElement::attributes()
Try this:
$xml=simplexml_load_file($file);
foreach($xml->Var[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
That will show you all the name/value attributes for the first foo element. It's an associative array, so you can do this as well:
$attr = $xml->Var[0]->attributes();
echo $attr['VarNum'];
What about using $xml['VarNum'] ?
Like this :
$str = <<<XML
<VAR VarNum="90">
<option>1</option>
</VAR>
XML;
$xml=simplexml_load_string($str);
$option=$xml->option;
var_dump((string)$xml['VarNum']);
(I've used simplexml_load_string because I've pasted your XML into a string, instead of creating a file ; what you are doing with simplexml_load_file is fine, in your case !)
Will get you
string '90' (length=2)
With simpleXML, you access attributes with an array syntax.
And you have to cast to a string to get the value, and not and instance of SimpleXMLElement
For instance, see example #5 of Basic usage in the manual :-)
[0] => Array
(
[#attributes] => Array
(
[uri] => https://abcd.com:1234/abc/cst/2/
[id] => 2
)
[name] => Array
(
[first] => abcd
[last] => efg
)
[company] => abc SOLUTION
[email] => abc#xyz.com
[homepage] => WWW.abcxyz.COM
[phone_numbers] => Array
(
[phone_number] => Array
(
[0] => Array
(
[main] => true
[type] => work
[list_order] => 1
[number] => +919876543210
)
[1] => Array
(
[main] => false
[type] => mobile
[list_order] => 2
[number] => +919876543210
)
)
)
[photo] => Array
(
[#attributes] => Array
(
[uri] => https://abcd.com:1234/abc/cst/2/cust_photo/
)
)
)
I applied the below code
$xml = simplexml_load_string($response);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
print_r($array);
but it is not use full i want all the data in single array in php
Try this
$xml->attributes()['YourPropertyName']; //check property case also

Extract specific values from JSON Array php

I have a JSON Array
[0] => Array
(
[stage_id] => 80
[yieldVal] => Array
(
[0] => Array
(
[datajson] => [{"name":"doi","value":"215"},{"name":"dateofpollinationstops","value":"Date of Pollination Stops~23-3-2015"}]
)
[1] => Array
(
[datajson] => [{"name":"doi","value":"698"},{"name":"dateofpollinationstops","value":"Date of Pollination Stops~23-3-2015"}]
)
)
)
I need to extract the values from this Array
[0] => Array
(
[stage_id] => 80
[yieldVal] => Array
(
[doi_value] => 215
[doi_value] => 698
)
)
I have tried decoding the JSON. But unable to continue further.
$phpArray = json_decode($res['datajson'], true);
How to extract the values and assign the key.
EDIT : My final output should be
[0] => Array
(
[stage_id] => 80
[yieldVal] => 913 //215+698 -> Extracting values from [datajson]
)
One thing that may of tripped you up is that your datajson string is:
`[{"name":"doi","value":"215"},{"name":"dateofpollinationstops","value":"Date of Pollination Stops~23-3-2015"}]`
The square brackets mean that json_decode will create an array from the objects.
Anyway, try this...should give you the exact output you asked for:
$yieldVal = 0;
foreach ($res['yieldVal'] as $key => $arr) {
$decode = json_decode($arr['datajson']);
$yieldVal = $yieldVal + $decode[0]->value;
}
$newArray = array (
'stage_id' => $res['stage_id'],
'yieldVal' => $yieldVal
);
//var_dump($newArray);
echo "<pre>".print_r($newArray, true)."</pre>";
You should be able to get the value with:
$doi_value = $phpArray[0]['value'];
You can then sum them, push them onto a resulting array, or whatever.

Pull data from PHP array based on a given infromation

I am trying to pull ImageUrl's, Lat and Long from a php array where I provide the HotelCode: $hotelCode
My XML file looks like the code below:
<Hotels>
<Hotel>
<HotelCode>Code<HotelCode>
<Latitude>Lat</Latitude>
<Longitude>Long</Longitude>
<HotelImages>
<ImageURL>file.jpg</ImageURL>
<ImageURL>file2.jpg</ImageURL>
....
</HotelImages>
</Hotel>
....
</Hotels>
My PHP code is :
$xmlstring = file_get_contents($xmlurl);
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$hotels = json_decode($json,TRUE);
print_r($hotels) is:
Array (
[Hotel] => Array (
[0] => Array (
[HotelCode] => ES002A
[comment] => Array (
[0] => Array ( ) )
[Latitude] => 37.396792
[Longitude] => -5.992054
[HotelImages] => Array (
[ImageURL] => Array (
[0] => http://image.metglobal.com/hotelimages/ES002A/9405329_0x0.jpg
[1] => http://image.metglobal.com/hotelimages/ES002A/9405330_0x0.jpg
[2] => http://image.metglobal.com/hotelimages/ES002A/9405331_0x0.jpg
)
)
)
print_r($hotelCodes) is
Array ( [0] => ESG56G [1] => ES0Z10 )
I have tried some diferent methods but none of them worked.
Well, first off you have an error in your xml.
<HotelCode>Code<HotelCode>
Should be:
<HotelCode>Code</HotelCode>
After that you can get the images with:
$hotels['Hotel']['HotelImages']['ImageURL'][0];
and
$hotels['Hotel']['HotelImages']['ImageURL'][0];
And the lat long respectivly:
$hotels['Hotel']['Latitude'];
$hotels['Hotel']['Longitude'];
You can loop around the [Hotel] array with a foreach and check if the [HotelCode] element is equal to the one you provided and return the lat and long properties after that.
foreach ($hotels as $hotel) {
if($hotel['HotelCode'] == 'YourCode'){
echo $hotel['Latitude'];
echo $hotel['Longtitude'];
}
}
Use array_keys
$hotelCodes = array_keys($hotels, "HotelCode");
This will return all values with key "HotelCode". Then you can loop the array with these values.
foreach ($hotelCodes as $code)
{
$iUrls = $hotels[$code]['HotelImages']['ImageURL'];
foreach ($iUrls as $iUrl)
{
echo $iUrl;
}
echo $hotels[$code]['Latitude'];
echo $hotels[$code]['Longitude'];
}

Categories