49
|
1 package IMPL::DOM::Schema::NodeSet;
|
|
2 use strict;
|
|
3 use warnings;
|
|
4
|
|
5 use base qw(IMPL::DOM::Node);
|
|
6 use IMPL::Class::Property;
|
|
7
|
|
8 our %CTOR = (
|
|
9 'IMPL::DOM::Node' => sub { nodeName => 'NodeSet' }
|
|
10 );
|
|
11
|
|
12 BEGIN {
|
|
13 public property messageUnexpected => prop_all;
|
|
14 public property messageMax => prop_all;
|
|
15 public property messageMin => prop_all;
|
|
16 }
|
|
17
|
|
18 sub CTOR {
|
|
19 my ($this,%args) = @_;
|
|
20
|
|
21 $this->messageMax( $args{messageMax} || 'Too many %Node.nodeName% nodes');
|
|
22 $this->messageMin( $args{messageMin} || '%Schema.name% nodes expected');
|
|
23 $this->messageUnexpected( $args{messageUnexpected} || 'A %Node.nodeName% isn\'t allowed in %Node.parentNode.path%');
|
|
24 }
|
|
25
|
|
26 sub Validate {
|
|
27 my ($this,$node) = @_;
|
|
28
|
|
29 my @errors;
|
|
30
|
|
31 my %nodes;
|
|
32 my $anyNode;
|
|
33 foreach (@{$this->childNodes}) {
|
|
34 if ($_->isa('IMPL::DOM::Schema::AnyNode')) {
|
|
35 $anyNode = {Schema => $_, Min => $_->minOccur, Max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur , Seen => 0 };
|
|
36 } else {
|
|
37 $nodes{$_->name} = {Schema => $_, Min => $_->minOccur, Max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur , Seen => 0 };
|
|
38 }
|
|
39 }
|
|
40
|
|
41 foreach my $child ( @{$node->childNodes} ) {
|
|
42 if (my $info = $nodes{$child->nodeName} || $anyNode) {
|
|
43 $info->{Seen}++;
|
|
44 push @errors,new IMPL::DOM::Schema::ValidationError (
|
|
45 Source => $this,
|
|
46 Node => $child,
|
|
47 Schema => $info->{Schema},
|
|
48 Message => $this->messageMax
|
|
49 ) if ($info->{Max} and $info->{Seen} > $info->{Max});
|
|
50
|
|
51 if (my @localErrors = $info->{Schema}->Validate($child)) {
|
|
52 push @errors,@localErrors;
|
|
53 }
|
|
54 } else {
|
|
55 push @errors, new IMPL::DOM::Schema::ValidationError (
|
|
56 Source => $this,
|
|
57 Node => $child,
|
|
58 Message => $this->messageUnexpected
|
|
59 )
|
|
60 }
|
|
61 }
|
|
62
|
|
63 foreach my $info (values %nodes) {
|
|
64 push @errors, new IMPL::DOM::Schema::ValidationError (
|
|
65 Source => $this,
|
|
66 Schema => $info->{Schema},
|
|
67 Message => $this->messageMin
|
|
68 ) if $info->{Min} > $info->{Seen};
|
|
69 }
|
|
70
|
|
71 return @errors;
|
|
72 }
|
|
73
|
|
74 1;
|
|
75
|
|
76 __END__
|
|
77
|
|
78 =pod
|
|
79
|
|
80 =head1 DESCRIPTION
|
|
81
|
|
82 Содержимое для сложного узла. Порядок не важен. Дочерними элементами могут быть
|
|
83 только C<IMPL::DOM::Schema::ComplexNode> и C<IMPL::DOM::Schema::SimpleNode>.
|
|
84
|
|
85 При проверке данного правила, проверяются имеющиеся элементы на соответсие схемы
|
|
86 и количества встречаемости, после чего проверяются количественные ограничения
|
|
87 для несуществующих элементов.
|
|
88
|
|
89 =cut
|