xml2array() - XML Parser for PHP
xml2array() is a easy to use PHP function that will convert the given XML text to an array in the XML structure. Kind of like my Javascript xml2array() function.
Demo
See a Sample - the output of this function.
See a demo.
Code
<?php
/**
* xml2array() will convert the given XML text to an array in the XML structure.
* Link: http://www.bin-co.com/php/scripts/xml2array/
* Arguments : $contents - The XML text
* $get_attributes - 1 or 0. If this is 1 the function will get the attributes as well as the tag values - this results in a different array structure in the return value.
* Return: The parsed XML in an array form.
*/
function xml2array($contents, $get_attributes=1) {
if(!$contents) return array();
if(!function_exists('xml_parser_create')) {
//print "'xml_parser_create()' function not found!";
return array();
}
//Get the XML parser of PHP - PHP must have this module for the parser to work
$parser = xml_parser_create();
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
xml_parse_into_struct( $parser, $contents, $xml_values );
xml_parser_free( $parser );
if(!$xml_values) return;//Hmm...
//Initializations
$xml_array = array();
$parents = array();
$opened_tags = array();
$arr = array();
$current = &$xml_array;
//Go through the tags.
foreach($xml_values as $data) {
unset($attributes,$value);//Remove existing values, or there will be trouble
//This command will extract these variables into the foreach scope
// tag(string), type(string), level(int), attributes(array).
extract($data);//We could use the array by itself, but this cooler.
$result = '';
if($get_attributes) {//The second argument of the function decides this.
$result = array();
if(isset($value)) $result['value'] = $value;
//Set the attributes too.
if(isset($attributes)) {
foreach($attributes as $attr => $val) {
if($get_attributes == 1) $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
/** :TODO: should we change the key name to '_attr'? Someone may use the tagname 'attr'. Same goes for 'value' too */
}
}
} elseif(isset($value)) {
$result = $value;
}
//See tag status and do the needed.
if($type == "open") {//The starting of the tag '<tag>'
$parent[$level-1] = &$current;
if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
$current[$tag] = $result;
$current = &$current[$tag];
} else { //There was another element with the same tag name
if(isset($current[$tag][0])) {
array_push($current[$tag], $result);
} else {
$current[$tag] = array($current[$tag],$result);
}
$last = count($current[$tag]) - 1;
$current = &$current[$tag][$last];
}
} elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
//See if the key is already taken.
if(!isset($current[$tag])) { //New Key
$current[$tag] = $result;
} else { //If taken, put all things inside a list(array)
if((is_array($current[$tag]) and $get_attributes == 0)//If it is already an array...
or (isset($current[$tag][0]) and is_array($current[$tag][0]) and $get_attributes == 1)) {
array_push($current[$tag],$result); // ...push the new element into that array.
} else { //If it is not an array...
$current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
}
}
} elseif($type == 'close') { //End of tag '</tag>'
$current = &$parent[$level-1];
}
}
return($xml_array);
}

Comments
I'm very impressed.
I was wondering what's the license of the function? I'd like to use it for GPL projects, is that okay?
Thanks!
anywhere.
$contents = file_get_contents('sample.xml');//Or however you what it
$result = xml2array($contents);
so if one of my arrays is called say LAT and has a value of 100 how do I reference
it in my php? say echo $LAT[0];
//print_r($result);
Thanks
and <li> and and they are not giving back the way I would want it. Is there a solution for this ??
example node:
<Tekst>
xxxxx.</li>

