XML to one level php array - php

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.

Related

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

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.

Pull values from SimpleXMLElement Object

I'm using the namecheap API to do some stuff, it's the first time I've used a API and I'm running into a bit of a problem.
This is what I have so far:
$ApiKey = "**********************";
$ApiUser = "*****";
$UserName = "*********";
$ClientIP = "********";
$NamecheapURI = "https://api.namecheap.com/xml.response";
$executionURL = $NamecheapURI."?ApiUser=".$ApiUser."&ApiKey=".$ApiKey."&UserName=".$UserName."&Command=namecheap.domains.check&ClientIp=".$ClientIP."&DomainList=".$domain;
$xml = simplexml_load_file($executionURL);
print_r($xml);
When print $xml I am returned simple XML objects:
SimpleXMLElement Object
(
[#attributes] => Array
(
[Status] => OK
)
[Errors] => SimpleXMLElement Object
(
)
[Warnings] => SimpleXMLElement Object
(
)
[RequestedCommand] => namecheap.domains.check
[CommandResponse] => SimpleXMLElement Object
(
[#attributes] => Array
(
[Type] => namecheap.domains.check
)
[DomainCheckResult] => SimpleXMLElement Object
(
[#attributes] => Array
(
[Domain] => facebook.com
[Available] => false
[ErrorNo] => 0
[Description] =>
[IsPremiumName] => false
[PremiumRegistrationPrice] => 0
[PremiumRenewalPrice] => 0
[PremiumRestorePrice] => 0
[PremiumTransferPrice] => 0
[IcannFee] => 0
[EapFee] => 0
)
)
)
[Server] => PHX01APIEXT03
[GMTTimeDifference] => --5:00
[ExecutionTime] => 0.008
)
My question is beyond this, how do I move forward and pull data from this?
I've tried treating this as an array but I am getting nowhere, when using is_array() to test if it was an array it says it's not which I don't understand...
I apologise if this is a noob question, I am a bit new to this. In short, what do I need to do to pull data from this?
Thanks in advance!
Learning to use SimpleXML is much better than trying to convert it to arrays/json/anything else and simple (hence the name). A quick example...
$response = '<?xml version="1.0" encoding="UTF-8"?>
<CommandResponse Type="namecheap.domains.check">
<DomainCheckResult Domain="facebook.com">
<Element>1234</Element>
<Element>12345</Element>
</DomainCheckResult>
</CommandResponse>';
$xml = simplexml_load_string($response);
echo "DOmain=".$xml->DomainCheckResult['Domain'].PHP_EOL;
foreach ( $xml->DomainCheckResult->Element as $value) {
echo "Value=".(string)$value.PHP_EOL;
}
outputs...
DOmain=facebook.com
Value=1234
Value=12345
You have to adapt this to your own XML, but the idea is that if you want to access an element of an item you use object notation -> and if you need to get an attribute, use array notation [].
So in the above code, the first echo ($xml->DomainCheckResult['Domain']) gets the <DomainCheckResult> element and outputs the Domain attribute.
Then the foreach loop says fetch each <Element> within <DomainCheckResult> and output the value.

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

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

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