Location: PHPKode > projects > jjfmapper > jjfmapper/lib/xml_detail_parser.php
<?php #-*-Mode: php; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/*
    xml_detail_parser for PHP 4.
    Copyright (C) 2004  John J Foerch

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* The xml_detail_parser class facilitates working with xml raw
data.  This class creates two data trees similar in structure to
those produced by xml_parse_into_struct.  Additionally, each
node of the tree has an element called position, which contains
its byte position in the raw data.  This information can be used
to better handle CDATA.
*/


class xml_detail_parser {
    var $ok=true;
    var $error;
    var $level=0;
    var $current_index = 0;
    var $struct = array();
    var $index = array();
    var $tag_indices = array();
    var $content='';
    var $current_tag_is_complete=false;
    var $fulltags = false;
    var $ignore_tags = false;
    var $supported_tags;
    var $ignore_level = false;//used when ignoring tags
    
    function xml_detail_parser (&$xmldata) {
        $this->content = $xmldata;
        if (func_num_args () > 1)
        {
            $ops = func_get_arg (1);
            $this->options ($ops);
        }
        
        $parser = xml_parser_create();
        xml_set_object ($parser, $this);
        xml_set_element_handler ($parser,'start_element','end_element');
        $parse_success = xml_parse ($parser,$this->content,true);
        if ($parse_success === false)
        {
            $this->ok = false;
            $this->error = xml_error_string(xml_get_error_code($parser));
        }
        xml_parser_free ($parser);
    }
    
    function options (&$ops) {
        if (isset ($ops['fulltags']) && $ops['fulltags'] === true)
            $this->fulltags = true;
        if (isset ($ops['support']))
        {
            $this->ignore_tags = true;
            $this->supported_tags = explode (',', $ops['support']);
        }
    }

    function start_element (&$parser, $name, &$attr) {

        ++$this->level;

        $position = xml_get_current_byte_index ($parser);
        $fulltag = substr ($this->content, $position);
        $fulltag = substr ($fulltag, 0, strpos ($fulltag,'>')+1);
        $type = $fulltag[strlen ($fulltag) - 2] == '/' ? 'complete' : 'open';
        if ($type == 'complete') $this->current_tag_is_complete = true;


        if ($this->ignore_tags == true)
        {
            if ($this->ignore_level == false &&
                in_array ($name, $this->supported_tags) == false)
            {
                $this->ignore_level = $this->level;
            }
        }

        if ($this->ignore_tags == false || $this->ignore_level == false)
        {
            $this->struct[$this->current_index] = array (
                'tag' => $name,
                'type' => $type,
                'level' => $this->level,
                'position' => $position,
                'taglen' => strlen ($fulltag)
                );
            if ($this->fulltags)
            {
                $this->struct[$this->current_index]['fulltag'] = $fulltag;
            }
            if (count ($attr) > 0) 
            {
                $this->struct[$this->current_index]['attributes'] = $attr;
            }
            $this->tag_indices[] = $this->current_index;
            if (! isset ($this->index[$name])) $this->index[$name] = array();
            $this->index[$name][] = $this->current_index;

            ++$this->current_index;
        }
    }
    
    function end_element (&$parser, $name) {
        if ($this->ignore_level == false)
            $open_index = array_pop ($this->tag_indices);

        if ($this->current_tag_is_complete)
        {
            $this->current_tag_is_complete = false;
            --$this->level;
            if ($this->level == $this->ignore_level)
                $this->ignore_level = false;
            return;
        }
        
        if ($this->ignore_level == false)
        {
            $position = xml_get_current_byte_index ($parser);
        
            $this->struct[$this->current_index] = array (
                'tag' => $name,
                'type' => 'close',
                'level' => $this->level,
                'open' => $open_index,
                'position' => $position
                );
            $this->struct[$open_index]['close'] = $this->current_index;

            if (! isset ($this->index[$name])) $this->index[$name] = array();

            $this->index[$name][] = $this->current_index;
            ++$this->current_index;
        }
        if ($this->level == $this->ignore_level) $this->ignore_level = false;
        --$this->level;
        
    }
    
    function cdata_for_tag (&$tag) {
        $clip_start = $tag['position'] + $tag['taglen'];
        $clip_end = $this->struct[$tag['close']]['position'];
        $clip_length = $clip_end - $clip_start;
        return substr ($this->content, $clip_start, $clip_length);
    }
}

?>
Return current item: jjfmapper