/[suikacvs]/markup/html/whatpm/Whatpm/ContentChecker/Atom.pm
Suika

Contents of /markup/html/whatpm/Whatpm/ContentChecker/Atom.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Sun Aug 5 04:50:57 2007 UTC (17 years, 3 months ago) by wakaba
Branch: MAIN
++ whatpm/Whatpm/ChangeLog	5 Aug 2007 04:50:52 -0000
	* ContentChecker.pm: Reference to the |Whatpm::ContentChecker::Atom|
	is added.
	(check_document): Load appropriate module before validation.

2007-08-04  Wakaba  <wakaba@suika.fam.cx>

++ whatpm/Whatpm/ContentChecker/ChangeLog	5 Aug 2007 04:49:57 -0000
2007-08-05  Wakaba  <wakaba@suika.fam.cx>

	* Atom.pm: New Perl module.

1 wakaba 1.1 package Whatpm::ContentChecker;
2     use strict;
3     require Whatpm::ContentChecker;
4    
5     my $ATOM_NS = q<http://www.w3.org/2005/Atom>;
6    
7     ## MUST be well-formed XML (RFC 4287 references XML 1.0 REC 20040204)
8    
9     ## NOTE: Commants and PIs are not explicitly allowed.
10    
11     our $AttrChecker;
12    
13     ## Any element MAY have xml:base, xml:lang
14     my $GetAtomAttrsChecker = sub {
15     my $element_specific_checker = shift;
16     return sub {
17     my ($self, $todo) = @_;
18     for my $attr (@{$todo->{node}->attributes}) {
19     my $attr_ns = $attr->namespace_uri;
20     $attr_ns = '' unless defined $attr_ns;
21     my $attr_ln = $attr->manakai_local_name;
22     my $checker;
23     if ($attr_ns eq '') {
24     $checker = $element_specific_checker->{$attr_ln};
25     } else {
26     $checker = $AttrChecker->{$attr_ns}->{$attr_ln}
27     || $AttrChecker->{$attr_ns}->{''};
28     }
29     if ($checker) {
30     $checker->($self, $attr, $todo);
31     } else {
32     $self->{onerror}->(node => $attr, level => 'unsupported',
33     type => 'attribute');
34     ## ISSUE: No comformance createria for unknown attributes in the spec
35     }
36     }
37     };
38     }; # $GetAtomAttrsChecker
39    
40     my $AtomTextConstruct = {
41     attrs_checker => $GetAtomAttrsChecker->({
42     type => sub { 1 }, # checked in |checker|
43     }),
44     checker => sub {
45     my ($self, $todo) = @_;
46    
47     my $attr = $todo->{node}->get_attribute_node_ns (undef, 'type');
48     my $value = 'text';
49     if ($attr) {
50     $value = $attr->value;
51     if ($value eq 'text' or $value eq 'html' or $value eq 'xhtml') {
52     # MUST
53     } else {
54     $self->{onerror}->(node => $attr, type => 'keyword:invalid');
55     }
56     # IMT MUST NOT be used
57     }
58    
59     if ($value eq 'text') {
60     my @nodes = (@{$todo->{node}->child_nodes});
61     my $new_todos = [];
62    
63     while (@nodes) {
64     my $node = shift @nodes;
65     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
66    
67     my $nt = $node->node_type;
68     if ($nt == 1) {
69     # MUST NOT
70     $self->{onerror}->(node => $node, type => 'element not allowed');
71     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
72     unshift @nodes, @$sib;
73     push @$new_todos, @$ch;
74     } elsif ($nt == 5) {
75     unshift @nodes, @{$node->child_nodes};
76     }
77     }
78    
79     return ($new_todos);
80     } elsif ($value eq 'html') {
81     my @nodes = (@{$todo->{node}->child_nodes});
82     my $new_todos = [];
83    
84     while (@nodes) {
85     my $node = shift @nodes;
86     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
87    
88     my $nt = $node->node_type;
89     if ($nt == 1) {
90     # MUST NOT
91     $self->{onerror}->(node => $node, type => 'element not allowed');
92     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
93     unshift @nodes, @$sib;
94     push @$new_todos, @$ch;
95     } elsif ($nt == 5) {
96     unshift @nodes, @{$node->child_nodes};
97     }
98     }
99    
100     ## TODO: SHOULD be suitable for handling as HTML [HTML4]
101     # markup MUST be escaped
102     ## TODO: HTML SHOULD be valid as if within <div>
103    
104     return ($new_todos);
105     } elsif ($value eq 'xhtml') {
106     my @nodes = (@{$todo->{node}->child_nodes});
107     my $new_todos = [];
108    
109     my $has_div;
110     while (@nodes) {
111     my $node = shift @nodes;
112     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
113    
114     my $nt = $node->node_type;
115     if ($nt == 1) {
116     # MUST
117     my $nsuri = $node->namespace_uri;
118     if (defined $nsuri and
119     $nsuri eq q<http://www.w3.org/1999/xhtml> and
120     $node->manakai_local_name eq 'div' and
121     not $has_div) {
122     ## TODO: SHOULD be suitable for handling as HTML [XHTML10]
123     $has_div = 1;
124     } else {
125     $self->{onerror}->(node => $node, type => 'element not allowed');
126     }
127     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
128     unshift @nodes, @$sib;
129     push @$new_todos, @$ch;
130     } elsif ($nt == 3 or $nt == 4) {
131     ## TODO: Are white spaces allowed?
132     $self->{onerror}->(node => $node, type => 'character not allowed');
133     } elsif ($nt == 5) {
134     unshift @nodes, @{$node->child_nodes};
135     }
136     }
137    
138     unless ($has_div) {
139     $self->{onerror}->(node => $todo->{node},
140     type => 'element missing:div');
141     }
142    
143     return ($new_todos);
144     }
145    
146     },
147     }; # $AtomTextConstruct
148    
149     my $AtomPersonConstruct = {
150     attrs_checker => $GetAtomAttrsChecker->({}),
151     checker => sub {
152     my ($self, $todo) = @_;
153    
154     my @nodes = (@{$todo->{node}->child_nodes});
155     my $new_todos = [];
156    
157     my $has_name;
158     my $has_uri;
159     my $has_email;
160     while (@nodes) {
161     my $node = shift @nodes;
162     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
163    
164     my $nt = $node->node_type;
165     if ($nt == 1) {
166     # MUST
167     my $nsuri = $node->namespace_uri;
168     $nsuri = '' unless defined $nsuri;
169     my $not_allowed;
170     if ($nsuri eq $ATOM_NS) {
171     my $ln = $node->manakai_local_name;
172     if ($ln eq 'name') {
173     unless ($has_name) {
174     $has_name = 1;
175     } else {
176     $not_allowed = 1;
177     }
178     } elsif ($ln eq 'uri') {
179     unless ($has_uri) {
180     ## TODO: MUST be an IRI
181     $has_uri = 1;
182     } else {
183     $not_allowed = 1; # MUST NOT
184     }
185     } elsif ($ln eq 'email') {
186     unless ($has_email) {
187     ## TODO: MUST be an addr-spec
188     $has_email = 1;
189     } else {
190     $not_allowed = 1; # MUST NOT
191     }
192     } else {
193     $not_allowed = 1;
194     }
195     } else {
196     ## TODO: extension element
197     $not_allowed = 1;
198     }
199     $self->{onerror}->(node => $node, type => 'element not allowed')
200     if $not_allowed;
201     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
202     unshift @nodes, @$sib;
203     push @$new_todos, @$ch;
204     } elsif ($nt == 3 or $nt == 4) {
205     ## TODO: Are white spaces allowed?
206     $self->{onerror}->(node => $node, type => 'character not allowed');
207     } elsif ($nt == 5) {
208     unshift @nodes, @{$node->child_nodes};
209     }
210     }
211    
212     unless ($has_name) { # MUST
213     $self->{onerror}->(node => $todo->{node},
214     type => 'element missing:atom.name');
215     }
216    
217     return ($new_todos);
218     },
219     }; # $AtomPersonConstruct
220    
221     ## MUST NOT be any white space
222     my $AtomDateConstruct = {
223     attrs_checker => $GetAtomAttrsChecker->({}),
224     checker => sub {
225     my ($self, $todo) = @_;
226    
227     my ($self, $todo) = @_;
228    
229     my @nodes = (@{$todo->{node}->child_nodes});
230     my $new_todos = [];
231    
232     my $s = '';
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: It does not explicitly say that there MUST NOT be any element.
240     $self->{onerror}->(node => $node, type => 'element not allowed');
241     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
242     unshift @nodes, @$sib;
243     push @$new_todos, @$ch;
244     } elsif ($nt == 3 or $nt == 4) {
245     $s .= $node->data;
246     } elsif ($nt == 5) {
247     unshift @nodes, @{$node->child_nodes};
248     }
249     }
250    
251     ## TODO: $s =~ MUST RFC 3339 date-time, uppercase T, Z
252     # SHOULD be accurate as possible
253    
254     return ($new_todos);
255     },
256     }; # $AtomDateConstruct
257    
258     ## MUST NOT be any IRI
259     my $AtomIRIChecker = sub {
260    
261     }; # $AtomIRIChecker
262    
263     our $Element;
264    
265     $Element->{$ATOM_NS}->{entryXXX} = {
266     is_root => 1,
267     attrs_checker => $GetAtomAttrsChecker->({}),
268     checker => sub {
269     my ($self, $todo) = @_;
270    
271     my @nodes = (@{$todo->{node}->child_nodes});
272     my $new_todos = [];
273    
274     ## TODO: MUST author+ unless (child::source/child::author)
275     ## or (parent::feed/child::author)
276    
277     my $has_element = {};
278     while (@nodes) {
279     my $node = shift @nodes;
280     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
281    
282     my $nt = $node->node_type;
283     if ($nt == 1) {
284     # MUST
285     my $nsuri = $node->namespace_uri;
286     $nsuri = '' unless defined $nsuri;
287     my $not_allowed;
288     if ($nsuri eq $ATOM_NS) {
289     my $ln = $node->manakai_local_name;
290     if ({ # MUST (0, 1)
291     content => 1,
292     id => 1,
293     published => 1,
294     rights => 1,
295     source => 1,
296     summary => 1,
297     ## TODO: MUST if child::content/@src | child::content/@type = IMT, !text/ !/xml !+xml
298     title => 1,
299     updated => 1,
300     }->{$ln}) {
301     unless ($has_element->{$ln}) {
302     $has_element->{$ln} = 1;
303     $not_allowed = $has_element->{entry};
304     } else {
305     $not_allowed = 1;
306     }
307     } elsif ($ln eq 'link') { # MAY
308     ## TODO: MUST link rel=alternate + unless child::content
309     ## TODO: MUST NOT rel=alternate with same (type, hreflang) +
310     ## NOTE: MAY
311     #
312     $not_allowed = $has_element->{entry};
313     } elsif ({ # MAY
314     author => 1,
315     category => 1,
316     contributor => 1,
317     }->{$ln}) {
318     $not_allowed = $has_element->{entry};
319     } else {
320     $not_allowed = 1;
321     }
322     } else {
323     ## TODO: extension element
324     $not_allowed = 1;
325     }
326     $self->{onerror}->(node => $node, type => 'element not allowed')
327     if $not_allowed;
328     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
329     unshift @nodes, @$sib;
330     push @$new_todos, @$ch;
331     } elsif ($nt == 3 or $nt == 4) {
332     ## TODO: Are white spaces allowed?
333     $self->{onerror}->(node => $node, type => 'character not allowed');
334     } elsif ($nt == 5) {
335     unshift @nodes, @{$node->child_nodes};
336     }
337     }
338    
339     ## NOTE: metadata elements, followed by atom:entry* (no explicit MAY)
340    
341     ## TODO: If entry's with same id, then updated SHOULD be different
342    
343     unless ($has_element->{id}) { # MUST
344     $self->{onerror}->(node => $todo->{node},
345     type => 'element missing:atom.id');
346     }
347     unless ($has_element->{title}) { # MUST
348     $self->{onerror}->(node => $todo->{node},
349     type => 'element missing:atom.title');
350     }
351     unless ($has_element->{updated}) { # MUST
352     $self->{onerror}->(node => $todo->{node},
353     type => 'element missing:atom.updated');
354     }
355    
356     return ($new_todos);
357     },
358     };
359    
360     $Element->{$ATOM_NS}->{feed} = {
361     is_root => 1,
362     attrs_checker => $GetAtomAttrsChecker->({}),
363     checker => sub {
364     my ($self, $todo) = @_;
365    
366     my @nodes = (@{$todo->{node}->child_nodes});
367     my $new_todos = [];
368    
369     ## TODO: MUST author+ unless all entry child has author+.
370    
371     my $has_element = {};
372     while (@nodes) {
373     my $node = shift @nodes;
374     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
375    
376     my $nt = $node->node_type;
377     if ($nt == 1) {
378     # MUST
379     my $nsuri = $node->namespace_uri;
380     $nsuri = '' unless defined $nsuri;
381     my $not_allowed;
382     if ($nsuri eq $ATOM_NS) {
383     my $ln = $node->manakai_local_name;
384     if ($ln eq 'entry') {
385     $has_element->{entry} = 1;
386     } elsif ({ # MUST (0, 1)
387     generator => 1,
388     icon => 1,
389     id => 1,
390     logo => 1,
391     rights => 1,
392     subtitle => 1,
393     title => 1,
394     updated => 1,
395     }->{$ln}) {
396     unless ($has_element->{$ln}) {
397     $has_element->{$ln} = 1;
398     $not_allowed = $has_element->{entry};
399     } else {
400     $not_allowed = 1;
401     }
402     } elsif ($ln eq 'link') { # MAY
403     ## TODO: SHOULD rel=self
404     ## TODO: MUST NOT rel=alternate with same (type, hreflang)
405     #
406     $not_allowed = $has_element->{entry};
407     } elsif ({ # MAY
408     author => 1,
409     category => 1,
410     contributor => 1,
411     }->{$ln}) {
412     $not_allowed = $has_element->{entry};
413     } else {
414     $not_allowed = 1;
415     }
416     } else {
417     ## TODO: extension element
418     $not_allowed = 1;
419     }
420     $self->{onerror}->(node => $node, type => 'element not allowed')
421     if $not_allowed;
422     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
423     unshift @nodes, @$sib;
424     push @$new_todos, @$ch;
425     } elsif ($nt == 3 or $nt == 4) {
426     ## TODO: Are white spaces allowed?
427     $self->{onerror}->(node => $node, type => 'character not allowed');
428     } elsif ($nt == 5) {
429     unshift @nodes, @{$node->child_nodes};
430     }
431     }
432    
433     ## NOTE: metadata elements, followed by atom:entry* (no explicit MAY)
434    
435     ## TODO: If entry's with same id, then updated SHOULD be different
436    
437     unless ($has_element->{id}) { # MUST
438     $self->{onerror}->(node => $todo->{node},
439     type => 'element missing:atom.id');
440     }
441     unless ($has_element->{title}) { # MUST
442     $self->{onerror}->(node => $todo->{node},
443     type => 'element missing:atom.title');
444     }
445     unless ($has_element->{updated}) { # MUST
446     $self->{onerror}->(node => $todo->{node},
447     type => 'element missing:atom.updated');
448     }
449    
450     return ($new_todos);
451     },
452     };
453    
454     $Element->{$ATOM_NS}->{content} = {
455     attrs_checker => $GetAtomAttrsChecker->({
456     src => sub { 1 }, # checked in |checker|
457     type => sub { 1 }, # checked in |checker|
458     }),
459     checker => sub {
460     my ($self, $todo) = @_;
461    
462     my $attr = $todo->{node}->get_attribute_node_ns (undef, 'type');
463     my $src_attr = $todo->{node}->get_attribute_node_ns (undef, 'src');
464     my $value;
465     if ($attr) {
466     $value = $attr->value;
467     if ($value eq 'text' or $value eq 'html' or $value eq 'xhtml') {
468     # MUST
469     } else {
470    
471     }
472     # IMT MUST NOT be used
473     } elsif ($src_attr) {
474     $value = '';
475     $self->{onerror}->(node => $todo->{node},
476     type => 'attribute missing:type', level => 's');
477     } else {
478     $value = 'text';
479     }
480    
481     ## TODO: type MUST be text/html/xhtml or MIME media type
482    
483     ## TODO: This implementation is not optimal.
484    
485     if ($src_attr) {
486     ## TODO: MUST be an IRI reference
487    
488    
489     ## NOTE: If @src, the element MUST be empty. What is "empty"?
490     ## Is |<e><!----></e>| empty? |<e>&e;</e>| where |&e;| has
491     ## empty replacement tree shuld be empty, since Atom is defined
492     ## in terms of XML Information Set where entities are expanded.
493     ## (but what if |&e;| is an unexpanded entity?)
494     }
495    
496     if ($value eq 'text') {
497     $self->{onerror}->(node => $attr, type => 'not IMT') if $src_attr;
498    
499     my @nodes = (@{$todo->{node}->child_nodes});
500     my $new_todos = [];
501    
502     while (@nodes) {
503     my $node = shift @nodes;
504     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
505    
506     my $nt = $node->node_type;
507     if ($nt == 1) {
508     # MUST NOT
509     $self->{onerror}->(node => $node, type => 'element not allowed');
510     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
511     unshift @nodes, @$sib;
512     push @$new_todos, @$ch;
513     } elsif ($nt == 3 or $nt == 4) {
514     $self->{onerror}->(node => $node, type => 'character not allowed')
515     if $src_attr;
516     } elsif ($nt == 5) {
517     unshift @nodes, @{$node->child_nodes};
518     }
519     }
520    
521     return ($new_todos);
522     } elsif ($value eq 'html') {
523     $self->{onerror}->(node => $attr, type => 'not IMT') if $src_attr;
524    
525     my @nodes = (@{$todo->{node}->child_nodes});
526     my $new_todos = [];
527    
528     while (@nodes) {
529     my $node = shift @nodes;
530     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
531    
532     my $nt = $node->node_type;
533     if ($nt == 1) {
534     # MUST NOT
535     $self->{onerror}->(node => $node, type => 'element not allowed');
536     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
537     unshift @nodes, @$sib;
538     push @$new_todos, @$ch;
539     } elsif ($nt == 3 or $nt == 4) {
540     $self->{onerror}->(node => $node, type => 'character not allowed')
541     if $src_attr;
542     } elsif ($nt == 5) {
543     unshift @nodes, @{$node->child_nodes};
544     }
545     }
546    
547     ## TODO: SHOULD be suitable for handling as HTML [HTML4]
548     # markup MUST be escaped
549     ## TODO: HTML SHOULD be valid as if within <div>
550    
551     return ($new_todos);
552     } elsif ($value eq 'xhtml') {
553     $self->{onerror}->(node => $attr, type => 'not IMT') if $src_attr;
554    
555     my @nodes = (@{$todo->{node}->child_nodes});
556     my $new_todos = [];
557    
558     my $has_div;
559     while (@nodes) {
560     my $node = shift @nodes;
561     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
562    
563     my $nt = $node->node_type;
564     if ($nt == 1) {
565     # MUST
566     my $nsuri = $node->namespace_uri;
567     if (defined $nsuri and
568     $nsuri eq q<http://www.w3.org/1999/xhtml> and
569     $node->manakai_local_name eq 'div' and
570     not $has_div) {
571     ## TODO: SHOULD be suitable for handling as HTML [XHTML10]
572     $has_div = 1;
573     $self->{onerror}->(node => $node, type => 'element not allowed')
574     if $src_attr;
575     } else {
576     $self->{onerror}->(node => $node, type => 'element not allowed');
577     }
578     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
579     unshift @nodes, @$sib;
580     push @$new_todos, @$ch;
581     } elsif ($nt == 3 or $nt == 4) {
582     ## TODO: Are white spaces allowed?
583     $self->{onerror}->(node => $node, type => 'character not allowed');
584     } elsif ($nt == 5) {
585     unshift @nodes, @{$node->child_nodes};
586     }
587     }
588    
589     unless ($has_div) {
590     $self->{onerror}->(node => $todo->{node},
591     type => 'element missing:div');
592     }
593    
594     return ($new_todos);
595     } elsif ($value =~ m![+/][Xx][Mm][Ll]\z!) {
596     ## ISSUE: There is no definition for "XML media type" in RFC 3023.
597     ## Is |application/xml-dtd| an XML media type?
598    
599     my @nodes = (@{$todo->{node}->child_nodes});
600     my $new_todos = [];
601    
602     while (@nodes) {
603     my $node = shift @nodes;
604     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
605    
606     my $nt = $node->node_type;
607     if ($nt == 1) {
608     ## MAY contain elements
609     $self->{onerror}->(node => $node, type => 'element not allowed')
610     if $src_attr;
611     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
612     unshift @nodes, @$sib;
613     push @$new_todos, @$ch;
614     } elsif ($nt == 3 or $nt == 4) {
615     ## TODO: Are white spaces allowed?
616     $self->{onerror}->(node => $node, type => 'character not allowed');
617     } elsif ($nt == 5) {
618     unshift @nodes, @{$node->child_nodes};
619     }
620     }
621    
622     ## TODO: SHOULD be suitable for handling as $value.
623     ## If no @src, this would normally mean it contains a
624     ## single child element that would serve as the root element.
625    
626     return ($new_todos);
627     } elsif ($value =~ m!^[Tt][Ee][Xx][Tt]/!) {
628     my @nodes = (@{$todo->{node}->child_nodes});
629     my $new_todos = [];
630    
631     while (@nodes) {
632     my $node = shift @nodes;
633     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
634    
635     my $nt = $node->node_type;
636     if ($nt == 1) {
637     # MUST NOT
638     $self->{onerror}->(node => $node, type => 'element not allowed');
639     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
640     unshift @nodes, @$sib;
641     push @$new_todos, @$ch;
642     } elsif ($nt == 3 or $nt == 4) {
643     $self->{onerror}->(node => $node, type => 'character not allowed')
644     if $src_attr;
645     } elsif ($nt == 5) {
646     unshift @nodes, @{$node->child_nodes};
647     }
648     }
649    
650     ## NOTE: No further restriction (such as to conform to the type).
651    
652     return ($new_todos);
653     } else {
654     my @nodes = (@{$todo->{node}->child_nodes});
655     my $new_todos = [];
656    
657     if ($value =~ m!^(?>message|multipart)/!i) { # MUST NOT
658     $self->{onerror}->(node => $attr, type => 'IMT:composite');
659     }
660    
661     my $s = '';
662     while (@nodes) {
663     my $node = shift @nodes;
664     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
665    
666     my $nt = $node->node_type;
667     if ($nt == 1) {
668     ## not explicitly disallowed
669     $self->{onerror}->(node => $node, type => 'element not allowed');
670     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
671     unshift @nodes, @$sib;
672     push @$new_todos, @$ch;
673     } elsif ($nt == 3 or $nt == 4) {
674     $s .= $node->data;
675     $self->{onerror}->(node => $node, type => 'character not allowed')
676     if $src_attr;
677     } elsif ($nt == 5) {
678     unshift @nodes, @{$node->child_nodes};
679     }
680     }
681    
682     ## TODO: $s = valid Base64ed [RFC 3548] where
683     ## MAY leading and following "white space" (what?)
684     ## and lines separated by a single U+000A
685     ## SHOULD be suitable for the indicated media type
686    
687     return ($new_todos);
688     }
689     },
690     };
691    
692     $Element->{$ATOM_NS}->{author} = $AtomPersonConstruct;
693    
694     $Element->{$ATOM_NS}->{category} = {
695     attrs_checker => $GetAtomAttrsChecker->({
696     label => sub { 1 }, # no value constraint
697     scheme => sub { }, ## TODO: IRI # No MUST
698     term => sub { 1 }, # no value constraint
699     }),
700     checker => sub {
701     my ($self, $todo) = @_;
702    
703     unless ($todo->{node}->has_attribute_ns (undef, 'term')) {
704     $self->{onerror}->(node => $todo->{node},
705     type => 'attribute missing:term');
706     }
707    
708     my @nodes = (@{$todo->{node}->child_nodes});
709     my $new_todos = [];
710    
711     while (@nodes) {
712     my $node = shift @nodes;
713     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
714    
715     my $nt = $node->node_type;
716     if ($nt == 1) {
717     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
718     unshift @nodes, @$sib;
719     push @$new_todos, @$ch;
720     } elsif ($nt == 3 or $nt == 4) {
721     #
722     } elsif ($nt == 5) {
723     unshift @nodes, @{$node->child_nodes};
724     }
725     }
726    
727     return ($new_todos);
728     },
729     };
730    
731     $Element->{$ATOM_NS}->{contributor} = $AtomPersonConstruct;
732    
733     $Element->{$ATOM_NS}->{generator} = {
734     attrs_checker => $GetAtomAttrsChecker->({
735     uri => sub { }, ## TODO: IRI reference # MUST # SHOULD produce a representation that is relevant to the agent
736     version => sub { 1 }, # no value constraint
737     }),
738     checker => sub {
739     my ($self, $todo) = @_;
740    
741     my @nodes = (@{$todo->{node}->child_nodes});
742     my $new_todos = [];
743    
744     while (@nodes) {
745     my $node = shift @nodes;
746     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
747    
748     my $nt = $node->node_type;
749     if ($nt == 1) {
750     ## not explicitly disallowed
751     $self->{onerror}->(node => $node, type => 'element not allowed');
752     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
753     unshift @nodes, @$sib;
754     push @$new_todos, @$ch;
755     } elsif ($nt == 3 or $nt == 4) {
756     ## MUST be a string that is a human-readable name for
757     ## the generating agent
758     } elsif ($nt == 5) {
759     unshift @nodes, @{$node->child_nodes};
760     }
761     }
762    
763     return ($new_todos);
764     },
765     };
766    
767     $Element->{$ATOM_NS}->{icon} = {
768     attrs_checker => $GetAtomAttrsChecker->({}),
769     checker => sub {
770     my ($self, $todo) = @_;
771    
772     my @nodes = (@{$todo->{node}->child_nodes});
773     my $new_todos = [];
774    
775     while (@nodes) {
776     my $node = shift @nodes;
777     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
778    
779     my $nt = $node->node_type;
780     if ($nt == 1) {
781     ## not explicitly disallowed
782     $self->{onerror}->(node => $node, type => 'element not allowed');
783     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
784     unshift @nodes, @$sib;
785     push @$new_todos, @$ch;
786     } elsif ($nt == 3 or $nt == 4) {
787     #
788     } elsif ($nt == 5) {
789     unshift @nodes, @{$node->child_nodes};
790     }
791     }
792    
793     ## TODO: an IRI reference (no MUST)
794     ## NOTE: Image SHOULD be 1:1 and SHOULD be small
795    
796     return ($new_todos);
797     },
798     };
799    
800     $Element->{$ATOM_NS}->{id} = {
801     attrs_checker => $GetAtomAttrsChecker->({}),
802     checker => sub {
803     my ($self, $todo) = @_;
804    
805     my @nodes = (@{$todo->{node}->child_nodes});
806     my $new_todos = [];
807    
808     while (@nodes) {
809     my $node = shift @nodes;
810     $self->_remove_minuses ($node) and next if ref $node eq 'HASH';
811    
812     my $nt = $node->node_type;
813     if ($nt == 1) {
814     ## not explicitly disallowed
815     $self->{onerror}->(node => $node, type => 'element not allowed');
816     my ($sib, $ch) = $self->_check_get_children ($node, $todo);
817     unshift @nodes, @$sib;
818     push @$new_todos, @$ch;
819     } elsif ($nt == 3 or $nt == 4) {
820     #
821     } elsif ($nt == 5) {
822     unshift @nodes, @{$node->child_nodes};
823     }
824     }
825    
826     ## TODO: MUST be an IRI (absolute)
827     ## TODO: SHOULD be normalized
828    
829     return ($new_todos);
830     },
831     };
832    
833     $Whatpm::ContentChecker::Namespace->{$ATOM_NS}->{loaded} = 1;
834    
835     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24