Mercurial > pub > Impl
diff Lib/IMPL/DOM/Schema/NodeList.pm @ 8:fffb153be599
DOM Schema
author | Sergey |
---|---|
date | Tue, 25 Aug 2009 17:36:37 +0400 |
parents | |
children | 1ca530e5c9c5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/DOM/Schema/NodeList.pm Tue Aug 25 17:36:37 2009 +0400 @@ -0,0 +1,83 @@ +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 \ No newline at end of file