| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package XML::Validator::Schema::RootNode; |
|
2
|
5
|
|
|
5
|
|
29
|
use strict; |
|
|
5
|
|
|
|
|
7
|
|
|
|
5
|
|
|
|
|
153
|
|
|
3
|
5
|
|
|
5
|
|
60
|
use warnings; |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
142
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
5
|
|
|
5
|
|
36
|
use base 'XML::Validator::Schema::ElementNode'; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
379
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
5
|
|
|
5
|
|
31
|
use XML::Validator::Schema::Util qw(_err); |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
247
|
|
|
8
|
5
|
|
|
5
|
|
24
|
use Carp qw(croak); |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
4634
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
XML::Validator::Schema::RootNode - the root node in a schema document |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
This is an internal module used by XML::Validator::Schema to represent |
|
17
|
|
|
|
|
|
|
the root node in an XML Schema document. Holds references to the |
|
18
|
|
|
|
|
|
|
libraries for the schema document and is responsible for hooking up |
|
19
|
|
|
|
|
|
|
named types to their uses in the node tree at the end of parsing. |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=cut |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub new { |
|
24
|
0
|
|
|
0
|
1
|
|
my $pkg = shift; |
|
25
|
0
|
|
|
|
|
|
my $self = $pkg->SUPER::new(@_); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# start up with empty libraries |
|
28
|
0
|
|
|
|
|
|
$self->{type_library} = XML::Validator::Schema::TypeLibrary->new; |
|
29
|
0
|
|
|
|
|
|
$self->{element_library} = XML::Validator::Schema::ElementLibrary->new; |
|
30
|
0
|
|
|
|
|
|
$self->{attribute_library} = XML::Validator::Schema::AttributeLibrary->new; |
|
31
|
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
return $self; |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# finish typing and references |
|
36
|
|
|
|
|
|
|
sub compile { |
|
37
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
38
|
0
|
|
|
|
|
|
my $element_library = $self->{element_library}; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# put global elements into the library (could move this to ::ElementNode) |
|
41
|
0
|
|
|
|
|
|
foreach my $d ($self->daughters) { |
|
42
|
0
|
0
|
|
|
|
|
if (ref($d) eq 'XML::Validator::Schema::ElementNode') { |
|
43
|
0
|
|
|
|
|
|
$element_library->add(name => $d->{name}, |
|
44
|
|
|
|
|
|
|
obj => $d); |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# complete all element refs first, forming a complete tree |
|
50
|
0
|
|
|
|
|
|
foreach my $element ($self->descendants) { |
|
51
|
0
|
|
|
|
|
|
$self->complete_ref($element); |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# completa all element types, including their attributes |
|
55
|
0
|
|
|
|
|
|
foreach my $element ($self->descendants) { |
|
56
|
0
|
|
|
|
|
|
$self->complete_type($element); |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub complete_ref { |
|
62
|
0
|
|
|
0
|
0
|
|
my ($self, $ref) = @_; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# handle any unresolved attribute types |
|
65
|
0
|
0
|
|
|
|
|
if ($ref->{attr}) { |
|
66
|
0
|
|
|
|
|
|
$self->complete_attr_ref($_) |
|
67
|
0
|
|
|
|
|
|
for (grep { $_->{unresolved_ref} } (@{$ref->{attr}})); |
|
|
0
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# all done unless unresolved |
|
71
|
0
|
0
|
|
|
|
|
return unless $ref->{unresolved_ref}; |
|
72
|
|
|
|
|
|
|
|
|
73
|
0
|
|
|
|
|
|
my $name = $ref->{name}; |
|
74
|
0
|
|
|
|
|
|
my ($element) = $self->{element_library}->find(name => $ref->{name}); |
|
75
|
0
|
0
|
|
|
|
|
_err("Found unresolved reference to element '$name'") |
|
76
|
|
|
|
|
|
|
unless $element; |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# replace the current element |
|
81
|
0
|
|
|
|
|
|
$ref->replace_with($element->copy_at_and_under); |
|
82
|
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
return; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub complete_type { |
|
87
|
0
|
|
|
0
|
0
|
|
my ($self, $element) = @_; |
|
88
|
0
|
|
|
|
|
|
my $library = $self->{type_library}; |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# handle any unresolved attribute types |
|
91
|
0
|
0
|
|
|
|
|
if ($element->{attr}) { |
|
92
|
0
|
|
|
|
|
|
$self->complete_attr_type($_) |
|
93
|
0
|
|
|
|
|
|
for (grep { $_->{unresolved_type} } (@{$element->{attr}})); |
|
|
0
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# all done unless unresolved |
|
97
|
0
|
0
|
|
|
|
|
return unless $element->{unresolved_type}; |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# get type data |
|
100
|
0
|
|
|
|
|
|
my $type_name = $element->{type_name}; |
|
101
|
0
|
|
|
|
|
|
my $type = $library->find(name => $type_name); |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# isn't there? |
|
104
|
0
|
0
|
|
|
|
|
_err("Element '<$element->{name}>' has unrecognized type '$type_name'.") |
|
105
|
|
|
|
|
|
|
unless $type; |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
|
|
108
|
0
|
0
|
|
|
|
|
if ($type->isa('XML::Validator::Schema::ComplexTypeNode')) { |
|
|
|
0
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# can't have daughters for this to work |
|
110
|
0
|
0
|
|
|
|
|
_err("Element '<$element->{name}>' is using a named complexType and has sub-elements of its own. That's not supported.") |
|
111
|
|
|
|
|
|
|
if $element->daughters; |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# replace the current element with one based on the complex node |
|
114
|
0
|
|
|
|
|
|
my $new_node = $type->copy_at_and_under; |
|
115
|
0
|
|
|
|
|
|
$new_node->name($element->{name}); |
|
116
|
0
|
0
|
|
|
|
|
$new_node->{attr} = [ @{ $new_node->{attr} || [] }, |
|
|
0
|
0
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
|
@{ $element->{attr} || [] } ]; |
|
118
|
0
|
|
|
|
|
|
$element->replace_with($new_node); |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
} elsif ($type->isa('XML::Validator::Schema::SimpleType')) { |
|
122
|
0
|
|
|
|
|
|
$element->{type} = $type; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
} else { |
|
125
|
0
|
|
|
|
|
|
croak("Library returned '$type'!"); |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# fixed it |
|
129
|
0
|
|
|
|
|
|
delete $element->{unresolved_type}; |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub complete_attr_type { |
|
133
|
0
|
|
|
0
|
0
|
|
my ($self, $attr) = @_; |
|
134
|
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my $type = $self->{type_library}->find(name => $attr->{type_name}); |
|
136
|
0
|
0
|
|
|
|
|
_err("Attribute '<$attr->{name}>' has unrecognized ". |
|
137
|
|
|
|
|
|
|
"type '$attr->{type_name}'.") |
|
138
|
|
|
|
|
|
|
unless $type; |
|
139
|
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
$attr->{type} = $type; |
|
141
|
0
|
|
|
|
|
|
delete $attr->{unresolved_type}; |
|
142
|
|
|
|
|
|
|
} |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub complete_attr_ref { |
|
145
|
0
|
|
|
0
|
0
|
|
my ($self, $ref) = @_; |
|
146
|
|
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
|
my $attr = $self->{attribute_library}->find(name => $ref->{name}); |
|
148
|
0
|
0
|
|
|
|
|
_err("Attribute reference '$ref->{name}' not found.") |
|
149
|
|
|
|
|
|
|
unless $attr; |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# clone, keep use |
|
152
|
0
|
|
|
|
|
|
my $use = $ref->{required}; |
|
153
|
0
|
|
|
|
|
|
%$ref = %$attr; |
|
154
|
0
|
|
|
|
|
|
$ref->{required} = $use; |
|
155
|
|
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
|
return; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
1; |