2 |
use strict; |
use strict; |
3 |
require Whatpm::ContentChecker; |
require Whatpm::ContentChecker; |
4 |
|
|
5 |
|
require Whatpm::URIChecker; |
6 |
|
|
7 |
my $ATOM_NS = q<http://www.w3.org/2005/Atom>; |
my $ATOM_NS = q<http://www.w3.org/2005/Atom>; |
8 |
|
|
9 |
## MUST be well-formed XML (RFC 4287 references XML 1.0 REC 20040204) |
## MUST be well-formed XML (RFC 4287 references XML 1.0 REC 20040204) |
179 |
} |
} |
180 |
} elsif ($ln eq 'uri') { |
} elsif ($ln eq 'uri') { |
181 |
unless ($has_uri) { |
unless ($has_uri) { |
|
## TODO: MUST be an IRI |
|
182 |
$has_uri = 1; |
$has_uri = 1; |
183 |
} else { |
} else { |
184 |
$not_allowed = 1; # MUST NOT |
$not_allowed = 1; # MUST NOT |
185 |
} |
} |
186 |
} elsif ($ln eq 'email') { |
} elsif ($ln eq 'email') { |
187 |
unless ($has_email) { |
unless ($has_email) { |
|
## TODO: MUST be an addr-spec |
|
188 |
$has_email = 1; |
$has_email = 1; |
189 |
} else { |
} else { |
190 |
$not_allowed = 1; # MUST NOT |
$not_allowed = 1; # MUST NOT |
218 |
}, |
}, |
219 |
}; # $AtomPersonConstruct |
}; # $AtomPersonConstruct |
220 |
|
|
221 |
## MUST NOT be any white space |
our $Element; |
222 |
my $AtomDateConstruct = { |
|
223 |
|
$Element->{$ATOM_NS}->{name} = { |
224 |
|
## NOTE: Strictly speaking, structure and semantics for atom:name |
225 |
|
## element outside of Person construct is not defined. |
226 |
|
attrs_checker => $GetAtomAttrsChecker->({}), |
227 |
|
checker => sub { |
228 |
|
my ($self, $todo) = @_; |
229 |
|
|
230 |
|
my @nodes = (@{$todo->{node}->child_nodes}); |
231 |
|
my $new_todos = []; |
232 |
|
|
233 |
|
while (@nodes) { |
234 |
|
my $node = shift @nodes; |
235 |
|
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
236 |
|
|
237 |
|
my $nt = $node->node_type; |
238 |
|
if ($nt == 1) { |
239 |
|
## NOTE: No constraint. |
240 |
|
my ($sib, $ch) = $self->_check_get_children ($node, $todo); |
241 |
|
unshift @nodes, @$sib; |
242 |
|
push @$new_todos, @$ch; |
243 |
|
} elsif ($nt == 3 or $nt == 4) { |
244 |
|
# |
245 |
|
} elsif ($nt == 5) { |
246 |
|
unshift @nodes, @{$node->child_nodes}; |
247 |
|
} |
248 |
|
} |
249 |
|
|
250 |
|
return ($new_todos); |
251 |
|
}, |
252 |
|
}; |
253 |
|
|
254 |
|
$Element->{$ATOM_NS}->{uri} = { |
255 |
|
## NOTE: Strictly speaking, structure and semantics for atom:uri |
256 |
|
## element outside of Person construct is not defined. |
257 |
|
attrs_checker => $GetAtomAttrsChecker->({}), |
258 |
|
checker => sub { |
259 |
|
my ($self, $todo) = @_; |
260 |
|
|
261 |
|
my @nodes = (@{$todo->{node}->child_nodes}); |
262 |
|
my $new_todos = []; |
263 |
|
|
264 |
|
my $s = ''; |
265 |
|
while (@nodes) { |
266 |
|
my $node = shift @nodes; |
267 |
|
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
268 |
|
|
269 |
|
my $nt = $node->node_type; |
270 |
|
if ($nt == 1) { |
271 |
|
## NOTE: Not explicitly disallowed. |
272 |
|
$self->{onerror}->(node => $node, type => 'element not allowed'); |
273 |
|
my ($sib, $ch) = $self->_check_get_children ($node, $todo); |
274 |
|
unshift @nodes, @$sib; |
275 |
|
push @$new_todos, @$ch; |
276 |
|
} elsif ($nt == 3 or $nt == 4) { |
277 |
|
$s .= $node->data; |
278 |
|
} elsif ($nt == 5) { |
279 |
|
unshift @nodes, @{$node->child_nodes}; |
280 |
|
} |
281 |
|
} |
282 |
|
|
283 |
|
## NOTE: There MUST NOT be any white space. |
284 |
|
Whatpm::URIChecker->check_iri_reference ($s, sub { |
285 |
|
my %opt = @_; |
286 |
|
$self->{onerror}->(node => $todo->{node}, level => $opt{level}, |
287 |
|
type => 'URI::'.$opt{type}. |
288 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
289 |
|
}); |
290 |
|
|
291 |
|
return ($new_todos); |
292 |
|
}, |
293 |
|
}; |
294 |
|
|
295 |
|
$Element->{$ATOM_NS}->{email} = { |
296 |
|
## NOTE: Strictly speaking, structure and semantics for atom:email |
297 |
|
## element outside of Person construct is not defined. |
298 |
attrs_checker => $GetAtomAttrsChecker->({}), |
attrs_checker => $GetAtomAttrsChecker->({}), |
299 |
checker => sub { |
checker => sub { |
300 |
my ($self, $todo) = @_; |
my ($self, $todo) = @_; |
301 |
|
|
302 |
|
my @nodes = (@{$todo->{node}->child_nodes}); |
303 |
|
my $new_todos = []; |
304 |
|
|
305 |
|
my $s = ''; |
306 |
|
while (@nodes) { |
307 |
|
my $node = shift @nodes; |
308 |
|
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
309 |
|
|
310 |
|
my $nt = $node->node_type; |
311 |
|
if ($nt == 1) { |
312 |
|
## NOTE: Not explicitly disallowed. |
313 |
|
$self->{onerror}->(node => $node, type => 'element not allowed'); |
314 |
|
my ($sib, $ch) = $self->_check_get_children ($node, $todo); |
315 |
|
unshift @nodes, @$sib; |
316 |
|
push @$new_todos, @$ch; |
317 |
|
} elsif ($nt == 3 or $nt == 4) { |
318 |
|
$s .= $node->data; |
319 |
|
} elsif ($nt == 5) { |
320 |
|
unshift @nodes, @{$node->child_nodes}; |
321 |
|
} |
322 |
|
} |
323 |
|
|
324 |
|
## TODO: addr-spec |
325 |
|
$self->{onerror}->(node => $todo->{node}, type => 'addr-spec', |
326 |
|
level => 'unsupported'); |
327 |
|
|
328 |
|
return ($new_todos); |
329 |
|
}, |
330 |
|
}; |
331 |
|
|
332 |
|
## MUST NOT be any white space |
333 |
|
my $AtomDateConstruct = { |
334 |
|
attrs_checker => $GetAtomAttrsChecker->({}), |
335 |
|
checker => sub { |
336 |
my ($self, $todo) = @_; |
my ($self, $todo) = @_; |
337 |
|
|
338 |
my @nodes = (@{$todo->{node}->child_nodes}); |
my @nodes = (@{$todo->{node}->child_nodes}); |
364 |
}, |
}, |
365 |
}; # $AtomDateConstruct |
}; # $AtomDateConstruct |
366 |
|
|
367 |
## MUST NOT be any IRI |
$Element->{$ATOM_NS}->{entry} = { |
|
my $AtomIRIChecker = sub { |
|
|
|
|
|
}; # $AtomIRIChecker |
|
|
|
|
|
our $Element; |
|
|
|
|
|
$Element->{$ATOM_NS}->{entryXXX} = { |
|
368 |
is_root => 1, |
is_root => 1, |
369 |
attrs_checker => $GetAtomAttrsChecker->({}), |
attrs_checker => $GetAtomAttrsChecker->({}), |
370 |
checker => sub { |
checker => sub { |
477 |
|
|
478 |
my $nt = $node->node_type; |
my $nt = $node->node_type; |
479 |
if ($nt == 1) { |
if ($nt == 1) { |
|
# MUST |
|
480 |
my $nsuri = $node->namespace_uri; |
my $nsuri = $node->namespace_uri; |
481 |
$nsuri = '' unless defined $nsuri; |
$nsuri = '' unless defined $nsuri; |
482 |
my $not_allowed; |
my $not_allowed; |
584 |
## TODO: This implementation is not optimal. |
## TODO: This implementation is not optimal. |
585 |
|
|
586 |
if ($src_attr) { |
if ($src_attr) { |
587 |
## TODO: MUST be an IRI reference |
## NOTE: There MUST NOT be any white space. |
588 |
|
Whatpm::URIChecker->check_iri_reference ($src_attr->value, sub { |
589 |
|
my %opt = @_; |
590 |
|
$self->{onerror}->(node => $todo->{node}, level => $opt{level}, |
591 |
|
type => 'URI::'.$opt{type}. |
592 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
593 |
|
}); |
594 |
|
|
595 |
## NOTE: If @src, the element MUST be empty. What is "empty"? |
## NOTE: If @src, the element MUST be empty. What is "empty"? |
596 |
## Is |<e><!----></e>| empty? |<e>&e;</e>| where |&e;| has |
## Is |<e><!----></e>| empty? |<e>&e;</e>| where |&e;| has |
800 |
$Element->{$ATOM_NS}->{category} = { |
$Element->{$ATOM_NS}->{category} = { |
801 |
attrs_checker => $GetAtomAttrsChecker->({ |
attrs_checker => $GetAtomAttrsChecker->({ |
802 |
label => sub { 1 }, # no value constraint |
label => sub { 1 }, # no value constraint |
803 |
scheme => sub { }, ## TODO: IRI # No MUST |
scheme => sub { # NOTE: No MUST. |
804 |
|
my ($self, $attr) = @_; |
805 |
|
## NOTE: There MUST NOT be any white space. |
806 |
|
Whatpm::URIChecker->check_iri ($attr->value, sub { |
807 |
|
my %opt = @_; |
808 |
|
$self->{onerror}->(node => $attr, level => $opt{level}, |
809 |
|
type => 'URI::'.$opt{type}. |
810 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
811 |
|
}); |
812 |
|
}, |
813 |
term => sub { 1 }, # no value constraint |
term => sub { 1 }, # no value constraint |
814 |
}), |
}), |
815 |
checker => sub { |
checker => sub { |
847 |
|
|
848 |
$Element->{$ATOM_NS}->{generator} = { |
$Element->{$ATOM_NS}->{generator} = { |
849 |
attrs_checker => $GetAtomAttrsChecker->({ |
attrs_checker => $GetAtomAttrsChecker->({ |
850 |
uri => sub { }, ## TODO: IRI reference # MUST # SHOULD produce a representation that is relevant to the agent |
uri => sub { # MUST |
851 |
|
my ($self, $attr) = @_; |
852 |
|
## NOTE: There MUST NOT be any white space. |
853 |
|
Whatpm::URIChecker->check_iri_reference ($attr->value, sub { |
854 |
|
my %opt = @_; |
855 |
|
$self->{onerror}->(node => $attr, level => $opt{level}, |
856 |
|
type => 'URI::'.$opt{type}. |
857 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
858 |
|
}); |
859 |
|
## NOTE: Dereferencing SHOULD produce a representation |
860 |
|
## that is relevant to the agent. |
861 |
|
}, |
862 |
version => sub { 1 }, # no value constraint |
version => sub { 1 }, # no value constraint |
863 |
}), |
}), |
864 |
checker => sub { |
checker => sub { |
898 |
my @nodes = (@{$todo->{node}->child_nodes}); |
my @nodes = (@{$todo->{node}->child_nodes}); |
899 |
my $new_todos = []; |
my $new_todos = []; |
900 |
|
|
901 |
|
my $s = ''; |
902 |
while (@nodes) { |
while (@nodes) { |
903 |
my $node = shift @nodes; |
my $node = shift @nodes; |
904 |
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
911 |
unshift @nodes, @$sib; |
unshift @nodes, @$sib; |
912 |
push @$new_todos, @$ch; |
push @$new_todos, @$ch; |
913 |
} elsif ($nt == 3 or $nt == 4) { |
} elsif ($nt == 3 or $nt == 4) { |
914 |
# |
$s .= $node->data; |
915 |
} elsif ($nt == 5) { |
} elsif ($nt == 5) { |
916 |
unshift @nodes, @{$node->child_nodes}; |
unshift @nodes, @{$node->child_nodes}; |
917 |
} |
} |
918 |
} |
} |
919 |
|
|
920 |
## TODO: an IRI reference (no MUST) |
## NOTE: No MUST. |
921 |
|
## NOTE: There MUST NOT be any white space. |
922 |
|
Whatpm::URIChecker->check_iri_reference ($s, sub { |
923 |
|
my %opt = @_; |
924 |
|
$self->{onerror}->(node => $todo->{node}, level => $opt{level}, |
925 |
|
type => 'URI::'.$opt{type}. |
926 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
927 |
|
}); |
928 |
|
|
929 |
## NOTE: Image SHOULD be 1:1 and SHOULD be small |
## NOTE: Image SHOULD be 1:1 and SHOULD be small |
930 |
|
|
931 |
return ($new_todos); |
return ($new_todos); |
939 |
|
|
940 |
my @nodes = (@{$todo->{node}->child_nodes}); |
my @nodes = (@{$todo->{node}->child_nodes}); |
941 |
my $new_todos = []; |
my $new_todos = []; |
942 |
|
|
943 |
|
my $s = ''; |
944 |
while (@nodes) { |
while (@nodes) { |
945 |
my $node = shift @nodes; |
my $node = shift @nodes; |
946 |
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
953 |
unshift @nodes, @$sib; |
unshift @nodes, @$sib; |
954 |
push @$new_todos, @$ch; |
push @$new_todos, @$ch; |
955 |
} elsif ($nt == 3 or $nt == 4) { |
} elsif ($nt == 3 or $nt == 4) { |
956 |
# |
$s .= $node->data; |
957 |
} elsif ($nt == 5) { |
} elsif ($nt == 5) { |
958 |
unshift @nodes, @{$node->child_nodes}; |
unshift @nodes, @{$node->child_nodes}; |
959 |
} |
} |
960 |
} |
} |
961 |
|
|
962 |
## TODO: MUST be an IRI (absolute) |
## NOTE: There MUST NOT be any white space. |
963 |
|
Whatpm::URIChecker->check_iri ($s, sub { # MUST |
964 |
|
my %opt = @_; |
965 |
|
$self->{onerror}->(node => $todo->{node}, level => $opt{level}, |
966 |
|
type => 'URI::'.$opt{type}. |
967 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
968 |
|
}); |
969 |
## TODO: SHOULD be normalized |
## TODO: SHOULD be normalized |
970 |
|
|
971 |
return ($new_todos); |
return ($new_todos); |
972 |
}, |
}, |
973 |
}; |
}; |
974 |
|
|
975 |
|
$Element->{$ATOM_NS}->{link} = { |
976 |
|
attrs_checker => $GetAtomAttrsChecker->({ |
977 |
|
href => sub { |
978 |
|
my ($self, $attr) = @_; |
979 |
|
## NOTE: There MUST NOT be any white space. |
980 |
|
Whatpm::URIChecker->check_iri_reference ($attr->value, sub { |
981 |
|
my %opt = @_; |
982 |
|
$self->{onerror}->(node => $attr, level => $opt{level}, |
983 |
|
type => 'URI::'.$opt{type}. |
984 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
985 |
|
}); |
986 |
|
}, |
987 |
|
hreflang => sub { }, # TODO: MUST be an RFC 3066 language tag |
988 |
|
length => sub { }, # No MUST; in octets. |
989 |
|
rel => sub { # MUST |
990 |
|
my ($self, $attr) = @_; |
991 |
|
my $value = $attr->value; |
992 |
|
if ($value =~ /\A(?>[0-9A-Za-z._~!\$&'()*+,;=\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}-]|%[0-9A-Fa-f][0-9A-Fa-f]|\@)+\z/) { |
993 |
|
$value = q<http://www.iana.org/assignments/relation/> . $value; |
994 |
|
} |
995 |
|
|
996 |
|
## NOTE: There MUST NOT be any white space. |
997 |
|
Whatpm::URIChecker->check_iri ($value, sub { |
998 |
|
my %opt = @_; |
999 |
|
$self->{onerror}->(node => $attr, level => $opt{level}, |
1000 |
|
type => 'URI::'.$opt{type}. |
1001 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
1002 |
|
}); |
1003 |
|
|
1004 |
|
## TODO: Warn if unregistered |
1005 |
|
}, |
1006 |
|
type => sub { }, # TODO: MUST be a MIME media type |
1007 |
|
}), |
1008 |
|
checker => sub { |
1009 |
|
my ($self, $todo) = @_; |
1010 |
|
|
1011 |
|
unless ($todo->{node}->has_attribute_ns (undef, 'href')) { # MUST |
1012 |
|
$self->{onerror}->(node => $todo->{node}, |
1013 |
|
type => 'attribute missing:href'); |
1014 |
|
} |
1015 |
|
|
1016 |
|
if ($todo->{node}->rel eq |
1017 |
|
q<http://www.iana.org/assignments/relation/enclosure> and |
1018 |
|
not $todo->{node}->has_attribute_ns (undef, 'length')) { |
1019 |
|
$self->{onerror}->(node => $todo->{node}, level => 's', |
1020 |
|
type => 'attribute missing:length'); |
1021 |
|
} |
1022 |
|
|
1023 |
|
my @nodes = (@{$todo->{node}->child_nodes}); |
1024 |
|
my $new_todos = []; |
1025 |
|
|
1026 |
|
while (@nodes) { |
1027 |
|
my $node = shift @nodes; |
1028 |
|
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
1029 |
|
|
1030 |
|
my $nt = $node->node_type; |
1031 |
|
if ($nt == 1) { |
1032 |
|
my ($sib, $ch) = $self->_check_get_children ($node, $todo); |
1033 |
|
unshift @nodes, @$sib; |
1034 |
|
push @$new_todos, @$ch; |
1035 |
|
} elsif ($nt == 3 or $nt == 4) { |
1036 |
|
# |
1037 |
|
} elsif ($nt == 5) { |
1038 |
|
unshift @nodes, @{$node->child_nodes}; |
1039 |
|
} |
1040 |
|
} |
1041 |
|
|
1042 |
|
return ($new_todos); |
1043 |
|
}, |
1044 |
|
}; |
1045 |
|
|
1046 |
|
$Element->{$ATOM_NS}->{logo} = { |
1047 |
|
attrs_checker => $GetAtomAttrsChecker->({}), |
1048 |
|
checker => sub { |
1049 |
|
my ($self, $todo) = @_; |
1050 |
|
|
1051 |
|
my @nodes = (@{$todo->{node}->child_nodes}); |
1052 |
|
my $new_todos = []; |
1053 |
|
|
1054 |
|
my $s = ''; |
1055 |
|
while (@nodes) { |
1056 |
|
my $node = shift @nodes; |
1057 |
|
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
1058 |
|
|
1059 |
|
my $nt = $node->node_type; |
1060 |
|
if ($nt == 1) { |
1061 |
|
## not explicitly disallowed |
1062 |
|
$self->{onerror}->(node => $node, type => 'element not allowed'); |
1063 |
|
my ($sib, $ch) = $self->_check_get_children ($node, $todo); |
1064 |
|
unshift @nodes, @$sib; |
1065 |
|
push @$new_todos, @$ch; |
1066 |
|
} elsif ($nt == 3 or $nt == 4) { |
1067 |
|
$s .= $node->data; |
1068 |
|
} elsif ($nt == 5) { |
1069 |
|
unshift @nodes, @{$node->child_nodes}; |
1070 |
|
} |
1071 |
|
} |
1072 |
|
|
1073 |
|
## NOTE: There MUST NOT be any white space. |
1074 |
|
Whatpm::URIChecker->check_iri_reference ($s, sub { |
1075 |
|
my %opt = @_; |
1076 |
|
$self->{onerror}->(node => $todo->{node}, level => $opt{level}, |
1077 |
|
type => 'URI::'.$opt{type}. |
1078 |
|
(defined $opt{position} ? ':'.$opt{position} : '')); |
1079 |
|
}); |
1080 |
|
|
1081 |
|
## NOTE: Image SHOULD be 2:1 |
1082 |
|
|
1083 |
|
return ($new_todos); |
1084 |
|
}, |
1085 |
|
}; |
1086 |
|
|
1087 |
|
$Element->{$ATOM_NS}->{published} = $AtomDateConstruct; |
1088 |
|
|
1089 |
|
$Element->{$ATOM_NS}->{rights} = $AtomDateConstruct; |
1090 |
|
## SHOULD NOT be used to convey machine-readable information. |
1091 |
|
|
1092 |
|
$Element->{$ATOM_NS}->{source} = { |
1093 |
|
attrs_checker => $GetAtomAttrsChecker->({}), |
1094 |
|
checker => sub { |
1095 |
|
my ($self, $todo) = @_; |
1096 |
|
|
1097 |
|
my @nodes = (@{$todo->{node}->child_nodes}); |
1098 |
|
my $new_todos = []; |
1099 |
|
my $has_element = {}; |
1100 |
|
while (@nodes) { |
1101 |
|
my $node = shift @nodes; |
1102 |
|
$self->_remove_minuses ($node) and next if ref $node eq 'HASH'; |
1103 |
|
|
1104 |
|
my $nt = $node->node_type; |
1105 |
|
if ($nt == 1) { |
1106 |
|
my $nsuri = $node->namespace_uri; |
1107 |
|
$nsuri = '' unless defined $nsuri; |
1108 |
|
my $not_allowed; |
1109 |
|
if ($nsuri eq $ATOM_NS) { |
1110 |
|
my $ln = $node->manakai_local_name; |
1111 |
|
if ($ln eq 'entry') { |
1112 |
|
$has_element->{entry} = 1; |
1113 |
|
} elsif ({ |
1114 |
|
generator => 1, |
1115 |
|
icon => 1, |
1116 |
|
id => 1, |
1117 |
|
logo => 1, |
1118 |
|
rights => 1, |
1119 |
|
subtitle => 1, |
1120 |
|
title => 1, |
1121 |
|
updated => 1, |
1122 |
|
}->{$ln}) { |
1123 |
|
unless ($has_element->{$ln}) { |
1124 |
|
$has_element->{$ln} = 1; |
1125 |
|
$not_allowed = $has_element->{entry}; |
1126 |
|
} else { |
1127 |
|
$not_allowed = 1; |
1128 |
|
} |
1129 |
|
} elsif ($ln eq 'link') { |
1130 |
|
## TODO: MUST NOT rel=alternate with same (type, hreflang) |
1131 |
|
# |
1132 |
|
$not_allowed = $has_element->{entry}; |
1133 |
|
} elsif ({ |
1134 |
|
author => 1, |
1135 |
|
category => 1, |
1136 |
|
contributor => 1, |
1137 |
|
}->{$ln}) { |
1138 |
|
$not_allowed = $has_element->{entry}; |
1139 |
|
} else { |
1140 |
|
$not_allowed = 1; |
1141 |
|
} |
1142 |
|
} else { |
1143 |
|
## TODO: extension element |
1144 |
|
$not_allowed = 1; |
1145 |
|
} |
1146 |
|
$self->{onerror}->(node => $node, type => 'element not allowed') |
1147 |
|
if $not_allowed; |
1148 |
|
my ($sib, $ch) = $self->_check_get_children ($node, $todo); |
1149 |
|
unshift @nodes, @$sib; |
1150 |
|
push @$new_todos, @$ch; |
1151 |
|
} elsif ($nt == 3 or $nt == 4) { |
1152 |
|
## TODO: Are white spaces allowed? |
1153 |
|
$self->{onerror}->(node => $node, type => 'character not allowed'); |
1154 |
|
} elsif ($nt == 5) { |
1155 |
|
unshift @nodes, @{$node->child_nodes}; |
1156 |
|
} |
1157 |
|
} |
1158 |
|
|
1159 |
|
return ($new_todos); |
1160 |
|
}, |
1161 |
|
}; |
1162 |
|
|
1163 |
|
$Element->{$ATOM_NS}->{subtitle} = $AtomTextConstruct; |
1164 |
|
|
1165 |
|
$Element->{$ATOM_NS}->{summary} = $AtomTextConstruct; |
1166 |
|
|
1167 |
|
$Element->{$ATOM_NS}->{title} = $AtomTextConstruct; |
1168 |
|
|
1169 |
|
$Element->{$ATOM_NS}->{updated} = $AtomDateConstruct; |
1170 |
|
|
1171 |
|
## TODO: signature element |
1172 |
|
|
1173 |
|
## TODO: simple extension element and structured extension element |
1174 |
|
|
1175 |
$Whatpm::ContentChecker::Namespace->{$ATOM_NS}->{loaded} = 1; |
$Whatpm::ContentChecker::Namespace->{$ATOM_NS}->{loaded} = 1; |
1176 |
|
|
1177 |
1; |
1; |