I recently started working with xml in php and started doing it the easy way - using simplexml functions in php5. I then discovered that my web hosting providers only provide php4, and so I have to change to use the full-blown xml parsing functions.
I've read loads of examples of how to create a parser object, recognise start and end tags etc. to do something simple like indent xml-sourced data in html, but I need to parse xml and return an array of objects (in a separate php script included in a number of pages).
It seems that the functions called by the xml parser (i.e. start_tag, end_tag, tag_contents) don't really 'know' about the array and its objects that I'm trying to work with. Here is my code:
Code: Select all
<?php
function parseObjectXML($xmlPath,$objCount) {
// populate the array I need to return
$internalObjArray = array();
for($x = 0; $x < $objCount; $x++) {
$thisObj = new FatBiscuitObject();
array_push($internalObjArray,$thisObj);
}
$current = "";
if (! ($xmlparser = xml_parser_create()) ) {
die ("Cannot create parser");
}
function start_tag($parser, $name, $attribs) {
global $current;
$current = $name;
if ($name == "TYPE") {
// currently nothing in here
}
}
function end_tag($parser, $name) {
if ($name == "SOURCE") {
// currently nothing in here
}
}
function tag_contents($parser, $data) {
global $current;
global $internalObjArray;
switch($current) {
case "TYPE":
$internalObjArray[count($internalObjArray)]->type = $data;
break;
case "ID":
$internalObjArray[count($internalObjArray)]->id = $data;
break;
case "NAME":
$internalObjArray[count($internalObjArray)]->name = $data;
break;
case "DESCRIPTION":
$internalObjArray[count($internalObjArray)]->description = $data;
break;
/*... and so on */
}
}
xml_set_element_handler($xmlparser, "start_tag", "end_tag");
xml_set_character_data_handler($xmlparser, "tag_contents");
$filename = $xmlPath;
if (!($fp = fopen($filename, "r"))) { die("cannot open ".$filename); }
while ($data = fread($fp, 4096)) {
$data=eregi_replace(">"."[[:space:]]+"."<","><",$data);
if (!xml_parse($xmlparser, $data, feof($fp))) {
$reason = xml_error_string(xml_get_error_code($xmlparser));
$reason .= xml_get_current_line_number($xmlparser);
die($reason);
}
}
xml_parser_free($xmlparser);
// report what's in the array's objects
echo "count: ".count($internalObjArray)."<br />0->ID: ".$internalObjArray[0]->id."<br />0->Name: ".$internalObjArray[0]->name;
return $internalObjArray;
}
?>
Code: Select all
count: 2
0->ID:
0->Name:
In the code above I'm assigning the number of objects I expect to find contained within the xml up-front. I'd rather push the completed object into the array when I come across the closing tag 'SOURCE', but if I do I am told that the $internalObjArray does not exist... As far as I can see this is not a problem with how I am referencing global variables as the $current variable is used as expected.
It seems that the 'tag_contents' function simply doesn't know about the $internalObjArray array, and therefore assigns nothing.
Any suggestions / help with this would be massively appreciated as I am about to give up completely due to lack of progress.