/[suikacvs]/messaging/manakai/lib/Message/DOM/Element.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/Element.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.25 - (show annotations) (download)
Sun Nov 11 04:23:32 2007 UTC (17 years ago) by wakaba
Branch: MAIN
Changes since 1.24: +4 -4 lines
++ manakai/lib/Message/DOM/ChangeLog	11 Nov 2007 04:23:26 -0000
2007-11-11  Wakaba  <wakaba@suika.fam.cx>

	* Document.pm, Element.pm (inner_html): Use |Whatpm::HTML::Serializer|
	for getter.

1 ## NOTE: This module will be renamed as Element.pm.
2
3 package Message::DOM::Element;
4 use strict;
5 our $VERSION=do{my @r=(q$Revision: 1.24 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
6 push our @ISA, 'Message::DOM::Node', 'Message::IF::Element',
7 'Message::IF::ElementSelector'; # MUST in Selectors API spec.
8 require Message::DOM::Document;
9
10 sub ____new ($$$$$) {
11 my $self = shift->SUPER::____new (shift);
12 ($$self->{namespace_uri},
13 $$self->{prefix},
14 $$self->{local_name}) = @_;
15 $$self->{attributes} = {};
16 $$self->{child_nodes} = [];
17 return $self;
18 } # ____new
19
20 sub AUTOLOAD {
21 my $method_name = our $AUTOLOAD;
22 $method_name =~ s/.*:://;
23 return if $method_name eq 'DESTROY';
24
25 if ({
26 ## Read-only attributes (trivial accessors)
27 namespace_uri => 1,
28 }->{$method_name}) {
29 no strict 'refs';
30 eval qq{
31 sub $method_name (\$) {
32 return \${\$_[0]}->{$method_name};
33 }
34 };
35 goto &{ $AUTOLOAD };
36 } elsif ({
37 ## Read-write attributes (DOMString, trivial accessors)
38 manakai_base_uri => 1,
39 }->{$method_name}) {
40 no strict 'refs';
41 eval qq{
42 sub $method_name (\$;\$) {
43 if (\@_ > 1) {
44 if (\${\${\$_[0]}->{owner_document}}->{strict_error_checking} and
45 \${\$_[0]}->{manakai_read_only}) {
46 report Message::DOM::DOMException
47 -object => \$_[0],
48 -type => 'NO_MODIFICATION_ALLOWED_ERR',
49 -subtype => 'READ_ONLY_NODE_ERR';
50 }
51 if (defined \$_[1]) {
52 \${\$_[0]}->{$method_name} = ''.\$_[1];
53 } else {
54 delete \${\$_[0]}->{$method_name};
55 }
56 }
57 return \${\$_[0]}->{$method_name};
58 }
59 };
60 goto &{ $AUTOLOAD };
61 } elsif (my $module_name = {
62 query_selector => 'Message::DOM::SelectorsAPI',
63 query_selector_all => 'Message::DOM::SelectorsAPI',
64 }->{$method_name}) {
65 eval qq{ require $module_name } or die $@;
66 goto &{ $AUTOLOAD };
67 } else {
68 require Carp;
69 Carp::croak (qq<Can't locate method "$AUTOLOAD">);
70 }
71 } # AUTOLOAD
72
73 ## TODO: Test for create_element_ns ('', ...)
74
75 ## |Node| attributes
76
77 sub attributes ($) {
78 require Message::DOM::NamedNodeMap;
79 return bless \\($_[0]), 'Message::DOM::NamedNodeMap::AttrMap';
80 } # attributes
81
82 sub base_uri ($) {
83 my $self = $_[0];
84 return $$self->{manakai_base_uri} if defined $$self->{manakai_base_uri};
85
86 local $Error::Depth = $Error::Depth + 1;
87 my $xb = $self->get_attribute_node_ns
88 ('http://www.w3.org/XML/1998/namespace', 'base');
89 unless (defined $xb) {
90 $xb = $self->get_attribute_node_ns (undef, 'xml:base');
91 }
92
93 if ($xb) {
94 my $v = $self->owner_document->implementation->create_uri_reference
95 ($xb->value);
96 if (not defined $v->uri_scheme) { # Relative reference
97 my $xbbase = $xb->base_uri;
98 if (defined $xbbase) {
99 return $v->get_absolute_reference ($xbbase)->uri_reference;
100 }
101 }
102 return $v->uri_reference;
103 }
104
105 my $pe = $$self->{parent_node};
106 while (defined $pe) {
107 my $nt = $pe->node_type;
108 if ($nt == 1 or $nt == 6 or $nt == 9 or $nt == 11) {
109 ## Element, Entity, Document, or DocumentFragment
110 return $pe->base_uri;
111 } elsif ($nt == 5) {
112 ## EntityReference
113 if ($pe->manakai_external) {
114 return $pe->manakai_entity_base_uri;
115 }
116 }
117 $pe = $$pe->{parent_node};
118 }
119 return $pe->base_uri if $pe;
120 return $$self->{owner_document}->base_uri;
121 } # base_uri
122
123 sub local_name ($) { # TODO: HTML5 case
124 return ${$_[0]}->{local_name};
125 } # local_name
126
127 sub manakai_local_name ($) {
128 return ${$_[0]}->{local_name};
129 } # manakai_local_name
130
131 sub namespace_uri ($);
132
133 ## The tag name of the element [DOM1, DOM2].
134 ## Same as |Element.tagName| [DOM3].
135
136 *node_name = \&tag_name;
137
138 sub node_type () { 1 } # ELEMENT_NODE
139
140 sub prefix ($;$) {
141 ## NOTE: No check for new value as Firefox doesn't do.
142 ## See <http://suika.fam.cx/gate/2005/sw/prefix>.
143
144 ## NOTE: Same as trivial setter except "" -> undef
145
146 ## NOTE: Same as |Attr|'s |prefix|.
147
148 if (@_ > 1) {
149 if (${$_[0]}->{manakai_read_only}) {
150 report Message::DOM::DOMException
151 -object => $_[0],
152 -type => 'NO_MODIFICATION_ALLOWED_ERR',
153 -subtype => 'READ_ONLY_NODE_ERR';
154 }
155 if (defined $_[1] and $_[1] ne '') {
156 ${$_[0]}->{prefix} = ''.$_[1];
157 } else {
158 delete ${$_[0]}->{prefix};
159 }
160 }
161 return ${$_[0]}->{prefix};
162 } # prefix
163
164 ## |Element| attributes
165
166 sub manakai_base_uri ($;$);
167
168 ## Defined in |HTMLElement| interface of HTML5
169 sub inner_html ($;$) {
170 my $self = $_[0];
171
172 ## TODO: Setter
173
174 if (${$$self->{owner_document}}->{manakai_is_html}) {
175 require Whatpm::HTML::Serializer;
176 return ${ Whatpm::HTML::Serializer->get_inner_html ($self) };
177 } else {
178 ## TODO: This serializer is not currenly conformant to HTML5.
179 require Whatpm::XMLSerializer;
180 my $r = '';
181 for (@{$self->child_nodes}) {
182 $r .= ${ Whatpm::XMLSerializer->get_outer_xml ($_) };
183 }
184 return $r;
185 }
186 } # inner_html
187
188 sub schema_type_info ($) {
189 require Message::DOM::TypeInfo;
190 my $v = 0;
191 return bless \$v, 'Message::DOM::TypeInfo';
192 ## NOTE: Currently manakai does not support XML Schema, so it is
193 ## always a no-type |TypeInfo|. It is expected that
194 ## a future version of the implementation will return an
195 ## element type definition node that also implement the
196 ## |TypeInfo| interface when the schema language is XML DTD.
197 } # schema_type_info
198
199 ## TODO: HTML5 capitalization
200 sub tag_name ($) {
201 my $self = shift;
202 if (defined $$self->{prefix}) {
203 return $$self->{prefix} . ':' . $$self->{local_name};
204 } else {
205 return $$self->{local_name};
206 }
207 } # tag_name
208
209 ## TODO: Documentation
210 sub manakai_tag_name ($) {
211 my $self = shift;
212 if (defined $$self->{prefix}) {
213 return $$self->{prefix} . ':' . $$self->{local_name};
214 } else {
215 return $$self->{local_name};
216 }
217 } # manakai_tag_name
218
219 ## The |Element| interface - methods
220
221 sub manakai_element_type_match ($$$) {
222 my ($self, $nsuri, $ln) = @_;
223 if (defined $nsuri) {
224 if (defined $$self->{namespace_uri} and $nsuri eq $$self->{namespace_uri}) {
225 return ($ln eq $$self->{local_name});
226 } else {
227 return 0;
228 }
229 } else {
230 if (not defined $$self->{namespace_uri}) {
231 return ($ln eq $$self->{local_name});
232 } else {
233 return 0;
234 }
235 }
236 } # manakai_element_type_match
237
238 sub get_attribute ($$) {
239 my $attr = ${$_[0]}->{attributes};
240 my $name = ''.$_[1];
241
242 ## NOTE: |sort|ing is required so that every |getAttribute|, |setAttribute|,
243 ## |hasAttribute|, |removeAttribute|, or any other namespace unaware
244 ## methods operates on the same node even if there is
245 ## multiple nodes with the same qualified name.
246
247 ## NOTE: Same as |get_attribute_node|, except what is returned.
248
249 for my $ns (sort {$a cmp $b} keys %$attr) {
250 for my $ln (sort {$a cmp $b} keys %{$attr->{$ns}}) {
251 my $node = $attr->{$ns}->{$ln};
252 if ($node->manakai_name eq $name) {
253 return $node->value;
254 }
255 }
256 }
257
258 return undef;
259 } # get_attribute
260
261 sub get_attribute_node ($$) {
262 my $attr = ${$_[0]}->{attributes};
263 my $name = ''.$_[1];
264
265 ## NOTE: Same as |get_attribute|, except what is returned.
266
267 for my $ns (sort {$a cmp $b} keys %$attr) {
268 for my $ln (sort {$a cmp $b} keys %{$attr->{$ns}}) {
269 my $node = $attr->{$ns}->{$ln};
270 if ($node->manakai_name eq $name) {
271 return $node;
272 }
273 }
274 }
275
276 return undef;
277 } # get_attribute_node
278
279 sub get_attribute_ns ($$$) {
280 my $nsuri = defined $_[1] ? ''.$_[1] : '';
281 my $ln = ''.$_[2];
282 if (my $attr = ${$_[0]}->{attributes}->{$nsuri}->{$ln}) {
283 return $attr->value;
284 } else {
285 return undef;
286 }
287 } # get_attribute_ns
288
289 sub get_attribute_node_ns ($$$) {
290 return ${$_[0]}->{attributes}->{defined $_[1] ? ''.$_[1] : ''}->{''.$_[2]};
291 } # get_attribute_node_ns
292
293 *get_elements_by_tag_name = \&Message::DOM::Document::get_elements_by_tag_name;
294
295 *get_elements_by_tag_name_ns
296 = \&Message::DOM::Document::get_elements_by_tag_name_ns;
297
298 sub has_attribute ($$) {
299 my $attr = ${$_[0]}->{attributes};
300 my $name = ''.$_[1];
301
302 for my $ns (keys %$attr) {
303 for my $ln (keys %{$attr->{$ns}}) {
304 my $node = $attr->{$ns}->{$ln};
305 if ($node->manakai_name eq $name) {
306 return 1;
307 }
308 }
309 }
310
311 return 0;
312 } # has_attribute
313
314 sub has_attribute_ns ($$$) {
315 return ${$_[0]}->{attributes}->{defined $_[1] ? ''.$_[1] : ''}->{''.$_[2]}?1:0;
316 } # has_attribute_ns
317
318 sub remove_attribute ($$) {
319 my $attr = ${$_[0]}->{attributes};
320 my $name = ''.$_[1];
321
322 my $list;
323 my $key;
324 my $attr_node;
325 ATTR: {
326 for my $ns (keys %$attr) {
327 $list = $attr->{$ns};
328 for my $ln (keys %$list) {
329 $attr_node = $list->{$ln};
330 if ($attr_node->manakai_name eq $name) {
331 $key = $ln;
332 last ATTR;
333 }
334 }
335 }
336
337 return undef; # not found
338 } # ATTR
339
340 my $od = ${$_[0]}->{owner_document};
341 if ($$od->{strict_error_checking} and ${$_[0]}->{manakai_read_only}) {
342 report Message::DOM::DOMException
343 -object => $_[0],
344 -type => 'NO_MODIFICATION_ALLOWED_ERR',
345 -subtype => 'READ_ONLY_NODE_ERR';
346 }
347
348 delete $list->{$key};
349 delete $$attr_node->{owner_element};
350 $$attr_node->{specified} = 1;
351 delete ${$_[0]}->{manakai_content_attribute_list};
352
353 ## Default attribute
354 local $Error::Depth = $Error::Depth + 1;
355 my $cfg = $od->dom_config;
356 if ($cfg->get_parameter
357 (q<http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute>)) {
358 my $doctype = $od->doctype;
359 if ($doctype) {
360 my $et = $doctype->get_element_type_definition_node
361 ($_[0]->manakai_tag_name);
362 if ($et) {
363 my $at = $et->get_attribute_definition_node ($name);
364 if ($at) {
365 local $$od->{strict_error_checking} = 0;
366 my $copy_asis = $cfg->get_parameter
367 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree>);
368 $cfg->set_parameter
369 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => 1);
370 ADD: {
371 my $def_attr_node;
372 my $def_prefix = $attr_node->prefix;
373 my $def_nsuri = '';
374 my $def_ln;
375 if (defined $def_prefix) {
376 $def_nsuri =
377 $def_prefix eq 'xml' ? q<http://www.w3.org/XML/1998/namespace>:
378 $def_prefix eq 'xmlns' ? q<http://www.w3.org/2000/xmlns/>:
379 $_[0]->lookup_namespace_uri ($def_prefix);
380 unless (defined $def_nsuri) {
381 ## TODO: Namespace well-formedness error...
382 }
383 $def_ln = $attr_node->manakai_local_name;
384 } else {
385 $def_nsuri = $name eq 'xmlns'
386 ? q<http://www.w3.org/2000/xmlns/> : undef;
387 $def_ln = $name;
388 }
389 if ($attr->{defined $def_nsuri ? $def_nsuri : ''}->{$def_ln}) {
390 ## TODO: Namespace well-formedness warning?
391 last ADD;
392 }
393 $def_attr_node = $od->create_attribute_ns
394 ($def_nsuri, [$def_prefix, $def_ln]);
395
396 for my $child (@{$at->child_nodes}) {
397 $def_attr_node->append_child ($child->clone_node (1));
398 }
399 $def_attr_node->manakai_attribute_type ($at->declared_type);
400 $attr->{defined $def_nsuri ? $def_nsuri : ''}->{$def_ln}
401 = $def_attr_node;
402 $$def_attr_node->{owner_element} = $_[0];
403 Scalar::Util::weaken ($$def_attr_node->{owner_element});
404 delete $$def_attr_node->{specified};
405 } # ADD
406 $cfg->set_parameter
407 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => $copy_asis);
408 }
409 }
410 }
411 }
412
413 return undef;
414 } # remove_attribute
415
416 sub remove_attribute_node ($$) {
417 my $od = ${$_[0]}->{owner_document};
418 if ($$od->{strict_error_checking} and ${$_[0]}->{manakai_read_only}) {
419 report Message::DOM::DOMException
420 -object => $_[0],
421 -type => 'NO_MODIFICATION_ALLOWED_ERR',
422 -subtype => 'READ_ONLY_NODE_ERR';
423 }
424
425 my $attr_node = $_[1];
426 my $ln = $attr_node->manakai_local_name;
427 my $attr = ${$_[0]}->{attributes};
428 FIND: {
429 my $nsuri = $attr_node->namespace_uri;
430 my $list = $attr->{defined $nsuri ? $nsuri : ''};
431 my $list_node = $list->{$ln};
432 if (defined $list_node and $list_node eq $attr_node) {
433 delete $list->{$ln};
434 last FIND;
435 }
436
437 report Message::DOM::DOMException
438 -object => $_[0],
439 -type => 'NOT_FOUND_ERR',
440 -subtype => 'NOT_CHILD_ERR';
441 } # FIND
442
443 delete ${$_[0]}->{manakai_content_attribute_list};
444 delete $$attr_node->{owner_element};
445 $$attr_node->{specified} = 1;
446
447 ## Default attribute
448 ## Same as |remove_attribute|'s, except where marked as "***".
449 local $Error::Depth = $Error::Depth + 1;
450 my $cfg = $od->dom_config;
451 if ($cfg->get_parameter
452 (q<http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute>)) {
453 my $doctype = $od->doctype;
454 if ($doctype) {
455 my $et = $doctype->get_element_type_definition_node
456 ($_[0]->manakai_tag_name);
457 if ($et) {
458 my $at = $et->get_attribute_definition_node ($_[1]->manakai_name); # ***
459 if ($at) {
460 local $$od->{strict_error_checking} = 0;
461 my $copy_asis = $cfg->get_parameter
462 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree>);
463 $cfg->set_parameter
464 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => 1);
465 ADD: {
466 my $def_attr_node;
467 my $def_prefix = $attr_node->prefix;
468 my $def_nsuri = '';
469 my $def_ln;
470 if (defined $def_prefix) {
471 $def_nsuri =
472 $def_prefix eq 'xml' ? q<http://www.w3.org/XML/1998/namespace>:
473 $def_prefix eq 'xmlns' ? q<http://www.w3.org/2000/xmlns/>:
474 $_[0]->lookup_namespace_uri ($def_prefix);
475 unless (defined $def_nsuri) {
476 ## TODO: Namespace well-formedness error...
477 }
478 $def_ln = $attr_node->manakai_local_name;
479 } else {
480 $def_nsuri = $attr_node->manakai_name eq 'xmlns'
481 ? q<http://www.w3.org/2000/xmlns/> : undef;
482 $def_ln = $attr_node->manakai_local_name; ## ***
483 }
484 if ($attr->{defined $def_nsuri ? $def_nsuri : ''}->{$def_ln}) {
485 ## TODO: Namespace well-formedness warning?
486 last ADD;
487 }
488 $def_attr_node = $od->create_attribute_ns
489 ($def_nsuri, [$def_prefix, $def_ln]);
490
491 for my $child (@{$at->child_nodes}) {
492 $def_attr_node->append_child ($child->clone_node (1));
493 }
494 $def_attr_node->manakai_attribute_type ($at->declared_type);
495 $attr->{defined $def_nsuri ? $def_nsuri : ''}->{$def_ln}
496 = $def_attr_node;
497 $$def_attr_node->{owner_element} = $_[0];
498 Scalar::Util::weaken ($$def_attr_node->{owner_element});
499 delete $$def_attr_node->{specified};
500 } # ADD
501 $cfg->set_parameter
502 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => $copy_asis);
503 }
504 }
505 }
506 }
507
508 return $_[1];
509 } # remove_attribute_node
510
511 sub remove_attribute_ns ($$$) {
512 my $attr = ${$_[0]}->{attributes};
513
514 my $list = $attr->{defined $_[1] ? $_[1] : ''};
515 my $key = ''.$_[2];
516 my $attr_node = $list->{$key};
517 return undef unless defined $attr_node;
518
519 ## NOTE: Anything below is same as |remove_attribute|'s except "***"
520
521 my $od = ${$_[0]}->{owner_document};
522 if ($$od->{strict_error_checking} and ${$_[0]}->{manakai_read_only}) {
523 report Message::DOM::DOMException
524 -object => $_[0],
525 -type => 'NO_MODIFICATION_ALLOWED_ERR',
526 -subtype => 'READ_ONLY_NODE_ERR';
527 }
528
529 delete $list->{$key};
530 delete $$attr_node->{owner_element};
531 $$attr_node->{specified} = 1;
532 delete ${$_[0]}->{manakai_content_attribute_list};
533
534 ## Default attribute
535 local $Error::Depth = $Error::Depth + 1;
536 my $cfg = $od->dom_config;
537 if ($cfg->get_parameter
538 (q<http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute>)) {
539 my $doctype = $od->doctype;
540 if ($doctype) {
541 my $et = $doctype->get_element_type_definition_node
542 ($_[0]->manakai_tag_name);
543 if ($et) {
544 my $at = $et->get_attribute_definition_node
545 ($attr_node->manakai_name); # ***
546 if ($at) {
547 local $$od->{strict_error_checking} = 0;
548 my $copy_asis = $cfg->get_parameter
549 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree>);
550 $cfg->set_parameter
551 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => 1);
552 ADD: {
553 my $def_attr_node;
554 my $def_prefix = $attr_node->prefix;
555 my $def_nsuri = '';
556 my $def_ln;
557 if (defined $def_prefix) {
558 $def_nsuri =
559 $def_prefix eq 'xml' ? q<http://www.w3.org/XML/1998/namespace>:
560 $def_prefix eq 'xmlns' ? q<http://www.w3.org/2000/xmlns/>:
561 $_[0]->lookup_namespace_uri ($def_prefix);
562 unless (defined $def_nsuri) {
563 ## TODO: Namespace well-formedness error...
564 }
565 } else {
566 $def_nsuri = $attr_node->manakai_name eq 'xmlns'
567 ? q<http://www.w3.org/2000/xmlns/> : undef;
568 }
569 $def_ln = $attr_node->manakai_local_name; # ***
570 if ($attr->{defined $def_nsuri ? $def_nsuri : ''}->{$def_ln}) {
571 ## TODO: Namespace well-formedness warning?
572 last ADD;
573 }
574 $def_attr_node = $od->create_attribute_ns
575 ($def_nsuri, [$def_prefix, $def_ln]);
576
577 for my $child (@{$at->child_nodes}) {
578 $def_attr_node->append_child ($child->clone_node (1));
579 }
580 $def_attr_node->manakai_attribute_type ($at->declared_type);
581 $attr->{defined $def_nsuri ? $def_nsuri : ''}->{$def_ln}
582 = $def_attr_node;
583 $$def_attr_node->{owner_element} = $_[0];
584 Scalar::Util::weaken ($$def_attr_node->{owner_element});
585 delete $$def_attr_node->{specified};
586 } # ADD
587 $cfg->set_parameter
588 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => $copy_asis);
589 }
590 }
591 }
592 }
593
594 return undef;
595 } # remove_attribute_ns
596
597 sub set_attribute ($$$) {
598 my $od = ${$_[0]}->{owner_document};
599 if ($$od->{strict_error_checking}) {
600 if (${$_[0]}->{manakai_read_only}) {
601 report Message::DOM::DOMException
602 -object => $_[0],
603 -type => 'NO_MODIFICATION_ALLOWED_ERR',
604 -subtype => 'READ_ONLY_NODE_ERR';
605 }
606 }
607
608 my $name = ''.$_[1];
609 my $attr = ${$_[0]}->{attributes};
610 my $attr_node;
611 NS: for my $ns (keys %$attr) {
612 for my $ln (keys %{$attr->{$ns}}) {
613 my $node = $attr->{$ns}->{$ln};
614 if ($node->manakai_name eq $name) {
615 $attr_node = $node;
616 last NS;
617 }
618 }
619 }
620
621 local $Error::Depth = $Error::Depth + 1;
622 if (defined $attr_node) {
623 if ($$od->{strict_error_checking}) {
624 $od->create_attribute ($name); # or exception
625 }
626 } else {
627 $attr_node = $od->create_attribute ($name); # return or exception
628 delete ${$_[0]}->{manakai_content_attribute_list};
629 $attr->{''}->{$name} = $attr_node;
630 $$attr_node->{owner_element} = $_[0];
631 Scalar::Util::weaken ($$attr_node->{owner_element});
632
633 if ($od->dom_config->get_parameter
634 (q<http://suika.fam.cx/www/2006/dom-config/dtd-attribute-type>)) {
635 my $doctype = $od->doctype;
636 if (defined $doctype) {
637 my $et = $doctype->get_element_type_definition_node
638 ($_[0]->manakai_tag_name);
639 if (defined $et) {
640 my $at = $et->get_attribute_definition_node ($attr_node->manakai_name);
641 if (defined $at) {
642 $attr_node->manakai_attribute_type ($at->declared_type);
643 }
644 }
645 }
646 }
647 }
648
649 $attr_node->value ($_[2]); # set or exception
650 $attr_node->specified (1);
651 return undef;
652 } # set_attribute
653
654 sub set_attribute_node ($$) {
655 my ($self, $new_attr) = @_;
656 local $Error::Depth = $Error::Depth + 1;
657 my $check = ${$$self->{owner_document}}->{strict_error_checking};
658 if ($check and $$self->{owner_document} ne $new_attr->owner_document) {
659 local $Error::Depth = $Error::Depth - 1;
660 report Message::DOM::DOMException
661 -object => $self,
662 -type => 'WRONG_DOCUMENT_ERR';
663 }
664
665 my $nsuri = $$new_attr->{namespace_uri};
666 $nsuri = '' unless defined $nsuri;
667 my $ln = $$new_attr->{local_name};
668
669 delete $$self->{manakai_content_attribute_list};
670 my $attrs = $$self->{attributes};
671 my $current = $attrs->{$nsuri}->{$ln};
672
673 if (defined $$new_attr->{owner_element}) {
674 if (defined $current and $current eq $new_attr) {
675 ## No effect
676 return undef; # no return value
677 } else {
678 local $Error::Depth = $Error::Depth - 1;
679 report Message::DOM::DOMException
680 -object => $self,
681 -type => 'INUSE_ATTRIBUTE_ERR';
682 }
683 } elsif ($check and $$self->{manakai_read_only}) {
684 report Message::DOM::DOMException
685 -object => $self,
686 -type => 'NO_MODIFICATION_ALLOWED_ERR',
687 -subtype => 'READ_ONLY_NODE_ERR';
688 }
689
690 $attrs->{$nsuri}->{$ln} = $new_attr;
691 $$new_attr->{owner_element} = $self;
692 Scalar::Util::weaken ($$new_attr->{owner_element});
693 $$new_attr->{specified} = 1;
694
695 if (defined $current) {
696 delete $$current->{owner_element};
697 $$current->{specified} = 1;
698 }
699 return $current;
700 } # set_attribute_node
701
702 *set_attribute_node_ns = \&set_attribute_node;
703
704 ## The second parameter only supports manakai extended way
705 ## to specify qualified name - "[$prefix, $local_name]" ## TODO: Document
706 sub set_attribute_ns ($$$$) {
707 my $prefix;
708 my $lname;
709 if (ref $_[2] eq 'ARRAY') {
710 ($prefix, $lname) = @{$_[2]};
711 } else {
712 ($prefix, $lname) = split /:/, $_[2], 2;
713 ($prefix, $lname) = (undef, $prefix) unless defined $lname;
714 }
715
716 my $od = ${$_[0]}->{owner_document};
717 if ($$od->{strict_error_checking}) {
718 if (${$_[0]}->{manakai_read_only}) {
719 report Message::DOM::DOMException
720 -object => $_[0],
721 -type => 'NO_MODIFICATION_ALLOWED_ERR',
722 -subtype => 'READ_ONLY_NODE_ERR';
723 }
724 }
725
726 my $attr = ${$_[0]}->{attributes};
727 my $attr_node = $attr->{defined $_[1] ? ''.$_[1] : ''}->{$lname};
728
729 local $Error::Depth = $Error::Depth + 1;
730 if (defined $attr_node) {
731 if ($$od->{strict_error_checking}) {
732 $od->create_attribute_ns ($_[1], [$prefix, $lname]); # name exception
733 }
734 } else {
735 $attr_node = $od->create_attribute_ns
736 ($_[1], [$prefix, $lname]); # or exception
737 delete ${$_[0]}->{manakai_content_attribute_list};
738 $attr->{defined $_[1] ? ''.$_[1] : ''}->{$lname} = $attr_node;
739 $$attr_node->{owner_element} = $_[0];
740 Scalar::Util::weaken ($$attr_node->{owner_element});
741
742 if ($od->dom_config->get_parameter
743 (q<http://suika.fam.cx/www/2006/dom-config/dtd-attribute-type>)) {
744 my $doctype = $od->doctype;
745 if (defined $doctype) {
746 my $et = $doctype->get_element_type_definition_node
747 ($_[0]->manakai_tag_name);
748 if (defined $et) {
749 my $at = $et->get_attribute_definition_node ($attr_node->manakai_name);
750 if (defined $at) {
751 $attr_node->manakai_attribute_type ($at->declared_type);
752 }
753 }
754 }
755 }
756 }
757
758 $attr_node->value ($_[3]); # set or exception
759 $attr_node->prefix ($prefix);
760 $attr_node->specified (1);
761 return undef;
762 } # set_attribute_ns
763
764 sub set_id_attribute ($$$) {
765 if (${${$_[0]}->{owner_document}}->{strict_error_checking} and
766 ${$_[0]}->{manakai_read_only}) {
767 report Message::DOM::DOMException
768 -object => $_[0],
769 -type => 'NO_MODIFICATION_ALLOWED_ERR',
770 -subtype => 'READ_ONLY_NODE_ERR';
771 }
772
773 my $attr = $_[0]->get_attribute_node ($_[1]);
774 if (not defined $attr) {
775 report Message::DOM::DOMException
776 -object => $_[0],
777 -type => 'NOT_FOUND_ERR',
778 -subtype => 'NOT_CHILD_ERR';
779 } else {
780 local $Error::Depth = $Error::Depth + 1;
781 $attr->is_id ($_[2]); # or exception
782 }
783 return;
784 } # set_id_attribute
785
786 sub set_id_attribute_ns ($$$$) {
787 if (${${$_[0]}->{owner_document}}->{strict_error_checking} and
788 ${$_[0]}->{manakai_read_only}) {
789 report Message::DOM::DOMException
790 -object => $_[0],
791 -type => 'NO_MODIFICATION_ALLOWED_ERR',
792 -subtype => 'READ_ONLY_NODE_ERR';
793 }
794
795 my $attr = $_[0]->get_attribute_node_ns ($_[1], $_[2]);
796 if (not defined $attr) {
797 report Message::DOM::DOMException
798 -object => $_[0],
799 -type => 'NOT_FOUND_ERR',
800 -subtype => 'NOT_CHILD_ERR';
801 } else {
802 local $Error::Depth = $Error::Depth + 1;
803 $attr->is_id ($_[2]);
804 }
805 return;
806 } # set_id_attribute_ns
807
808 sub set_id_attribute_node ($$$$) {
809 if (${${$_[0]}->{owner_document}}->{strict_error_checking} and
810 ${$_[0]}->{manakai_read_only}) {
811 report Message::DOM::DOMException
812 -object => $_[0],
813 -type => 'NO_MODIFICATION_ALLOWED_ERR',
814 -subtype => 'READ_ONLY_NODE_ERR';
815 }
816
817 my $oe = $_[1]->owner_element;
818 if ($oe ne $_[0]) {
819 report Message::DOM::DOMException
820 -object => $_[0],
821 -type => 'NOT_FOUND_ERR',
822 -subtype => 'NOT_CHILD_ERR';
823 } else {
824 local $Error::Depth = $Error::Depth + 1;
825 $_[1]->is_id ($_[2]);
826 }
827 return;
828 } # set_id_attribute_node
829
830 package Message::IF::Element;
831 package Message::IF::ElementSelector;
832
833 package Message::DOM::Document;
834
835 sub create_element ($$) {
836 my $self = $_[0];
837 if ($$self->{strict_error_checking}) {
838 my $xv = $self->xml_version;
839 ## TODO: HTML Document ??
840 if (defined $xv) {
841 if ($xv eq '1.0' and
842 $_[1] =~ /\A\p{InXML_NameStartChar10}\p{InXMLNameChar10}*\z/) {
843 #
844 } elsif ($xv eq '1.1' and
845 $_[1] =~ /\A\p{InXMLNameStartChar11}\p{InXMLNameChar11}*\z/) {
846 #
847 } else {
848 report Message::DOM::DOMException
849 -object => $self,
850 -type => 'INVALID_CHARACTER_ERR',
851 -subtype => 'MALFORMED_NAME_ERR';
852 }
853 }
854 }
855 ## TODO: HTML5
856
857 my $r = Message::DOM::Element->____new ($self, undef, undef, $_[1]);
858
859 ## -- Default attributes
860 {
861 local $Error::Depth = $Error::Depth + 1;
862 my $cfg = $self->dom_config;
863 return $r
864 unless $cfg->get_parameter
865 (q<http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute>);
866
867 my $doctype = $self->doctype;
868 return $r unless defined $doctype;
869
870 my $et = $doctype->get_element_type_definition_node ($_[1]);
871 return $r unless defined $et;
872
873 my $orig_strict = $self->strict_error_checking;
874 $self->strict_error_checking (0);
875
876 my %gattr;
877 my %has_attr;
878 my %pfx_to_uri;
879 my $copy_asis = $cfg->get_parameter
880 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree>);
881 $cfg->set_parameter
882 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => 1);
883
884 for my $at (@{$et->attribute_definitions}) {
885 my $at_default = $at->default_type;
886 if ($at_default == 4 or $at_default == 1) {
887 # EXPLICIT_DEFAULT, FIXED_DEFAULT
888 my ($nn1, $nn2) = split /:/, $at->node_name;
889 if (defined $nn2) { # prefixed
890 if ($nn1 eq 'xmlns') {
891 ## TODO: NCName check, prefix check and NSURI check
892 my $attr = $self->create_attribute_ns
893 (q<http://www.w3.org/2000/xmlns/>, [$nn1, $nn2]);
894 for my $at_child (@{$at->child_nodes}) {
895 $attr->append_child ($at_child->clone_node (1));
896 }
897 $attr->manakai_attribute_type ($at->declared_type);
898 my $nsuri = $attr->value;
899 ## TODO: Namespace well-formedness check (NSURI), v1.1 chk
900 $pfx_to_uri{$nn2} = $nsuri;
901 $r->set_attribute_node_ns ($attr);
902 ## NOTE: This method changes |specified| flag
903 $attr->specified (0);
904 $has_attr{q<http://www.w3.org/2000/xmlns/>}->{$nn2} = 1;
905 } else {
906 ## TODO: NCName check
907 $gattr{$nn1}->{$nn2} = $at;
908 }
909 } else { # no prefixed
910 my $attr;
911 if ($nn1 eq 'xmlns') {
912 $attr = $self->create_attribute_ns
913 (q<http://www.w3.org/2000/xmlns/>, 'xmlns');
914 $has_attr{q<http://www.w3.org/2000/xmlns/>}->{xmlns} = 1;
915 } else {
916 $attr = $self->create_attribute_ns (undef, $nn1);
917 ## TODO: NCName check
918 }
919 for my $at_child (@{$at->child_nodes}) {
920 $attr->append_child ($at_child->clone_node (1));
921 }
922 $attr->manakai_attribute_type ($at->declared_type);
923 ## TODO: Namespace well-formedness check (NSURI)
924 $r->set_attribute_node_ns ($attr);
925 ## NOTE: This method changes |specified| flag
926 $attr->specified (0);
927 }
928 }
929 } # attrdefs
930 for my $pfx (keys %gattr) {
931 my $nsuri = $pfx_to_uri{$pfx};
932 unless (defined $nsuri) {
933 ## TODO: Namespace well-formedness error
934 }
935 LN: for my $ln (keys %{$gattr{$pfx}}) {
936 if ($has_attr{defined $nsuri ? $nsuri : ''}->{$ln}) {
937 ## TODO: Namespace well-formedness error
938 next LN;
939 }
940 ## TODO: NCName check, prefix check and NSURI check
941 my $at = $gattr{$pfx}->{$ln};
942 my $attr = $self->create_attribute_ns ($nsuri, [$pfx, $ln]);
943 for my $at_child (@{$at->child_nodes}) {
944 $attr->append_child ($at_child->clone_node (1));
945 }
946 $attr->manakai_attribute_type ($at->declared_type);
947 $r->set_attribute_node_ns ($attr);
948 ## NOTE: This method changes |specified| flag
949 $attr->specified (0);
950 $has_attr{defined $nsuri ? $nsuri : ''}->{$ln} = 1;
951 } # LN
952 } # pfx
953 $cfg->set_parameter
954 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => $copy_asis);
955 $self->strict_error_checking ($orig_strict);
956 }
957
958 return $r;
959 } # create_element
960
961 sub create_element_ns ($$$) {
962 my $self = $_[0];
963 my ($prefix, $lname);
964 if (ref $_[2] eq 'ARRAY') {
965 ($prefix, $lname) = @{$_[2]};
966 } else {
967 ($prefix, $lname) = split /:/, $_[2], 2;
968 ($prefix, $lname) = (undef, $prefix) unless defined $lname;
969 }
970 my $nsuri = defined $_[1] ? $_[1] eq '' ? undef : $_[1] : undef;
971
972 if ($$self->{strict_error_checking}) {
973 my $xv = $self->xml_version;
974 ## TODO: HTML Document ?? (NOT_SUPPORTED_ERR is different from what Web browsers do)
975 if (defined $xv) {
976 if ($xv eq '1.0') {
977 if (ref $_[2] eq 'ARRAY' or
978 $_[2] =~ /\A\p{InXML_NameStartChar10}\p{InXMLNameChar10}*\z/) {
979 if (defined $prefix) {
980 if ($prefix =~ /\A\p{InXML_NCNameStartChar10}\p{InXMLNCNameChar10}*\z/) {
981 #
982 } else {
983 report Message::DOM::DOMException
984 -object => $self,
985 -type => 'NAMESPACE_ERR',
986 -subtype => 'MALFORMED_QNAME_ERR';
987 }
988 }
989 if ($lname =~ /\A\p{InXML_NCNameStartChar10}\p{InXMLNCNameChar10}*\z/) {
990 #
991 } else {
992 report Message::DOM::DOMException
993 -object => $self,
994 -type => 'NAMESPACE_ERR',
995 -subtype => 'MALFORMED_QNAME_ERR';
996 }
997 } else {
998 report Message::DOM::DOMException
999 -object => $self,
1000 -type => 'INVALID_CHARACTER_ERR',
1001 -subtype => 'MALFORMED_NAME_ERR';
1002 }
1003 } elsif ($xv eq '1.1') {
1004 if (ref $_[2] eq 'ARRAY' or
1005 $_[2] =~ /\A\p{InXML_NameStartChar10}\p{InXMLNameChar10}*\z/) {
1006 if (defined $prefix) {
1007 if ($prefix =~ /\A\p{InXMLNCNameStartChar11}\p{InXMLNCNameChar11}*\z/) {
1008 #
1009 } else {
1010 report Message::DOM::DOMException
1011 -object => $self,
1012 -type => 'NAMESPACE_ERR',
1013 -subtype => 'MALFORMED_QNAME_ERR';
1014 }
1015 }
1016 if ($lname =~ /\A\p{InXMLNCNameStartChar11}\p{InXMLNCNameChar11}*\z/) {
1017 #
1018 } else {
1019 report Message::DOM::DOMException
1020 -object => $self,
1021 -type => 'NAMESPACE_ERR',
1022 -subtype => 'MALFORMED_QNAME_ERR';
1023 }
1024 } else {
1025 report Message::DOM::DOMException
1026 -object => $self,
1027 -type => 'INVALID_CHARACTER_ERR',
1028 -subtype => 'MALFORMED_NAME_ERR';
1029 }
1030 } else {
1031 die "create_attribute_ns: XML version |$xv| is not supported";
1032 }
1033 }
1034
1035 if (defined $prefix) {
1036 if (not defined $nsuri) {
1037 report Message::DOM::DOMException
1038 -object => $self,
1039 -type => 'NAMESPACE_ERR',
1040 -subtype => 'PREFIXED_NULLNS_ERR';
1041 } elsif ($prefix eq 'xml' and
1042 $nsuri ne q<http://www.w3.org/XML/1998/namespace>) {
1043 report Message::DOM::DOMException
1044 -object => $self,
1045 -type => 'NAMESPACE_ERR',
1046 -subtype => 'XMLPREFIX_NONXMLNS_ERR';
1047 } elsif ($prefix eq 'xmlns' and
1048 $nsuri ne q<http://www.w3.org/2000/xmlns/>) {
1049 report Message::DOM::DOMException
1050 -object => $self,
1051 -type => 'NAMESPACE_ERR',
1052 -subtype => 'XMLNSPREFIX_NONXMLNSNS_ERR';
1053 } elsif ($nsuri eq q<http://www.w3.org/2000/xmlns/> and
1054 $prefix ne 'xmlns') {
1055 report Message::DOM::DOMException
1056 -object => $self,
1057 -type => 'NAMESPACE_ERR',
1058 -subtype => 'NONXMLNSPREFIX_XMLNSNS_ERR';
1059 }
1060 } else { # no prefix
1061 if ($lname eq 'xmlns' and
1062 (not defined $nsuri or $nsuri ne q<http://www.w3.org/2000/xmlns/>)) {
1063 report Message::DOM::DOMException
1064 -object => $self,
1065 -type => 'NAMESPACE_ERR',
1066 -subtype => 'XMLNS_NONXMLNSNS_ERR';
1067 } elsif (not defined $nsuri) {
1068 #
1069 } elsif ($nsuri eq q<http://www.w3.org/2000/xmlns/> and
1070 $lname ne 'xmlns') {
1071 report Message::DOM::DOMException
1072 -object => $self,
1073 -type => 'NAMESPACE_ERR',
1074 -subtype => 'NONXMLNSPREFIX_XMLNSNS_ERR';
1075 }
1076 }
1077 }
1078
1079 ## -- Choose the most apppropriate class for the element
1080 my $class = 'Message::DOM::Element';
1081 if (defined $nsuri) {
1082 if ($nsuri eq q<http://www.w3.org/1999/xhtml>) {
1083 require Message::DOM::HTML::HTMLElement;
1084 $class = {
1085 a => 'Message::DOM::HTML::HTMLAnchorElement',
1086 area => 'Message::DOM::HTML::HTMLAreaElement',
1087 audio => 'Message::DOM::HTML::HTMLAudioElement',
1088 base => 'Message::DOM::HTML::HTMLBaseElement',
1089 body => 'Message::DOM::HTML::HTMLBodyElement',
1090 canvas => 'Message::DOM::HTML::HTMLCanvasElement',
1091 command => 'Message::DOM::HTML::HTMLCommandElement',
1092 datagrid => 'Message::DOM::HTML::HTMLDataGridElement',
1093 details => 'Message::DOM::HTML::HTMLDetailsElement',
1094 embed => 'Message::DOM::HTML::HTMLEmbedElement',
1095 'event-source' => 'Message::DOM::HTML::HTMLEventSourceElement',
1096 font => 'Message::DOM::HTML::HTMLFontElement',
1097 head => 'Message::DOM::HTML::HTMLHeadElement',
1098 html => 'Message::DOM::HTML::HTMLHtmlElement',
1099 iframe => 'Message::DOM::HTML::HTMLIFrameElement',
1100 img => 'Message::DOM::HTML::HTMLImageElement',
1101 li => 'Message::DOM::HTML::HTMLLIElement',
1102 link => 'Message::DOM::HTML::HTMLLinkElement',
1103 map => 'Message::DOM::HTML::HTMLMapElement',
1104 menu => 'Message::DOM::HTML::HTMLMenuElement',
1105 meta => 'Message::DOM::HTML::HTMLMetaElement',
1106 meter => 'Message::DOM::HTML::HTMLMeterElement',
1107 del => 'Message::DOM::HTML::HTMLModElement',
1108 ins => 'Message::DOM::HTML::HTMLModElement',
1109 object => 'Message::DOM::HTML::HTMLObjectElement',
1110 ol => 'Message::DOM::HTML::HTMLOListElement',
1111 param => 'Message::DOM::HTML::HTMLParamElement',
1112 progress => 'Message::DOM::HTML::HTMLProgressElement',
1113 blockquote => 'Message::DOM::HTML::HTMLQuoteElement',
1114 q => 'Message::DOM::HTML::HTMLQuoteElement',
1115 script => 'Message::DOM::HTML::HTMLScriptElement',
1116 source => 'Message::DOM::HTML::HTMLSourceElement',
1117 style => 'Message::DOM::HTML::HTMLStyleElement',
1118 table => 'Message::DOM::HTML::HTMLTableElement',
1119 td => 'Message::DOM::HTML::HTMLTableCellElement',
1120 col => 'Message::DOM::HTML::HTMLTableColElement',
1121 colgroup => 'Message::DOM::HTML::HTMLTableColElement',
1122 th => 'Message::DOM::HTML::HTMLTableHeaderCellElement',
1123 tr => 'Message::DOM::HTML::HTMLTableRowElement',
1124 tbody => 'Message::DOM::HTML::HTMLTableSectionElement',
1125 tfoot => 'Message::DOM::HTML::HTMLTableSectionElement',
1126 thead => 'Message::DOM::HTML::HTMLTableSectionElement',
1127 time => 'Message::DOM::HTML::HTMLTimeElement',
1128 video => 'Message::DOM::HTML::HTMLVideoElement',
1129 }->{$lname} || 'Message::DOM::HTML::HTMLElement';
1130 } elsif ($nsuri eq q<http://www.w3.org/2005/Atom>) {
1131 require Message::DOM::Atom::AtomElement;
1132 $class = {
1133 author => 'Message::DOM::Atom::AtomElement::AtomPersonConstruct',
1134 category => 'Message::DOM::Atom::AtomElement::AtomCategoryElement',
1135 content => 'Message::DOM::Atom::AtomElement::AtomContentElement',
1136 contributor => 'Message::DOM::Atom::AtomElement::AtomPersonConstruct',
1137 entry => 'Message::DOM::Atom::AtomElement::AtomEntryElement',
1138 feed => 'Message::DOM::Atom::AtomElement::AtomFeedElement',
1139 generator => 'Message::DOM::Atom::AtomElement::AtomGeneratorElement',
1140 link => 'Message::DOM::Atom::AtomElement::AtomLinkElement',
1141 published => 'Message::DOM::Atom::AtomElement::AtomDateConstruct',
1142 rights => 'Message::DOM::Atom::AtomElement::AtomTextConstruct',
1143 source => 'Message::DOM::Atom::AtomElement::AtomSourceElement',
1144 subtitle => 'Message::DOM::Atom::AtomElement::AtomTextConstruct',
1145 summary => 'Message::DOM::Atom::AtomElement::AtomTextConstruct',
1146 title => 'Message::DOM::Atom::AtomElement::AtomTextConstruct',
1147 updated => 'Message::DOM::Atom::AtomElement::AtomDateConstruct',
1148 }->{$lname} || 'Message::DOM::Atom::AtomElement';
1149 }
1150 }
1151
1152 my $r = $class->____new ($self, $nsuri, $prefix, $lname);
1153
1154 ## -- Default attributes
1155 {
1156 local $Error::Depth = $Error::Depth + 1;
1157 my $cfg = $self->dom_config;
1158 return $r
1159 unless $cfg->get_parameter
1160 (q<http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute>);
1161
1162 my $doctype = $self->doctype;
1163 return $r unless defined $doctype;
1164
1165 my $et = $doctype->get_element_type_definition_node
1166 (defined $prefix ? $prefix . ':' . $lname : $lname);
1167 return $r unless defined $et;
1168
1169 my $orig_strict = $self->strict_error_checking;
1170 $self->strict_error_checking (0);
1171
1172 my %gattr;
1173 my %has_attr;
1174 my %pfx_to_uri;
1175 my $copy_asis = $cfg->get_parameter
1176 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree>);
1177 $cfg->set_parameter
1178 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => 1);
1179
1180 for my $at (@{$et->attribute_definitions}) {
1181 my $at_default = $at->default_type;
1182 if ($at_default == 4 or $at_default == 1) {
1183 # EXPLICIT_DEFAULT, FIXED_DEFAULT
1184 my ($nn1, $nn2) = split /:/, $at->node_name;
1185 if (defined $nn2) { # prefixed
1186 if ($nn1 eq 'xmlns') {
1187 ## TODO: NCName check, prefix check and NSURI check
1188 my $attr = $self->create_attribute_ns
1189 (q<http://www.w3.org/2000/xmlns/>, [$nn1, $nn2]);
1190 for my $at_child (@{$at->child_nodes}) {
1191 $attr->append_child ($at_child->clone_node (1));
1192 }
1193 $attr->manakai_attribute_type ($at->declared_type);
1194 my $nsuri = $attr->value;
1195 ## TODO: Namespace well-formedness check (NSURI), v1.1 chk
1196 $pfx_to_uri{$nn2} = $nsuri;
1197 $r->set_attribute_node_ns ($attr);
1198 ## NOTE: This method changes |specified| flag
1199 $attr->specified (0);
1200 $has_attr{q<http://www.w3.org/2000/xmlns/>}->{$nn2} = 1;
1201 } else {
1202 ## TODO: NCName check
1203 $gattr{$nn1}->{$nn2} = $at;
1204 }
1205 } else { # no prefixed
1206 my $attr;
1207 if ($nn1 eq 'xmlns') {
1208 $attr = $self->create_attribute_ns
1209 (q<http://www.w3.org/2000/xmlns/>, 'xmlns');
1210 $has_attr{q<http://www.w3.org/2000/xmlns/>}->{xmlns} = 1;
1211 } else {
1212 $attr = $self->create_attribute_ns (undef, $nn1);
1213 ## TODO: NCName check
1214 }
1215 for my $at_child (@{$at->child_nodes}) {
1216 $attr->append_child ($at_child->clone_node (1));
1217 }
1218 $attr->manakai_attribute_type ($at->declared_type);
1219 ## TODO: Namespace well-formedness check (NSURI)
1220 $r->set_attribute_node_ns ($attr);
1221 ## NOTE: This method changes |specified| flag
1222 $attr->specified (0);
1223 }
1224 }
1225 } # attrdefs
1226 for my $pfx (keys %gattr) {
1227 my $nsuri = $pfx_to_uri{$pfx};
1228 unless (defined $nsuri) {
1229 ## TODO: Namespace well-formedness error
1230 }
1231 LN: for my $ln (keys %{$gattr{$pfx}}) {
1232 if ($has_attr{defined $nsuri ? $nsuri : ''}->{$ln}) {
1233 ## TODO: Namespace well-formedness error
1234 next LN;
1235 }
1236 ## TODO: NCName check, prefix check and NSURI check
1237 my $at = $gattr{$pfx}->{$ln};
1238 my $attr = $self->create_attribute_ns ($nsuri, [$pfx, $ln]);
1239 for my $at_child (@{$at->child_nodes}) {
1240 $attr->append_child ($at_child->clone_node (1));
1241 }
1242 $attr->manakai_attribute_type ($at->declared_type);
1243 $r->set_attribute_node_ns ($attr);
1244 ## NOTE: This method changes |specified| flag
1245 $attr->specified (0);
1246 $has_attr{defined $nsuri ? $nsuri : ''}->{$ln} = 1;
1247 } # LN
1248 } # pfx
1249 $cfg->set_parameter
1250 (q<http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree> => $copy_asis);
1251 $self->strict_error_checking ($orig_strict);
1252 }
1253
1254 return $r;
1255 } # create_element_ns
1256
1257 =head1 LICENSE
1258
1259 Copyright 2007 Wakaba <w@suika.fam.cx>
1260
1261 This program is free software; you can redistribute it and/or
1262 modify it under the same terms as Perl itself.
1263
1264 =cut
1265
1266 1;
1267 ## $Date: 2007/09/24 10:16:14 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24