line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyrights 2006-2019 by [Mark Overmeer ]. |
2
|
|
|
|
|
|
|
# For other contributors see ChangeLog. |
3
|
|
|
|
|
|
|
# See the manual pages for details on the licensing terms. |
4
|
|
|
|
|
|
|
# Pod stripped from pm file by OODoc 2.02. |
5
|
|
|
|
|
|
|
# This code is part of distribution XML-Compile. Meta-POD processed with |
6
|
|
|
|
|
|
|
# OODoc into POD and HTML manual-pages. See README.md |
7
|
|
|
|
|
|
|
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package XML::Compile::Schema::NameSpaces; |
10
|
50
|
|
|
50
|
|
358
|
use vars '$VERSION'; |
|
50
|
|
|
|
|
105
|
|
|
50
|
|
|
|
|
2566
|
|
11
|
|
|
|
|
|
|
$VERSION = '1.62'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
50
|
|
|
50
|
|
292
|
use warnings; |
|
50
|
|
|
|
|
98
|
|
|
50
|
|
|
|
|
1171
|
|
15
|
50
|
|
|
50
|
|
241
|
use strict; |
|
50
|
|
|
|
|
96
|
|
|
50
|
|
|
|
|
1086
|
|
16
|
|
|
|
|
|
|
|
17
|
50
|
|
|
50
|
|
222
|
use Log::Report 'xml-compile'; |
|
50
|
|
|
|
|
99
|
|
|
50
|
|
|
|
|
271
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
use XML::Compile::Util |
20
|
50
|
|
|
50
|
|
13424
|
qw/pack_type unpack_type pack_id unpack_id SCHEMA2001/; |
|
50
|
|
|
|
|
106
|
|
|
50
|
|
|
|
|
3592
|
|
21
|
|
|
|
|
|
|
|
22
|
50
|
|
|
50
|
|
355
|
use XML::Compile::Schema::BuiltInTypes qw/%builtin_types/; |
|
50
|
|
|
|
|
94
|
|
|
50
|
|
|
|
|
94191
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub new($@) |
26
|
52
|
|
|
52
|
1
|
153
|
{ my $class = shift; |
27
|
52
|
|
|
|
|
270
|
(bless {}, $class)->init( {@_} ); |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub init($) |
31
|
52
|
|
|
52
|
0
|
139
|
{ my ($self, $args) = @_; |
32
|
52
|
|
|
|
|
291
|
$self->{tns} = {}; |
33
|
52
|
|
|
|
|
160
|
$self->{sgs} = {}; |
34
|
52
|
|
|
|
|
147
|
$self->{use} = []; |
35
|
52
|
|
|
|
|
293
|
$self; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
39
|
9
|
|
|
9
|
1
|
367
|
sub list() { keys %{shift->{tns}} } |
|
9
|
|
|
|
|
35
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub namespace($) |
43
|
4651
|
|
|
4651
|
1
|
10140
|
{ my $nss = $_[0]->{tns}{$_[1]}; |
44
|
4651
|
100
|
|
|
|
11356
|
$nss ? @$nss : (); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub add(@) |
49
|
58
|
|
|
58
|
1
|
144
|
{ my $self = shift; |
50
|
58
|
|
|
|
|
176
|
foreach my $instance (@_) |
51
|
|
|
|
|
|
|
{ # With the "new" targetNamespace attribute on any attribute, one |
52
|
|
|
|
|
|
|
# schema may have contribute to multiple tns's. Also, I have |
53
|
|
|
|
|
|
|
# encounted schema's without elements, but |
54
|
58
|
|
|
|
|
289
|
my @tnses = $instance->tnses; |
55
|
58
|
50
|
|
|
|
242
|
@tnses or @tnses = '(none)'; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# newest definitions overrule earlier. |
58
|
58
|
|
|
|
|
297
|
unshift @{$self->{tns}{$_}}, $instance |
59
|
58
|
|
|
|
|
171
|
for @tnses; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# inventory where to find definitions which belong to some |
62
|
|
|
|
|
|
|
# substitutionGroup. |
63
|
58
|
|
|
|
|
131
|
while(my($base,$ext) = each %{$instance->sgs}) |
|
63
|
|
|
|
|
260
|
|
64
|
5
|
|
33
|
|
|
39
|
{ $self->{sgs}{$base}{$_} ||= $instance for @$ext; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
} |
67
|
58
|
|
|
|
|
181
|
@_; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub use($) |
72
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
73
|
0
|
|
|
|
|
0
|
push @{$self->{use}}, @_; |
|
0
|
|
|
|
|
0
|
|
74
|
0
|
|
|
|
|
0
|
@{$self->{use}}; |
|
0
|
|
|
|
|
0
|
|
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
4650
|
|
|
4650
|
1
|
9476
|
sub schemas($) { $_[0]->namespace($_[1]) } |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub allSchemas() |
82
|
2
|
|
|
2
|
1
|
4
|
{ my $self = shift; |
83
|
2
|
|
|
|
|
7
|
map {$self->schemas($_)} $self->list; |
|
2
|
|
|
|
|
5
|
|
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub find($$;$) |
88
|
3869
|
|
|
3869
|
1
|
6821
|
{ my ($self, $kind) = (shift, shift); |
89
|
3869
|
50
|
|
|
|
10965
|
my ($ns, $name) = (@_%2==1) ? (unpack_type shift) : (shift, shift); |
90
|
3869
|
|
|
|
|
7384
|
my %opts = @_; |
91
|
|
|
|
|
|
|
|
92
|
3869
|
50
|
|
|
|
6963
|
defined $ns or return undef; |
93
|
3869
|
|
|
|
|
8070
|
my $label = pack_type $ns, $name; # re-pack unpacked for consistency |
94
|
|
|
|
|
|
|
|
95
|
3869
|
|
|
|
|
7969
|
foreach my $schema ($self->schemas($ns)) |
96
|
2508
|
|
|
|
|
7088
|
{ my $def = $schema->find($kind, $label); |
97
|
2508
|
100
|
|
|
|
10699
|
return $def if defined $def; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
1623
|
50
|
|
|
|
2731
|
my $used = exists $opts{include_used} ? $opts{include_used} : 1; |
101
|
1623
|
50
|
|
|
|
2920
|
$used or return undef; |
102
|
|
|
|
|
|
|
|
103
|
1623
|
|
|
|
|
1853
|
foreach my $use ( @{$self->{use}} ) |
|
1623
|
|
|
|
|
2774
|
|
104
|
0
|
|
|
|
|
0
|
{ my $def = $use->namespaces->find($kind, $label, include_used => 0); |
105
|
0
|
0
|
|
|
|
0
|
return $def if defined $def; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
1623
|
|
|
|
|
4509
|
undef; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub doesExtend($$) |
113
|
815
|
|
|
815
|
1
|
2084
|
{ my ($self, $ext, $base) = @_; |
114
|
815
|
100
|
|
|
|
1640
|
return 1 if $ext eq $base; |
115
|
800
|
50
|
|
|
|
1537
|
return 0 if $ext =~ m/^unnamed /; |
116
|
|
|
|
|
|
|
|
117
|
800
|
|
|
|
|
1007
|
my ($node, $super, $subnode); |
118
|
800
|
100
|
|
|
|
1353
|
if(my $st = $self->find(simpleType => $ext)) |
|
|
100
|
|
|
|
|
|
119
|
|
|
|
|
|
|
{ # pure simple type |
120
|
86
|
|
|
|
|
141
|
$node = $st->{node}; |
121
|
86
|
100
|
|
|
|
229
|
if(($subnode) = $node->getChildrenByLocalName('restriction')) |
122
|
80
|
|
|
|
|
922
|
{ $super = $subnode->getAttribute('base'); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
# list an union currently ignored |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
elsif(my $ct = $self->find(complexType => $ext)) |
127
|
4
|
|
|
|
|
9
|
{ $node = $ct->{node}; |
128
|
|
|
|
|
|
|
# getChildrenByLocalName returns list, we know size one |
129
|
4
|
100
|
|
|
|
19
|
if(my($sc) = $node->getChildrenByLocalName('simpleContent')) |
|
|
50
|
|
|
|
|
|
130
|
|
|
|
|
|
|
{ # tagged |
131
|
2
|
50
|
|
|
|
26
|
if(($subnode) = $sc->getChildrenByLocalName('extension')) |
|
|
0
|
|
|
|
|
|
132
|
2
|
|
|
|
|
24
|
{ $super = $subnode->getAttribute('base'); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
elsif(($subnode) = $sc->getChildrenByLocalName('restriction')) |
135
|
0
|
|
|
|
|
0
|
{ $super = $subnode->getAttribute('base'); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
elsif(my($cc) = $node->getChildrenByLocalName('complexContent')) |
139
|
|
|
|
|
|
|
{ # real complex |
140
|
2
|
50
|
|
|
|
68
|
if(($subnode) = $cc->getChildrenByLocalName('extension')) |
|
|
0
|
|
|
|
|
|
141
|
2
|
|
|
|
|
23
|
{ $super = $subnode->getAttribute('base'); |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
elsif(($subnode) = $cc->getChildrenByLocalName('restriction')) |
144
|
0
|
|
|
|
|
0
|
{ $super = $subnode->getAttribute('base'); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
else |
149
|
|
|
|
|
|
|
{ # built-in |
150
|
710
|
|
|
|
|
1685
|
my ($ns, $local) = unpack_type $ext; |
151
|
710
|
50
|
33
|
|
|
3163
|
$ns eq SCHEMA2001 && $builtin_types{$local} |
152
|
|
|
|
|
|
|
or error __x"cannot find {type} as simpleType or complexType" |
153
|
|
|
|
|
|
|
, type => $ext; |
154
|
710
|
|
|
|
|
1415
|
my ($bns, $blocal) = unpack_type $base; |
155
|
710
|
50
|
|
|
|
1521
|
$ns eq $bns |
156
|
|
|
|
|
|
|
or return 0; |
157
|
|
|
|
|
|
|
|
158
|
710
|
|
|
|
|
1787
|
while(my $e = $builtin_types{$local}{extends}) |
159
|
2808
|
100
|
|
|
|
4086
|
{ return 1 if $e eq $blocal; |
160
|
2796
|
|
|
|
|
6129
|
$local = $e; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
788
|
100
|
|
|
|
3635
|
$super |
165
|
|
|
|
|
|
|
or return 0; |
166
|
|
|
|
|
|
|
|
167
|
84
|
100
|
|
|
|
346
|
my ($prefix, $local) = $super =~ m/:/ ? split(/:/,$super,2) : ('',$super); |
168
|
84
|
|
|
|
|
364
|
my $supertype = pack_type $subnode->lookupNamespaceURI($prefix), $local; |
169
|
|
|
|
|
|
|
|
170
|
84
|
100
|
|
|
|
262
|
$base eq $supertype ? 1 : $self->doesExtend($supertype, $base); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub findTypeExtensions($) |
175
|
2
|
|
|
2
|
1
|
7
|
{ my ($self, $type) = @_; |
176
|
|
|
|
|
|
|
|
177
|
2
|
|
|
|
|
3
|
my %ext; |
178
|
2
|
50
|
|
|
|
6
|
if($self->find(simpleType => $type)) |
|
|
50
|
|
|
|
|
|
179
|
|
|
|
|
|
|
{ $self->doesExtend($_, $type) && $ext{$_}++ |
180
|
0
|
|
0
|
|
|
0
|
for map $_->simpleTypes, $self->allSchemas; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
elsif($self->find(complexType => $type)) |
183
|
|
|
|
|
|
|
{ $self->doesExtend($_, $type) && $ext{$_}++ |
184
|
2
|
|
33
|
|
|
6
|
for map $_->complexTypes, $self->allSchemas; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
else |
187
|
0
|
|
|
|
|
0
|
{ error __x"cannot find base-type {type} for extensions", type => $type; |
188
|
|
|
|
|
|
|
} |
189
|
2
|
|
|
|
|
15
|
sort keys %ext; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub autoexpand_xsi_type($) |
193
|
2
|
|
|
2
|
0
|
7
|
{ my ($self, $type) = @_; |
194
|
2
|
|
|
|
|
7
|
my @ext = $self->findTypeExtensions($type); |
195
|
2
|
|
|
|
|
17
|
trace "discovered xsi:type choices for $type:\n ". join("\n ", @ext); |
196
|
2
|
|
|
|
|
54
|
\@ext; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub findSgMembers($$) |
201
|
1119
|
|
|
1119
|
1
|
2414
|
{ my ($self, $class, $base) = @_; |
202
|
1119
|
100
|
|
|
|
3623
|
my $s = $self->{sgs}{$base} |
203
|
|
|
|
|
|
|
or return; |
204
|
|
|
|
|
|
|
|
205
|
22
|
|
|
|
|
33
|
my @sgs; |
206
|
22
|
|
|
|
|
105
|
while(my($ext, $instance) = each %$s) |
207
|
36
|
|
|
|
|
85
|
{ push @sgs, $instance->find($class => $ext) |
208
|
|
|
|
|
|
|
, $self->findSgMembers($class, $ext); |
209
|
|
|
|
|
|
|
} |
210
|
22
|
|
|
|
|
60
|
@sgs; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub findID($;$) |
215
|
771
|
|
|
771
|
1
|
1302
|
{ my $self = shift; |
216
|
771
|
50
|
|
|
|
2958
|
my ($label, $ns, $id) |
217
|
|
|
|
|
|
|
= @_==1 ? ($_[0], unpack_id $_[0]) : (pack_id($_[0], $_[1]), @_); |
218
|
771
|
50
|
|
|
|
1892
|
defined $ns or return undef; |
219
|
|
|
|
|
|
|
|
220
|
771
|
|
|
|
|
20607
|
my $xpc = XML::LibXML::XPathContext->new; |
221
|
771
|
|
|
|
|
4322
|
$xpc->registerNs(a => $ns); |
222
|
|
|
|
|
|
|
|
223
|
771
|
|
|
|
|
1093
|
my @nodes; |
224
|
771
|
|
|
|
|
2076
|
foreach my $fragment ($self->schemas($ns)) |
225
|
0
|
0
|
|
|
|
0
|
{ @nodes = $xpc->findnodes("/*/a:*#$id", $fragment->schema) |
226
|
|
|
|
|
|
|
or next; |
227
|
|
|
|
|
|
|
|
228
|
0
|
0
|
|
|
|
0
|
return $nodes[0] |
229
|
|
|
|
|
|
|
if @nodes==1; |
230
|
|
|
|
|
|
|
|
231
|
0
|
|
0
|
|
|
0
|
error "multiple elements with the same id {id} in {source}" |
232
|
|
|
|
|
|
|
, id => $label |
233
|
|
|
|
|
|
|
, source => ($fragment->filename || $fragment->source); |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
771
|
|
|
|
|
8207
|
undef; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub printIndex(@) |
241
|
0
|
|
|
0
|
1
|
|
{ my $self = shift; |
242
|
0
|
0
|
|
|
|
|
my $fh = @_ % 2 ? shift : select; |
243
|
0
|
|
|
|
|
|
my %opts = @_; |
244
|
|
|
|
|
|
|
|
245
|
0
|
|
0
|
|
|
|
my $nss = delete $opts{namespace} || [$self->list]; |
246
|
0
|
0
|
|
|
|
|
foreach my $nsuri (ref $nss eq 'ARRAY' ? @$nss : $nss) |
247
|
0
|
|
|
|
|
|
{ $_->printIndex($fh, %opts) for $self->namespace($nsuri); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
0
|
0
|
|
|
|
|
my $show_used = exists $opts{include_used} ? $opts{include_used} : 1; |
251
|
0
|
|
|
|
|
|
foreach my $use ($self->use) |
252
|
0
|
|
|
|
|
|
{ $use->printIndex(%opts, include_used => 0); |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
|
$self; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub importIndex(%) |
260
|
0
|
|
|
0
|
1
|
|
{ my ($self, %args) = @_; |
261
|
0
|
|
|
|
|
|
my %import; |
262
|
0
|
|
|
|
|
|
foreach my $fragment (map $self->schemas($_), $self->list) |
263
|
0
|
|
|
|
|
|
{ foreach my $import ($fragment->imports) |
264
|
0
|
|
|
|
|
|
{ $import{$import}{$_}++ for $fragment->importLocations($import); |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
} |
267
|
0
|
|
|
|
|
|
foreach my $ns (keys %import) |
268
|
0
|
|
|
|
|
|
{ $import{$ns} = [ grep length, keys %{$import{$ns}} ]; |
|
0
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
} |
270
|
0
|
|
|
|
|
|
\%import; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
1; |