<li>yyyyy.</li>
<li>vvvvv.</li>
<li>qqqqq.</li>
zzzzz.
</Tekst>
$contents,0 gives : Array ( [p] => xxxxx. )
$contents gives : Array ( [p] => Array ( [value] => xxxxx. [attr] => Array ( [align] => justify ) ) )
Sorry about the confusion. If you have any more doubts(I am sure you will - the code is complicated, don't hesitate to email me. My email is binnyva, gmail.
the following xml, the message array contains 2 elements
<messageList>
<message>
<from>2</from>
<to>1</to>
<text>adf</text>
</message>
<message>
<from>3</from>
<to>4</to>
<text>bla adf</text>
</message>
</messageList>
in this case the message array contains 4 elements.
<messageList>
<message>
<from>2</from>
<to>1</to>
<text>adf</text>
</message>
</messageList>
There's isn't an easy way to determine how many messages are being passed.
} elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
//See if the key is already taken.
if(!isset($current[$tag])) { //New Key
$current[$tag] = array($result);
// last line just creates first element already in the array.
// enjoy!
if(isset($value)) $result['value'] = utf8_decode($value);
great piece of coding!
I just have a quick question, how would i go about putting the resulting data into a mysql database?
I am a real newbie and cant for the life of me see/understand how to do it.
However, I am looking for a result which is somewhere in between of the 2 modes results this function is producing. I would like the attribute value of a tag to be included like the other tags inside the attributed tag in the result array, but without everything being array values. Is there a simple way of doing this?
like this: xml: <home id="1045">
In the result array it should look like: home[id], home[price], home[available] etc.
Best function i found in the net..
Greetz from Germany and thanks a lot!
I'm planning to use this for an API module i'm writing.
If it's ok by you, i'm gonna publish it with this parser.
Greets, GrwN
but just i wants to know that how to extract the array results and store that value in a variable like $xyz.so on...
Just i wants to enter that variable in my database after retriving these values from the xml file.
this parser works really well,
but i have a problem under php 5.2.4 that return
"Fatal error: Cannot use string
offset as an array in"
This is my code:
$parsedBis = xml2array($xmlfileBis,0);
print_r($parsedBis);
output:
Array
(
[products] => Array
(
[categories] =>
)
)
Fatal error: Cannot use string offset as an array in /prod/doc/site/products/index.php on line 18
PS
under php 5.1.6 and php 4 it works correctly
To get the results you can use:
print_r ($array['rss']['channel']['item'][$i]['title']['value']);
if you look into an RSS feed from a weblog you can find the same dropdown structure. You can then adapt it to your needs!
Cheers Binny! Thanks!
I'm using the eBay APIs which may return one or more elements. The XML structure is the same regardless of the number of entries.
Also I suggest adding a version number to the header comments.
Single entry:
Array
(
[Item] => Array
(
[ItemID] => Array
(
[value] => 150216600790
)
Multiple entries:
Array
(
[Item] => Array
(
[0] => Array
(
[ItemID] => Array
(
[value] => 150216600790
)
// Mikael from Sweden
thanks
Example:
XML CODE
<general>
<context>default</context>
<srvlookup>yes</srvlookup>
</general>
What I want is to parse the tags and their contents so I can write it into a text file. Example:
[general]
context=default
srvlookup=yes
I get the value with: echo $array['general']['context']['value'];
Any idea on how to get the tag's name? Thank you.
while (list($i) = each ($result)) {
while (list($j) = each ($result[$i])){
echo "[".$j."]
";
while (list($k) = each ($result[$i][$j])){
echo $k."=";
while(list($h) = each ($result[$i][$j][$k])){
echo $result[$i][$j][$k][$h]."
";
}
}
echo "
";
}
}
Can anyone give me a hint, how to read the values IN trkpt....
Thanks....
“<?xml version="1.0" encoding="UTF-8" standalone="no" ?>”
<gpx
xmlns="http://www.topografix.com/GPX/1/1"
<metadata>
</metadata>
<trk>
<name>Huidig nummer: 26 APR 2008 08:12
</name>
<trkseg>
<trkpt lat="52.219812" lon="5.996262">
<ele>11.19</ele>
<time>2008-04-26T06:12:10Z</time>
<extensions>
<gpxtpx:TrackPointExtension>
<gpxtpx:atemp>27.3</gpxtpx:atemp>
</gpxtpx:TrackPointExtension>
</extensions>
</trkpt>
<trkpt lat="52.219872" lon="5.996397">
More trkpt…
</trkseg>
</trk>
</gpx>
if(assoc && arr_count == 1) {
if(arr[key]) { //If another element exists with the same tag name before,
// put it in a numeric array.
//Find out how many time this parent made its appearance
The error is about arr[key] and says that "undefined is null or not an object".
Is there an update to XML2Array() that fixes this?
reading the array's.
Is there a fix for this problem?
Anonymous at 22 Feb, 2008 02:30
This routine doesn't store an array with one element in the same manner as multiple entry arrays.
I'm using the eBay APIs which may return one or more elements. The XML structure is the same regardless of the number of entries.
It's really working :)
} elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
//See if the key is already taken.
if(!isset($current[$tag])) { //New Key
$current[$tag] = array($result);
// last line just creates first element already in the array.
// enjoy!
this function have problem whit big xml:
Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 93633696 bytes) in /var/www/vhosts/example.com/test.php on line 97
:(
a, strong, em, b, i, code, pre, pandbrallowed. Other tags will be shown as code(< will become <). Urls, Line breaks will be auto-formated.