<?php
/*
** Fishlib - a collection of utilities for db-driven applications in PHP
** Copyright (C) 2002  LTWD, LLC DBA The Madfish Group
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

class FishXML
{
    var 
$parser NULL;
    var 
$tags = array();
    var 
$tag NULL;
    var 
$attributes NULL;
    var 
$cdata NULL;

    var 
$root NULL;
    var 
$stack NULL;
    var 
$current NULL;

    var 
$tick NULL;
    var 
$who NULL;

    function 
FishXML()
    {
        static 
$tick 0;
        
$this->tick $tick++;
    }

    
// debugging methods
    
function dodump($new=NULL)
    {
        static 
$si FALSE;
        if (
$new !== NULL)
            
$si = (bool)$new;
        return 
$si;
    }

    function 
dump()
    {
        if (
$this->dodump())
        {
            
$args func_get_args();
            foreach (
$args as $arg)
                if (
is_string($arg))
                    echo 
$arg;
                else
                    echo 
'{'preg_replace('/[[:space:]]+/'' 'var_export($argTRUE)), '}';
            echo 
"\n";
        }
    }

    function 
forcedump()
    {
        
$args func_get_args();
        
$old $this->dodump();
        
$this->dodump(TRUE);
        
call_user_func_array(array(&$this'dump'), $args);
        
$this->dodump($old);
    }

    
// real methods
    
function parse($data)
    { 
        
$this->parser xml_parser_create();
        
xml_set_object($this->parser, &$this);
        
xml_set_element_handler($this->parser'tag_open''tag_close');
        
xml_set_character_data_handler($this->parser"cdata");
        
xml_parse($this->parser$data);
    }

    function 
tag($tag)
    {
        
$tag strtolower(trim($tag));
        if (!
in_array($tag$this->tags))
            
$this->tags[] = $tag;
        
$this->tag $tag;
    }

    function 
handle($what,$args=array())
    {
        if (!
is_array($args))
            
$args = (array)$args;
        switch (
$what)
        {
            case 
'open':
                
$this->attributes = isset($args[2]) ? $args[2] : NULL;
            case 
'close':
                
$this->tag(isset($args[1]) ? $args[1] : NULL);
                break;
            case 
'cdata':
                
$this->cdata = isset($args[1]) ? $args[1] : '';
                break;
            default:
                
$this->forcedump('bad call to handle: what='$what' args='$args);
                
user_error('internal error - exiting'E_USER_ERROR);
                exit;
        }
        
$method "{$this->tag}_{$what}";
        if (!
method_exists($this$method))
            
$method "default_{$what}";
        
call_user_func(array(&$this$method));
    }

    function 
default_open()
    {
        if (
$this->root === NULL)
        {
            
$this->root = array('tag'=>'root''attributes'=>NULL'children'=>array());
            
$this->stack = array();
            
$this->current = &$this->root;
        }
        if (
$this->current['children'] === NULL)
            
$this->current['children'] = array();
        
$i count($this->current['children']);
        
$this->current['children'][$i] = array(
            
'tag' => $this->tag
            
'attributes' => $this->attributes
            
'cdata' => NULL
            
'children' => NULL
        
);
        
$s count($this->stack);
        
$this->stack[$s] = &$this->current;
        
$this->current = &$this->current['children'][$i];
    }

    function 
tag_open($parser$tag$attributes)
    { 
        
$this->dump('tag_open: tick='$this->tick', tag='$tag' attributes='$attributes); 
        
$args func_get_args();
        
$this->handle('open'$args);
        
$this->dump("\t"'this->tag='$this->tag);
    }

    function 
default_cdata()
    {
        
$this->current['cdata'] .= $this->cdata;
    }

    function 
cdata($parser$cdata)
    {
        
$this->dump('cdata: tick='$this->tick' this->tag='$this->tag', cdata='$cdata);
        
$args func_get_args();
        
$this->handle('cdata'$args);
    }

    function 
default_close()
    {
        
$this->current['cdata'] = trim(preg_replace('|[[:space:]]+|'' '$this->current['cdata']));
        
$i count($this->stack) - 1;
        
$this->current = &$this->stack[$i];
        
array_pop($this->stack);
    }

    function 
tag_close($parser$tag)
    {
        
$this->dump('tag_close: tick='$this->tick', tag='$tag);
        
$args func_get_args();
        
$this->handle('close'$args);
    }
}
?>