|
Hi Jacob,
I found the bug. I've included changes below. 1)
This is very poorly structured code for a recursive routine. 2) There are
really only two 'cases' that are dealt with (open and complete). So I
changed from if()/else statements to a switch($type). 3) I added a function
to 'peek' at the next element's type. 4) Finally -- I do not think this is an
elegant solution but do not have time to rewrite the UpdateRecursive() routine
so it could in itself be elegant. Maybe one of the hot-shots at Google can
do that. I have not done extensive testing.
The Problem:
On an 'open' type element, the function loops and calls itself until it
sees a 'close' type. It accumulates the results of the recursion in an
array which it later unwinds to build the $params array (for that 'open' and
subsequent 'levels'). This picks up all elements at higher levels and
captures them into the accumulated array ($new_arr).
If the 'close' type is followed by a 'complete' type at the same level, the
'complete' type was skipped. That's because $this->global_index is
incremented within the if( $type == 'open') condition. After
$this->global_index is incremented, it points to the next element.
When the accumulation is unwound, the 'complete' tag was missed because it was
associated with an 'else' (I.e. else not open).
So there were multiple problems:
- 'complete' associated with an else
- Not picking up a 'complete' tag as the next tag at the same
level
My changed routines (note: added function of peek():
/* Look at the next type and
compare */ function peek($type, &$vals)
{
$idx
= $this->global_index + 1;
if(
$idx < count($vals) )
return( $vals[$idx]['type'] == $type ? $idx : 0 );
return(0); }
/* Converts the output of SAX parser
into a PHP associative array similar to the * DOM parser
output */ function
UpdateRecursive($vals) { // $params accumulates
through this level $params = array();
$this->global_index++; //Reached end of
array if($this->global_index >=
count($vals)) return;
$tag =
strtolower($vals[$this->global_index]['tag']); // TB
3/2/07 - Added to prevent value from being an Undefined
index. $value =
isset($vals[$this->global_index]['value']) ?
trim($vals[$this->global_index]['value']) :
''; $type =
$vals[$this->global_index]['type'];
//Add
attributes if(isset($vals[$this->global_index]['attributes']))
{
foreach($vals[$this->global_index]['attributes'] as $key=>$val)
{ $key =
strtolower($key);
$params[$tag][$key] = $val;
} } switch($type)
{ case
'open': $new_arr
=
array();
//Read all elements at the next levels and add to an
array while($vals[$this->global_index]['type']
!= 'close'
&&
$this->global_index < count($vals))
{
$arr =
$this->UpdateRecursive($vals);
if(count($arr) > 0)
{
$new_arr[] =
$arr;
} } //
First unwind the recursive accumulation for this prior element (if it had
depth) foreach($new_arr
as $arr)
{
foreach($arr as $key=>$val)
{ if(isset($params[$tag][$key]))
{
//If this key already
exists
if($this->is_associative_array($params[$tag][$key]))
{ //If
this is an associative array and not an indexed
array //
remove existing value and convert to an indexed
array $val_key
=
$params[$tag][$key]; & |