view lib/Yours/Parsers/SaxParser.pm @ 3:ae61af01bfa5

sync
author cin
date Wed, 23 Oct 2013 01:13:19 +0400
parents 93b83e3c38d6
children 8001dc056331
line wrap: on
line source

package Yours::Parsers::SaxParser;
use strict;

use IMPL::Const qw(:prop);
use IMPL::declare {
	require => {
		XMLReader    => 'XML::LibXML::Reader',
		Exception    => 'IMPL::Exception',
		ArgException => '-IMPL::InvalidArgumentException'
	  },
	  base  => [ 'IMPL::Object' => undef ],
	  props => [ _reader        => PROP_RW ]
};

BEGIN {
	XMLReader->import;
}

sub Parse {
	my ( $this, $options ) = @_;

	my $reader = $this->_reader( XMLReader->new($options) );

	$reader->read();
	$this->ProcessRootNode($reader);
	$reader->read();
}

sub ProcessRootNode {
	my ( $this, $reader ) = @_;
}

sub ReadChildren {
	my ( $this, $handler ) = @_;

	my $reader = $this->_reader;

	return if $reader->isEmptyElement;

	my $currentLevel = $reader->depth+1;

	while (
		$reader->read
	  )
	{
		print "---\n" and return if $reader->depth <= $currentLevel && $reader->nodeType == XML_READER_TYPE_END_ELEMENT;
		#if ($reader->nodeType != XML_READER_TYPE_END_ELEMENT) {
			$this->$handler($reader) if $handler;
		#}
	}
}

sub ReadTextNode {
	my ($this) = @_;

	my $text = "";

	my $handler;
	$handler = sub {
		my ( $me, $reader ) = @_;
		if ( $reader->nodeType == XML_READER_TYPE_TEXT ) {
			$text .= $reader->value;
		} else {
			$this->ReadChildren($handler);
		}
	};

	$this->ReadChildren($handler);

	return $text;
}

sub ReadComplexNode {
	my ( $this, $schema ) = @_;

	if ( ref $schema eq 'HASH' ) {
		my %data;

		$this->ReadChildren(
			sub {
				my ( $me, $node ) = @_;

				my $name = $node->localName;
				if ( my $handler = $schema->{$name} ) {
					if (ref $handler eq 'ARRAY') {
						push @{$data{$name}}, $me->ReadComplexNode($$handler[0]);
					} else {
						$data{$name} = $me->ReadComplexNode($handler);
					}
				} else {
					$me->ReadChildren();
				}
			}
		);

		return \%data;
	}
	elsif ( ref $schema eq 'CODE' or not ref $schema ) {
		return $this->$schema($this->_reader);
	}
	else {
		die ArgException->new( schema => 'An invalid schema is supplied' );
	}
}

sub attribute {
	shift->_reader->getAttribute(shift);
}

1;

__END__

=pod

=head1 NAME

=head1 DESCRIPTION

=head1 MEMBERS

=head2 ReadComplexNode($schema)

=begin code

{
	comments => sub { shift->ReadTextNode },
	data => [ {
		location => sub { $_[1]->getAttribute('href')} ,
		timestamp => 'ReadTextNode' 
	} ]
}

=end code

=cut