package AMP::ParseXH; ###### ParseXH class
### 	$Id: ParseXH.pm,v 1.1 2002/05/23 14:34:01 steve Exp $
###
###	This class parses and processes extended HTML and related markup

use XML::Node;
use XML::TrivialParser;
use Exporter();
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);

BEGIN {
    $VERSION=1.00;
    @ISA = qw(Exporter XML::TrivialParser);
    @EXPORT = qw(
		 );
}


#############################################################################
###
### Constructors:
###


sub new {
    my ($class, $context, $entities) = @_;

    #my $self = $class->XML::TrivialParser::new;
    my $self = bless { '_buf' => '', '_stack' => [], '_depth' => 0 }, $class;
    $self->{"_context"} = $context;
    $self->{"_entities"} = $entities;

    $self;
}


#############################################################################
###
### access functions:
###

### $p->get(name) -> value
#	get a value.  Typically these are also useable as entities, but names
#	starting with non-alpha-numeric characters will not be recognized as
#	entities and so can be used internally with impunity.
#
sub get {
    my ($self, $n) = (@_);
    return $self->{$n};
}

sub getContext {
    my ($self) = (@_);
    return $self->{"_context"};
}

sub getEntities {
    my ($self) = (@_);
    return $self->{"_entities"};
}


#############################################################################
###
### Token Handling:
###
###	These routines are the ones that XML::Parser calls on itself
###	when it recognizes an input token:
###
###		declaration($text)
###		comment($text)
###		pi($text)
###		start_tag($tag, [attr => value, ...])
###		end_tag($tag)
###		text($text)
###
###	The default bindings build a parse tree out of XML::Node objects.
###	Overriding these in a subclass allows SAX-like on-the-fly processing.

### $self->declaration($text)	HTML declaration, e.g. doctype.
##	initial "<!" and ending ">" stripped off.
sub declaration {
    my ($self, $text) = @_;
    $self->add(XML::Node->declaration($text)) unless $self->filter();
}

### $self->comment($text)	Comment.
##	The leading and trailing "<!--" and "-->" have been stripped off.
sub comment {
    my ($self, $text) = @_;
    $self->add(XML::Node->comment($text)) unless $self->filter();
}

### $self->pi($text)		Processing Instruction
sub pi {
    my ($self, $text) = @_;
    $self->add(XML::Node->pi($text)) unless $self->filter();
 
}

### $self->end_tag($tag)	End tag
sub end_tag {
    my ($self, $tag) = @_;
    --$self->{'_depth'};
    $self->add($self->pop());	# === need to do validity checking first
}

### $self->start_tag(tag, {attrs})	Start tag
##	The attributes are passed in a hash.
##	Called with additional attribute _empty=>'/' if it ended in '/>'.
sub start_tag {
    my ($self, $tag, $attrs) = @_;
    my $node = XML::Node->element($tag, $attrs);
    if ($node->marked_empty()) { $self->add($node); }
    elsif ($tag =~ /^(hr|br|img|meta|link|input)$/i) { 
	$node->mark_empty;
	$self->add($node); 
    } else { $self->push($node);  ++$self->{'_depth'};}
}

### $self->text($text)		Text
##	The parser doesn't recognize entities, so it's up to the 
##	application to process them if necessary.
sub text {
    my ($self, $text) = @_;
    if ($self->depth == 0 && $self->filter() ) { return; }
    $self->add($text);
}

### $self->cdata($text)		Character Data Section
##	Most applications will treat this the same as text
sub cdata {
    my ($self, $text) = @_;
    $self->add(XML::Node->cdata($text));
}


1;
