the best way would be to have it as a numerically indexed array (or, even better, a mix-n-matched array so you can call $data['items'][n]['value'])
here's a better xml parser that'll pull off what you want it to do, it's pretty much the best xml->array parser I've ever seen that isn't 30 different files from PEAR:
PHP Code:
<?php
class XMLParser {
var $data; // Input XML data buffer
var $vals; // Struct created by xml_parse_into_struct
var $collapse_dups; // If there is only one tag of a given name, shall we store as scalar or array?
var $index_numeric; // Index tags by numeric position, not name. Useful for ordered XML like CallXML.
var $trim_whitespace; // variable to declare whether or not to keep whitespace inside xml tags
// Read in XML on object creation.
// We can take raw XML data, a stream, a filename, or a url.
function XMLParser($data_source, $data_source_type='raw', $collapse_dups=0, $index_numeric=0, $trim_whitespace=0)
{
$this->collapse_dups = $collapse_dups;
$this->index_numeric = $index_numeric;
$this->trim_whitespace = $trim_whitespace;
$this->data = '';
// raw input
if ($data_source_type == 'raw')
{
$this->data = $data_source;
}
elseif ($data_source_type == 'stream') {
while (!feof($data_source))
{
$this->data .= fread($data_source, 1000);
}
// try filename, then if that fails...
}
elseif (file_exists($data_source))
{
$this->data = implode('', file($data_source));
}
// try url
else
{
$fp = fopen($data_source,'r');
while (!feof($fp))
{
$this->data .= fread($fp, 1000);
}
fclose($fp);
}
}
// Parse the XML file into a verbose, flat array struct.
// Then, coerce that into a simple nested array.
function getTree()
{
$parser = xml_parser_create('UTF-8');
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $this->trim_whitespace);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parse_into_struct($parser, $this->data, $vals, $index);
xml_parser_free($parser);
$i = -1;
return $this->getchildren($vals, $i);
}
// internal function: build a node of the tree
function buildtag($thisvals, $vals, &$i, $type)
{
$tag=array();
if (isset($thisvals['attributes']))
{
//$tag['attributes'] = $thisvals['attributes'];
$tag = $thisvals['attributes'];
}
// complete tag, just return it for storage in array
if ($type === 'complete')
{
// check if we're entering an empty value or not
if (!empty($thisvals['value']))
{
// not empty, so lets assign $tag to the value element of $thisvals to avoid unnecessary obfuscation
// doesn't work on cdata for some reason, oh well not a big deal
$tag = $thisvals['value'];
}
}
// open tag, recurse
else
{
$tag = array_merge($tag, $this->getchildren($vals, $i));
}
return $tag;
}
// internal function: build an nested array representing children
function getchildren($vals, &$i)
{
$children = array(); // Contains node data
// Node has CDATA before it's children
if ($i > -1 && !empty($vals[$i]['value']))
{
$children['value'] = $vals[$i]['value'];
}
// Loop through children, until hit close tag or run out of tags
while (++$i < count($vals))
{
$type = $vals[$i]['type'];
// 'cdata': Node has CDATA after one of it's children
// (Add to cdata found before in this case)
if ($type === 'cdata')
{
if (!empty($vals[$i]['value']))
{
$children['value'] .= $vals[$i]['value'];
}
}
// 'complete': At end of current branch
// 'open': Node has children, recurse
elseif ($type === 'complete' || $type === 'open')
{
$tag = $this->buildtag($vals[$i], $vals, $i, $type);
if ($this->index_numeric)
{
$tag['tag'] = $vals[$i]['tag'];
$children[] = $tag;
}
else
{
$children[$vals[$i]['tag']][] = $tag;
}
}
// 'close: End of node, return collected data
// Do not increment $i or nodes disappear!
elseif ($type === 'close')
{
break;
}
}
if ($this->collapse_dups)
{
foreach($children as $key => $value)
{
if (is_array($value) && (count($value) == 1) && (!empty($value)))
{
$children[$key] = $value[0];
}
}
return $children;
}
}
}
?>
edit: I modified a copy of this to use curl to pull data from a external location with cookie support if you want that instead
Bookmarks