XML-DOMHandler
view release on metacpan or search on metacpan
DOMHandler.pm view on Meta::CPAN
# $Id: DOMHandler.pm,v 1.1 2002/08/20 18:06:48 eray Exp eray $
package XML::DOMHandler;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
@ISA = qw( Exporter );
@EXPORT = qw( Version );
$VERSION = '1.0';
sub Version { $VERSION; }
#
# table of node types and internal handler methods
#
my %dispatch_table = (
&XML_ELEMENT_NODE => '_handle_element',
&XML_ATTRIBUTE_NODE => '_handle_attribute',
&XML_TEXT_NODE => '_handle_text',
&XML_CDATA_SECTION_NODE => '_handle_cdata',
&XML_ENTITY_REF_NODE => '_handle_entity_ref',
&XML_ENTITY_NODE => '',
&XML_PI_NODE => '_handle_pi',
&XML_COMMENT_NODE => '_handle_comment',
&XML_DOCUMENT_NODE => '_handle_doc_node',
&XML_DOCUMENT_TYPE_NODE => '_handle_doctype',
&XML_DOCUMENT_FRAG_NODE => '',
&XML_NOTATION_NODE => '',
&XML_HTML_DOCUMENT_NODE => '',
&XML_DTD_NODE => '',
&XML_ELEMENT_DECL_NODE => '',
&XML_ATTRIBUTE_DECL_NODE => '',
&XML_ENTITY_DECL_NODE => '',
&XML_NAMESPACE_DECL_NODE => '_handle_ns_decl',
&XML_XINCLUDE_START => '',
&XML_XINCLUDE_END => '',
);
my $level; # depth in the tree
my $position; # position in parent's content list
my @pstack; # position stack
my $root;
my $rootset = 0;
sub new {
#
# initialize object with options
#
my $class = shift;
my $self = {@_};
reset();
return bless( $self, $class );
}
sub reset {
#
# set globals back to zero
#
$level = 0;
$position = 0;
@pstack = (0);
}
sub traverse {
#
# dispatch node to handler, recurse
#
my( $self, $node ) = @_;
my $handled_flag = 0;
my $fun = $dispatch_table{ $node->nodeType };
$root = $node unless( $rootset );
$rootset = 1;
if( $fun ) {
$handled_flag = $self->$fun( $node );
return 1;
# apply generic Node handler
$handled_flag =
$self->_apply_user_handler( $node, 'generic_node' )
|| $handled_flag;
# apply generic "else" node handler if no handlers applied
$handled_flag ||=
$self->_apply_user_handler( $node, 'else_generic_node' );
}
return $handled_flag;
}
sub _handle_element {
#
# process an element, recurse if necessary
#
my( $self, $node ) = @_;
my $handled_flag = 0;
# apply specific element handler
my $name = $node->nodeName;
$handled_flag = $self->_apply_user_handler( $node, $name );
# apply generic element handler
$handled_flag = $self->_apply_user_handler( $node, 'generic_element' )
|| $handled_flag;
# apply generic "else" handler if no element handlers applied
$handled_flag ||=
$self->_apply_user_handler( $node, 'generic_element_else' );
return $self->_handle_descendants( $node ) || $handled_flag;
}
#
# default handlers for node types
#
sub _handle_attribute {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_attribute' );
}
sub _handle_text {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_text' );
}
sub _handle_cdata {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_CDATA' );
}
sub _handle_entity_ref {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_entity_ref' );
}
sub _handle_pi {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_PI' );
}
sub _handle_comment {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_comment' );
}
sub _handle_doc_type {
my( $self, $node ) = @_;
return $self->_apply_user_handler( $node, 'generic_doctype' );
}
sub _handle_doc_node {
#
# process the document node, recurse if necessary
#
my( $self, $node ) = @_;
$self->_apply_user_handler( $node, 'generic_document' );
$level++;
$pstack[1] = 1;
$position = 1;
my $handled_flag = $self->traverse( $node->getDocumentElement );
$level--;
return $handled_flag;
}
sub _handle_descendants {
#
# recurse through descendants
#
# NOTES:
# 1. Removing a node that follows the current node is dangerous!
# 2. Nodes inserted before or after the current node won't be processed.
#
my( $self, $node ) = @_;
my $handled_flag = 0;
$level++;
$pstack[ $level ] = 0;
foreach my $child ( $node->getChildnodes ) {
$pstack[ $level ] ++;
$position = $pstack[ $level ];
$handled_flag += $self->traverse( $child );
}
$level--;
return $handled_flag;
}
( run in 0.836 second using v1.01-cache-2.11-cpan-ff9377addf4 )