view Lib/IMPL/DOM/Schema/NodeList.pm @ 9:5899df8c289e

DOM schema
author Sergey
date Thu, 27 Aug 2009 17:49:42 +0400
parents fffb153be599
children 1ca530e5c9c5
line wrap: on
line source

package IMPL::DOM::Schema::NodeList;
use strict;
use warnings;
use base qw(IMPL::DOM::Schema::Item);
use IMPL::Class::Property;

BEGIN {
    public property MessageUnexpected => prop_all;
    public property MessageNodesRequired => prop_all;
}

sub Validate {
    my ($this,$node) = @_;
    
    my @nodes = map {
        {nodeName => $_->nodeName, Schema => $_, Min => $_->minOccur, Max => $_->maxOccur, Seen => 0 }
    } @{$this->childNodes};
    
    my $info = shift @nodes;
    
    foreach my $child ( @{$node->childNodes} ) {
        #skip schema elements
        while ($info and $info->{nodeName} ne $child->nodeName) {
            # if possible of course :)
            return {
                Error => 1,
                Message => $this->MessageUnexpected,
                Node => $child,
                Source => $this
            } if $info->{Min} > $info->{Seen};
            
            $info = shift @nodes;
        }
        
        # return error if no more children allowed
        return {
            Error => 1,
            Message => $this->MessageUnexpected,
            Node => $child,
            Source => $this
        } unless $info;
        
        # it's ok, we found schema element for him
        $info->{Seen}++;
        
        # check count limits
        return {
            Error => 1,
            Message => $this->MessageUnexpected,
            Node => $child,
            Source => $this,
        } if $info->{Seen} > $info->{Max};
        
        # validate
        if (my @errors = $info->{Schema}->Validate($child)) {
            return @errors;
        }
    }
    
    # no more children left (but may be should :)
    while ($info) {
        return {
            Error => 1,
            Message => $this->MessageNodesRequired,
            Source => $this
        } if $info->{Seen} < $info->{Min};
        
        $info = shift @nodes;
    }
}

1;

__END__

=pod

=head1 DESCRIPTION

Содержимое для сложного узла. Порядок важен. Дочерними элементами могут быть
только C<IMPL::DOM::Schema::ComplexNode> и C<IMPL::DOM::Schema::SimpleNode>.

=cut