| 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::Translate::Template; |
|
10
|
11
|
|
|
11
|
|
1945
|
use vars '$VERSION'; |
|
|
11
|
|
|
|
|
19
|
|
|
|
11
|
|
|
|
|
615
|
|
|
11
|
|
|
|
|
|
|
$VERSION = '1.63'; |
|
12
|
|
|
|
|
|
|
|
|
13
|
11
|
|
|
11
|
|
60
|
use base 'XML::Compile::Translate'; |
|
|
11
|
|
|
|
|
18
|
|
|
|
11
|
|
|
|
|
1434
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
11
|
|
|
11
|
|
78
|
use strict; |
|
|
11
|
|
|
|
|
18
|
|
|
|
11
|
|
|
|
|
221
|
|
|
16
|
11
|
|
|
11
|
|
44
|
use warnings; |
|
|
11
|
|
|
|
|
18
|
|
|
|
11
|
|
|
|
|
328
|
|
|
17
|
11
|
|
|
11
|
|
48
|
no warnings 'once', 'recursion'; |
|
|
11
|
|
|
|
|
14
|
|
|
|
11
|
|
|
|
|
471
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
11
|
|
|
11
|
|
60
|
use Log::Report 'xml-compile'; |
|
|
11
|
|
|
|
|
17
|
|
|
|
11
|
|
|
|
|
70
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
use XML::Compile::Util |
|
22
|
11
|
|
|
11
|
|
3132
|
qw/odd_elements even_elements SCHEMA2001i pack_type unpack_type/; |
|
|
11
|
|
|
|
|
18
|
|
|
|
11
|
|
|
|
|
848
|
|
|
23
|
11
|
|
|
11
|
|
69
|
use List::Util qw/max first/; |
|
|
11
|
|
|
|
|
27
|
|
|
|
11
|
|
|
|
|
698
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
11
|
|
|
11
|
|
56
|
use vars '$VERSION'; # OODoc adds $VERSION to the script |
|
|
11
|
|
|
|
|
21
|
|
|
|
11
|
|
|
|
|
76091
|
|
|
26
|
|
|
|
|
|
|
$VERSION ||= 'undef'; |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub makeTagQualified |
|
30
|
31
|
|
|
31
|
0
|
81
|
{ my ($self, $path, $node, $local, $ns) = @_; |
|
31
|
31
|
|
|
|
|
147
|
my $prefix = $self->_registerNSprefix('', $ns, 1); |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# it is certainly not correct to do a keyRewrite here, but it works :( |
|
34
|
31
|
100
|
|
|
|
170
|
$self->{_output} eq 'PERL' ? $self->keyRewrite($ns, $local) |
|
|
|
100
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
: length $prefix ? "$prefix:$local" |
|
36
|
|
|
|
|
|
|
: $local; |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub makeTagUnqualified |
|
40
|
95
|
|
|
95
|
0
|
163
|
{ my ($self, $path, $node, $local, $ns) = @_; |
|
41
|
|
|
|
|
|
|
# $name =~ s/.*\://; |
|
42
|
|
|
|
|
|
|
return $self->keyRewrite($ns, $local) |
|
43
|
95
|
100
|
|
|
|
276
|
if $self->{_output} eq 'PERL'; |
|
44
|
|
|
|
|
|
|
|
|
45
|
35
|
|
|
|
|
66
|
my $prefix = $self->_registerNSprefix('', $ns, 1); |
|
46
|
35
|
100
|
|
|
|
91
|
length $prefix ? "$prefix:$local" : $local; |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# Detect recursion. Based on type is best, but some schema's do not |
|
50
|
|
|
|
|
|
|
# have named types, so tags are indexed as well. |
|
51
|
|
|
|
|
|
|
my (%recurse_type, %reuse_type, %recurse_tag, %reuse_tag); |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub compile($@) |
|
54
|
19
|
|
|
19
|
1
|
118
|
{ my ($self, $type, %args) = @_; |
|
55
|
19
|
|
|
|
|
43
|
$self->{_output} = $args{output}; |
|
56
|
19
|
|
50
|
|
|
82
|
$self->{_style} = $args{output_style} || 1; |
|
57
|
19
|
|
|
|
|
45
|
(%recurse_type, %reuse_type, %recurse_tag, %reuse_tag) = (); |
|
58
|
19
|
|
|
|
|
147
|
$self->SUPER::compile($type, %args); |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub actsAs($) |
|
62
|
213
|
|
|
213
|
0
|
307
|
{ my ($self, $as) = @_; |
|
63
|
|
|
|
|
|
|
($as eq 'READER' && $self->{_output} eq 'PERL') |
|
64
|
213
|
100
|
100
|
|
|
1354
|
|| ($as eq 'WRITER' && $self->{_output} eq 'XML') |
|
|
|
|
100
|
|
|
|
|
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub makeWrapperNs($$$$$) |
|
68
|
4
|
|
|
4
|
0
|
11
|
{ my ($self, $path, $processor, $index, $filter) = @_; |
|
69
|
|
|
|
|
|
|
|
|
70
|
4
|
|
|
|
|
5
|
my @entries; |
|
71
|
4
|
50
|
|
8
|
|
19
|
$filter = sub {1} if ref $filter ne 'CODE'; |
|
|
8
|
|
|
|
|
12
|
|
|
72
|
|
|
|
|
|
|
|
|
73
|
4
|
|
|
|
|
20
|
foreach my $entry (sort {$a->{prefix} cmp $b->{prefix}} values %$index) |
|
|
17
|
|
|
|
|
28
|
|
|
74
|
16
|
100
|
|
|
|
31
|
{ $entry->{used} or next; |
|
75
|
8
|
|
|
|
|
7
|
my ($prefix, $uri) = @{$entry}{'prefix', 'uri'}; |
|
|
8
|
|
|
|
|
17
|
|
|
76
|
8
|
50
|
|
|
|
12
|
$filter->($uri, $prefix) or next; |
|
77
|
8
|
|
|
|
|
14
|
push @entries, [ $uri, $prefix ]; |
|
78
|
8
|
|
|
|
|
12
|
$entry->{used} = 0; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
4
|
50
|
|
4
|
|
9
|
sub { my $data = $processor->(@_) or return (); |
|
82
|
4
|
50
|
|
|
|
9
|
if($self->{include_namespaces}) |
|
83
|
4
|
|
|
|
|
23
|
{ $data->{"xmlns:$_->[1]"} = $_->[0] for @entries; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
4
|
|
|
|
|
18
|
$data; |
|
86
|
4
|
|
|
|
|
40
|
}; |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub typemapToHooks($$) |
|
90
|
19
|
|
|
19
|
0
|
39
|
{ my ($self, $hooks, $typemap) = @_; |
|
91
|
|
|
|
|
|
|
|
|
92
|
19
|
|
|
|
|
77
|
while(my($type, $action) = each %$typemap) |
|
93
|
3
|
50
|
|
|
|
6
|
{ defined $action or next; |
|
94
|
|
|
|
|
|
|
|
|
95
|
3
|
100
|
|
|
|
19
|
my ($struct, $example) |
|
|
|
100
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
= $action =~ s/^[\\]?\&/\$/ |
|
97
|
|
|
|
|
|
|
? ( "call on converter function with object" |
|
98
|
|
|
|
|
|
|
, "$action->('WRITER', \$object, '$type', \$doc)") |
|
99
|
|
|
|
|
|
|
: $action =~ m/^\$/ |
|
100
|
|
|
|
|
|
|
? ( "call on converter with object" |
|
101
|
|
|
|
|
|
|
, "$action->toXML(\$object, '$type', \$doc)") |
|
102
|
|
|
|
|
|
|
: ( [ "calls toXML() on $action objects", " with $type and doc" ] |
|
103
|
|
|
|
|
|
|
, "bless({}, '$action')" ); |
|
104
|
|
|
|
|
|
|
|
|
105
|
3
|
|
|
|
|
8
|
my $details = |
|
106
|
|
|
|
|
|
|
{ struct => $struct |
|
107
|
|
|
|
|
|
|
, example => $example |
|
108
|
|
|
|
|
|
|
}; |
|
109
|
|
|
|
|
|
|
|
|
110
|
3
|
|
|
3
|
|
19
|
push @$hooks, { type => $type, replace => sub { $details} }; |
|
|
3
|
|
|
|
|
4
|
|
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
19
|
|
|
|
|
38
|
$hooks; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub makeElementWrapper |
|
117
|
19
|
|
|
19
|
0
|
42
|
{ my ($self, $path, $processor) = @_; |
|
118
|
19
|
|
|
19
|
|
68
|
sub { $processor->() }; |
|
|
19
|
|
|
|
|
37
|
|
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
*makeAttributeWrapper = \&makeElementWrapper; |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub _block($@) |
|
123
|
45
|
|
|
45
|
|
107
|
{ my ($self, $block, $path, @pairs) = @_; |
|
124
|
|
|
|
|
|
|
bless |
|
125
|
40
|
|
|
40
|
|
98
|
sub { my @elems = map { $_->() } odd_elements @pairs; |
|
|
85
|
|
|
|
|
112
|
|
|
126
|
40
|
|
|
|
|
64
|
my @tags = map { $_->{tag} } @elems; |
|
|
85
|
|
|
|
|
126
|
|
|
127
|
|
|
|
|
|
|
|
|
128
|
40
|
|
|
|
|
57
|
local $" = ', '; |
|
129
|
40
|
50
|
|
|
|
172
|
my $struct = @tags ? "$block of @tags" |
|
130
|
|
|
|
|
|
|
: "empty $block from ".join(" ", even_elements @pairs); |
|
131
|
|
|
|
|
|
|
|
|
132
|
40
|
|
|
|
|
57
|
my @lines; |
|
133
|
40
|
|
|
|
|
107
|
while(length $struct > 65) |
|
134
|
0
|
|
|
|
|
0
|
{ $struct =~ s/(.{1,60}|\S+)(?:\s+|$)//; |
|
135
|
0
|
|
|
|
|
0
|
push @lines, $1; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
40
|
50
|
|
|
|
123
|
push @lines, $struct |
|
138
|
|
|
|
|
|
|
if length $struct; |
|
139
|
40
|
|
|
|
|
93
|
$lines[$_] =~ s/^/ / for 1..$#lines; |
|
140
|
|
|
|
|
|
|
|
|
141
|
40
|
|
|
|
|
185
|
{ tag => $block |
|
142
|
|
|
|
|
|
|
, elems => \@elems |
|
143
|
|
|
|
|
|
|
, struct => \@lines |
|
144
|
|
|
|
|
|
|
}; |
|
145
|
45
|
|
|
|
|
351
|
}, 'BLOCK'; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
39
|
|
|
39
|
0
|
51
|
sub makeSequence { my $self = shift; $self->_block(sequence => @_) } |
|
|
39
|
|
|
|
|
81
|
|
|
149
|
6
|
|
|
6
|
0
|
11
|
sub makeChoice { my $self = shift; $self->_block(choice => @_) } |
|
|
6
|
|
|
|
|
22
|
|
|
150
|
0
|
|
|
0
|
0
|
0
|
sub makeAll { my $self = shift; $self->_block(all => @_) } |
|
|
0
|
|
|
|
|
0
|
|
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub makeBlockHandler |
|
153
|
45
|
|
|
45
|
0
|
105
|
{ my ($self, $path, $label, $min, $max, $proc, $kind, $multi) = @_; |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my $code = |
|
156
|
40
|
|
|
40
|
|
71
|
sub { my $data = $proc->(); |
|
157
|
40
|
100
|
66
|
|
|
357
|
my $occur |
|
|
|
50
|
66
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
158
|
|
|
|
|
|
|
= $max eq 'unbounded' && $min==0 ? 'occurs any number of times' |
|
159
|
|
|
|
|
|
|
: $max ne 'unbounded' && $max==1 && $min==0 ? 'is optional' |
|
160
|
|
|
|
|
|
|
: $max ne 'unbounded' && $max==1 && $min==1 ? '' # the usual case |
|
161
|
|
|
|
|
|
|
: "occurs $min <= # <= $max times"; |
|
162
|
|
|
|
|
|
|
|
|
163
|
40
|
100
|
33
|
|
|
87
|
$data->{occur} ||= $occur if $occur; |
|
164
|
40
|
100
|
100
|
|
|
124
|
if($max ne 'unbounded' && $max==1) |
|
165
|
35
|
|
|
|
|
61
|
{ bless $data, 'BLOCK'; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
else |
|
168
|
5
|
|
|
|
|
8
|
{ $data->{tag} = $multi; |
|
169
|
5
|
|
|
|
|
8
|
$data->{is_array} = 1; |
|
170
|
5
|
|
|
|
|
16
|
bless $data, 'REP-BLOCK'; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
40
|
|
|
|
|
82
|
$data; |
|
173
|
45
|
|
|
|
|
146
|
}; |
|
174
|
45
|
|
|
|
|
168
|
($label => $code); |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub makeElementHandler |
|
178
|
85
|
|
|
85
|
0
|
173
|
{ my ($self, $path, $label, $min, $max, $req, $opt) = @_; |
|
179
|
80
|
50
|
|
80
|
|
146
|
sub { my $data = $opt->() or return; |
|
180
|
80
|
100
|
100
|
|
|
551
|
my $occur |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
181
|
|
|
|
|
|
|
= $max eq 'unbounded' && $min==0 ? 'occurs any number of times' |
|
182
|
|
|
|
|
|
|
: $max ne 'unbounded' && $max==1 && $min==0 ? 'is optional' |
|
183
|
|
|
|
|
|
|
: $max ne 'unbounded' && $max==1 && $min==1 ? '' # the usual case |
|
184
|
|
|
|
|
|
|
: "occurs $min <= # <= $max times"; |
|
185
|
80
|
100
|
33
|
|
|
179
|
$data->{occur} ||= $occur if $occur; |
|
186
|
80
|
|
100
|
|
|
255
|
$data->{is_array} = $max eq 'unbounded' || $max > 1; |
|
187
|
80
|
|
|
|
|
162
|
$data; |
|
188
|
85
|
|
|
|
|
647
|
}; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub makeRequired |
|
192
|
78
|
|
|
78
|
0
|
139
|
{ my ($self, $path, $label, $do) = @_; |
|
193
|
78
|
|
|
|
|
110
|
$do; |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub makeElementHref |
|
197
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $ns, $childname, $do) = @_; |
|
198
|
0
|
|
|
|
|
0
|
$do; |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub makeElement |
|
202
|
99
|
|
|
99
|
0
|
185
|
{ my ($self, $path, $ns, $childname, $do) = @_; |
|
203
|
97
|
|
|
97
|
|
137
|
sub { my $h = $do->(@_); |
|
204
|
97
|
|
|
|
|
148
|
$h->{_NAME} = $childname; |
|
205
|
97
|
|
|
|
|
174
|
$h; |
|
206
|
99
|
|
|
|
|
336
|
}; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub makeElementDefault |
|
210
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $ns, $childname, $do, $default) = @_; |
|
211
|
0
|
|
|
0
|
|
0
|
sub { my $h = $do->(@_); |
|
212
|
0
|
|
|
|
|
0
|
$h->{occur} = "defaults to '$default'"; |
|
213
|
0
|
|
|
|
|
0
|
$h->{example} = $default; |
|
214
|
0
|
|
|
|
|
0
|
$h; |
|
215
|
0
|
|
|
|
|
0
|
}; |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub makeElementFixed |
|
219
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $ns, $childname, $do, $fixed) = @_; |
|
220
|
0
|
|
|
0
|
|
0
|
sub { my $h = $do->(@_); |
|
221
|
0
|
|
|
|
|
0
|
$h->{occur} = "fixed to '$fixed'"; |
|
222
|
0
|
|
|
|
|
0
|
$h->{example} = $fixed; |
|
223
|
0
|
|
|
|
|
0
|
$h; |
|
224
|
0
|
|
|
|
|
0
|
}; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub makeElementAbstract |
|
228
|
2
|
|
|
2
|
0
|
6
|
{ my ($self, $path, $ns, $childname, $do) = @_; |
|
229
|
|
|
|
|
|
|
# sub { () }; |
|
230
|
|
|
|
|
|
|
sub { |
|
231
|
2
|
|
|
2
|
|
4
|
my $h = $do->(@_); |
|
232
|
2
|
|
|
|
|
4
|
$h->{_NAME} = $childname; |
|
233
|
2
|
|
|
|
|
4
|
$h->{occur} = "ABSTRACT"; |
|
234
|
2
|
|
|
|
|
3
|
$h; |
|
235
|
2
|
|
|
|
|
6
|
}; |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub makeComplexElement |
|
239
|
35
|
|
|
35
|
0
|
89
|
{ my ($self, $path, $tag, $elems, $attrs, $any_attr, $type, $is_nillable)=@_; |
|
240
|
35
|
|
|
|
|
131
|
my @elem_parts = odd_elements @$elems; |
|
241
|
35
|
|
|
|
|
68
|
my @attr_parts = (odd_elements(@$attrs), @$any_attr); |
|
242
|
|
|
|
|
|
|
|
|
243
|
30
|
|
|
30
|
|
37
|
sub { my (@attrs, @elems); |
|
244
|
30
|
|
|
|
|
84
|
my $is_pseudo_type = $type !~ m/^{/; # like "unnamed complex" |
|
245
|
|
|
|
|
|
|
|
|
246
|
30
|
50
|
66
|
|
|
159
|
if((!$is_pseudo_type && $recurse_type{$type}) || $recurse_tag{$tag}) |
|
|
|
|
33
|
|
|
|
|
|
247
|
|
|
|
|
|
|
{ return |
|
248
|
0
|
|
|
|
|
0
|
+{ kind => 'complex' |
|
249
|
|
|
|
|
|
|
, struct => 'probably a recursive complex' |
|
250
|
|
|
|
|
|
|
, tag => $tag |
|
251
|
|
|
|
|
|
|
, _TYPE => $type |
|
252
|
|
|
|
|
|
|
}; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
30
|
50
|
66
|
|
|
123
|
if((!$is_pseudo_type && $reuse_type{$type}) || $reuse_tag{$tag}) |
|
|
|
|
33
|
|
|
|
|
|
256
|
|
|
|
|
|
|
{ return |
|
257
|
0
|
|
|
|
|
0
|
+{ kind => 'complex' |
|
258
|
|
|
|
|
|
|
, struct => 'complex structure shown above' |
|
259
|
|
|
|
|
|
|
, tag => $tag |
|
260
|
|
|
|
|
|
|
, _TYPE => $type |
|
261
|
|
|
|
|
|
|
}; |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
30
|
|
|
|
|
60
|
$recurse_type{$type}++; $recurse_tag{$tag}++; |
|
|
30
|
|
|
|
|
46
|
|
|
265
|
30
|
|
|
|
|
39
|
$reuse_type{$type}++; $reuse_tag{$tag}++; |
|
|
30
|
|
|
|
|
38
|
|
|
266
|
30
|
|
|
|
|
65
|
push @elems, $_->() for @elem_parts; |
|
267
|
30
|
|
|
|
|
52
|
push @attrs, $_->() for @attr_parts; |
|
268
|
|
|
|
|
|
|
|
|
269
|
30
|
|
|
|
|
64
|
$recurse_type{$type}--; $recurse_tag{$tag}--; |
|
|
30
|
|
|
|
|
55
|
|
|
270
|
|
|
|
|
|
|
|
|
271
|
30
|
100
|
|
|
|
144
|
+{ kind => 'complex' |
|
272
|
|
|
|
|
|
|
, struct => ($is_nillable ? "is nillable, as: $tag => NIL" : undef) |
|
273
|
|
|
|
|
|
|
, tag => $tag |
|
274
|
|
|
|
|
|
|
, attrs => \@attrs |
|
275
|
|
|
|
|
|
|
, elems => \@elems |
|
276
|
|
|
|
|
|
|
, _TYPE => $type |
|
277
|
|
|
|
|
|
|
}; |
|
278
|
35
|
|
|
|
|
181
|
}; |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub makeTaggedElement |
|
282
|
1
|
|
|
1
|
0
|
4
|
{ my ($self, $path, $tag, $st, $attrs, $attrs_any, $type, $is_nillable) = @_; |
|
283
|
1
|
|
|
|
|
4
|
my @parts = (odd_elements(@$attrs), @$attrs_any); |
|
284
|
|
|
|
|
|
|
|
|
285
|
1
|
|
|
1
|
|
3
|
sub { my @attrs = map $_->(), @parts; |
|
286
|
1
|
|
|
|
|
3
|
my %simple = $st->(); |
|
287
|
|
|
|
|
|
|
|
|
288
|
1
|
|
|
|
|
3
|
my @struct = 'string content of the container'; |
|
289
|
1
|
50
|
|
|
|
3
|
push @struct, $simple{struct} if $simple{struct}; |
|
290
|
1
|
50
|
|
|
|
4
|
push @struct, 'is nillable, hence value or NIL' if $is_nillable; |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
my %content = |
|
293
|
|
|
|
|
|
|
( tag => '_' |
|
294
|
|
|
|
|
|
|
, struct => \@struct |
|
295
|
1
|
|
50
|
|
|
5
|
, example => ($simple{example} || 'Hello, World!') |
|
296
|
|
|
|
|
|
|
); |
|
297
|
1
|
50
|
|
|
|
3
|
$content{_TYPE} = $simple{_TYPE} if $simple{_TYPE}; |
|
298
|
|
|
|
|
|
|
|
|
299
|
1
|
|
|
|
|
7
|
+{ kind => 'tagged' |
|
300
|
|
|
|
|
|
|
, struct => "$tag is simple value with attributes" |
|
301
|
|
|
|
|
|
|
, tag => $tag |
|
302
|
|
|
|
|
|
|
, attrs => \@attrs |
|
303
|
|
|
|
|
|
|
, elems => [ \%content ] |
|
304
|
|
|
|
|
|
|
, _TYPE => $type |
|
305
|
|
|
|
|
|
|
}; |
|
306
|
1
|
|
|
|
|
6
|
}; |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub makeMixedElement |
|
310
|
1
|
|
|
1
|
0
|
4
|
{ my ($self, $path, $tag, $elems, $attrs, $attrs_any, $type, $is_nillable)=@_; |
|
311
|
1
|
|
|
|
|
5
|
my @parts = (odd_elements(@$attrs), @$attrs_any); |
|
312
|
|
|
|
|
|
|
|
|
313
|
1
|
|
|
|
|
3
|
my @struct = 'mixed content cannot be processed automatically'; |
|
314
|
1
|
50
|
|
|
|
4
|
push @struct, 'is nillable' if $is_nillable; |
|
315
|
|
|
|
|
|
|
|
|
316
|
1
|
|
|
|
|
5
|
my %mixed = |
|
317
|
|
|
|
|
|
|
( tag => '_' |
|
318
|
|
|
|
|
|
|
, struct => \@struct |
|
319
|
|
|
|
|
|
|
, example => "XML::LibXML::Element->new('$tag')" |
|
320
|
|
|
|
|
|
|
); |
|
321
|
|
|
|
|
|
|
|
|
322
|
1
|
50
|
|
|
|
3
|
unless(@parts) # show simpler alternative |
|
323
|
0
|
|
|
|
|
0
|
{ $mixed{tag} = $tag; |
|
324
|
0
|
|
|
|
|
0
|
$mixed{type} = $type; |
|
325
|
0
|
|
|
0
|
|
0
|
return sub { \%mixed }; |
|
|
0
|
|
|
|
|
0
|
|
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
1
|
|
|
1
|
|
2
|
sub { my @attrs = map $_->(), @parts; |
|
329
|
1
|
|
|
|
|
6
|
+{ kind => 'mixed' |
|
330
|
|
|
|
|
|
|
, struct => "$tag has a mixed content" |
|
331
|
|
|
|
|
|
|
, tag => $tag |
|
332
|
|
|
|
|
|
|
, elems => [ \%mixed ] |
|
333
|
|
|
|
|
|
|
, attrs => \@attrs |
|
334
|
|
|
|
|
|
|
, _TYPE => $type |
|
335
|
|
|
|
|
|
|
}; |
|
336
|
1
|
|
|
|
|
5
|
}; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub makeSimpleElement |
|
340
|
64
|
|
|
64
|
0
|
147
|
{ my ($self, $path, $tag, $st, undef, undef, $type, $is_nillable) = @_; |
|
341
|
67
|
|
|
67
|
|
61
|
sub { my @struct; |
|
342
|
67
|
100
|
|
|
|
97
|
push @struct, 'is nillable, hence value or NIL' if $is_nillable; |
|
343
|
67
|
|
|
|
|
96
|
+{ kind => 'simple' |
|
344
|
|
|
|
|
|
|
, struct => \@struct |
|
345
|
|
|
|
|
|
|
, tag => $tag |
|
346
|
|
|
|
|
|
|
, $st->() |
|
347
|
|
|
|
|
|
|
}; |
|
348
|
64
|
|
|
|
|
241
|
}; |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
sub makeBuiltin |
|
352
|
90
|
|
|
90
|
0
|
231
|
{ my ($self, $path, $node, $type, $def, $check_values) = @_; |
|
353
|
90
|
|
|
87
|
|
337
|
sub { (_TYPE=> $type, example => $def->{example}) }; |
|
|
87
|
|
|
|
|
358
|
|
|
354
|
|
|
|
|
|
|
} |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub makeList |
|
357
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $st) = @_; |
|
358
|
0
|
|
|
0
|
|
0
|
sub { my %d = $st->(); |
|
359
|
0
|
|
|
|
|
0
|
$d{struct} = 'a list of values, where each'; |
|
360
|
0
|
|
|
|
|
0
|
my $example = $d{example}; |
|
361
|
0
|
0
|
|
|
|
0
|
if($self->{_output} eq 'PERL') |
|
362
|
0
|
0
|
|
|
|
0
|
{ $example = qq("$example") if $example =~ m/[^0-9.]/; |
|
363
|
0
|
|
|
|
|
0
|
$d{example} = "[ $example , ... ]"; |
|
364
|
|
|
|
|
|
|
} |
|
365
|
|
|
|
|
|
|
else |
|
366
|
0
|
|
|
|
|
0
|
{ $d{example} = "$example $example ..."; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
0
|
|
|
|
|
0
|
%d }; |
|
|
0
|
|
|
|
|
0
|
|
|
369
|
|
|
|
|
|
|
} |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
sub makeFacetsList |
|
372
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $st, $info) = @_; |
|
373
|
0
|
|
|
|
|
0
|
$self->makeFacets($path, $st, $info); |
|
374
|
|
|
|
|
|
|
} |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub _ff($@) |
|
377
|
0
|
|
|
0
|
|
0
|
{ my ($self,$type) = (shift, shift); |
|
378
|
0
|
|
|
|
|
0
|
my @lines = $type.':'; |
|
379
|
0
|
|
|
|
|
0
|
while(@_) |
|
380
|
0
|
|
|
|
|
0
|
{ my $facet = shift; |
|
381
|
0
|
|
|
|
|
0
|
$facet =~ s/\t/\t/g; |
|
382
|
0
|
0
|
|
|
|
0
|
$facet = qq{"$facet"} if $facet =~ m/\s/; |
|
383
|
0
|
0
|
|
|
|
0
|
push @lines, ' ' if length($lines[-1]) + length($facet) > 55; |
|
384
|
0
|
|
|
|
|
0
|
$lines[-1] .= ' '.$facet; |
|
385
|
|
|
|
|
|
|
} |
|
386
|
0
|
|
|
|
|
0
|
@lines; |
|
387
|
|
|
|
|
|
|
} |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
sub makeFacets |
|
390
|
6
|
|
|
6
|
0
|
15
|
{ my ($self, $path, $st, $info) = @_; |
|
391
|
6
|
|
|
|
|
10
|
my @comment; |
|
392
|
6
|
|
|
|
|
36
|
foreach my $k (sort keys %$info) |
|
393
|
12
|
|
|
|
|
24
|
{ my $v = $info->{$k}; |
|
394
|
12
|
0
|
|
|
|
81
|
push @comment |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
, $k eq 'enumeration' ? $self->_ff('Enum', sort @$v) |
|
396
|
|
|
|
|
|
|
: $k eq 'pattern' ? $self->_ff('Pattern', @$v) |
|
397
|
|
|
|
|
|
|
: $k eq 'length' ? "fixed length of $v" |
|
398
|
|
|
|
|
|
|
: $k eq 'maxLength' ? "length <= $v" |
|
399
|
|
|
|
|
|
|
: $k eq 'minLength' ? "length >= $v" |
|
400
|
|
|
|
|
|
|
: $k eq 'totalDigits' ? "total digits is $v" |
|
401
|
|
|
|
|
|
|
: $k eq 'maxScale' ? "scale <= $v" |
|
402
|
|
|
|
|
|
|
: $k eq 'minScale' ? "scale >= $v" |
|
403
|
|
|
|
|
|
|
: $k eq 'maxInclusive' ? "value <= $v" |
|
404
|
|
|
|
|
|
|
: $k eq 'maxExclusive' ? "value < $v" |
|
405
|
|
|
|
|
|
|
: $k eq 'minInclusive' ? "value >= $v" |
|
406
|
|
|
|
|
|
|
: $k eq 'minExclusive' ? "value > $v" |
|
407
|
|
|
|
|
|
|
: $k eq 'fractionDigits' ? "faction digits is $v" |
|
408
|
|
|
|
|
|
|
: $k eq 'whiteSpace' ? "white-space $v" |
|
409
|
|
|
|
|
|
|
: "restriction? $k = $v"; |
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
|
|
412
|
6
|
|
|
|
|
17
|
my %facet = (facets => \@comment, $st->()); |
|
413
|
|
|
|
|
|
|
|
|
414
|
6
|
50
|
|
|
|
23
|
if(my $enum = $info->{enumeration}) |
|
415
|
0
|
|
|
|
|
0
|
{ $facet{example} = $enum->[0]; |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
|
|
418
|
6
|
|
|
10
|
|
38
|
sub { %facet }; |
|
|
10
|
|
|
|
|
50
|
|
|
419
|
|
|
|
|
|
|
} |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
sub makeUnion |
|
422
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, @types) = @_; |
|
423
|
0
|
|
|
0
|
|
0
|
sub { my @choices = map { +{$_->()} } @types; |
|
|
0
|
|
|
|
|
0
|
|
|
424
|
|
|
|
|
|
|
+( kind => 'union' |
|
425
|
|
|
|
|
|
|
, struct => "one of the following (union)" |
|
426
|
|
|
|
|
|
|
, choice => \@choices |
|
427
|
|
|
|
|
|
|
, example => $choices[0]->{example} |
|
428
|
0
|
|
|
|
|
0
|
); |
|
429
|
0
|
|
|
|
|
0
|
}; |
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
sub makeAttributeRequired |
|
433
|
6
|
|
|
6
|
0
|
16
|
{ my ($self, $path, $ns, $tag, $label, $do) = @_; |
|
434
|
|
|
|
|
|
|
|
|
435
|
6
|
|
|
6
|
|
25
|
sub { +{ kind => 'attr' |
|
436
|
|
|
|
|
|
|
, tag => $label |
|
437
|
|
|
|
|
|
|
, occur => "attribute $tag is required" |
|
438
|
|
|
|
|
|
|
, $do->() |
|
439
|
|
|
|
|
|
|
}; |
|
440
|
6
|
|
|
|
|
26
|
}; |
|
441
|
|
|
|
|
|
|
} |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
sub makeAttributeProhibited |
|
444
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $ns, $tag, $label, $do) = @_; |
|
445
|
0
|
|
|
|
|
0
|
(); |
|
446
|
|
|
|
|
|
|
} |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub makeAttribute |
|
449
|
19
|
|
|
19
|
0
|
38
|
{ my ($self, $path, $ns, $tag, $label, $do) = @_; |
|
450
|
17
|
|
|
17
|
|
27
|
sub { +{ kind => 'attr' |
|
451
|
|
|
|
|
|
|
, tag => $tag |
|
452
|
|
|
|
|
|
|
, occur => "becomes an attribute" |
|
453
|
|
|
|
|
|
|
, $do->() |
|
454
|
|
|
|
|
|
|
}; |
|
455
|
19
|
|
|
|
|
69
|
}; |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub makeAttributeDefault |
|
459
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $ns, $tag, $label, $do) = @_; |
|
460
|
|
|
|
|
|
|
sub { |
|
461
|
0
|
|
|
0
|
|
0
|
+{ kind => 'attr' |
|
462
|
|
|
|
|
|
|
, tag => $tag |
|
463
|
|
|
|
|
|
|
, occur => "attribute $tag has default" |
|
464
|
|
|
|
|
|
|
, $do->() |
|
465
|
|
|
|
|
|
|
}; |
|
466
|
0
|
|
|
|
|
0
|
}; |
|
467
|
|
|
|
|
|
|
} |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
sub makeAttributeFixed |
|
470
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $ns, $tag, $label, $do, $fixed) = @_; |
|
471
|
0
|
|
|
|
|
0
|
my $value = $fixed->value; |
|
472
|
|
|
|
|
|
|
|
|
473
|
0
|
|
|
0
|
|
0
|
sub { +{ kind => 'attr' |
|
474
|
|
|
|
|
|
|
, tag => $tag |
|
475
|
|
|
|
|
|
|
, occur => "attribute $tag is fixed" |
|
476
|
|
|
|
|
|
|
, example => $value |
|
477
|
|
|
|
|
|
|
}; |
|
478
|
0
|
|
|
|
|
0
|
}; |
|
479
|
|
|
|
|
|
|
} |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
sub makeSubstgroup |
|
482
|
2
|
|
|
2
|
0
|
7
|
{ my ($self, $path, $type, @todo) = @_; |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
sub { |
|
485
|
2
|
|
|
2
|
|
4
|
my (@example_tags, $example_nest, %tags); |
|
486
|
2
|
|
|
|
|
4
|
my @do = @todo; |
|
487
|
2
|
|
|
|
|
4
|
my $group = $do[1][0]; |
|
488
|
|
|
|
|
|
|
|
|
489
|
2
|
|
|
|
|
6
|
while(@do) |
|
490
|
6
|
|
|
|
|
12
|
{ my ($type, $info) = (shift @do, shift @do); |
|
491
|
6
|
|
|
|
|
11
|
my ($label, $call) = @$info; |
|
492
|
6
|
|
|
|
|
10
|
my $processed = $call->(); |
|
493
|
6
|
|
|
|
|
7
|
my $show = ''; |
|
494
|
6
|
50
|
|
|
|
17
|
if($processed->{kind} eq 'substitution group') |
|
|
|
50
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
{ # substr extended by subst, which already is formatted. |
|
496
|
|
|
|
|
|
|
# need to extract only the indicated type info. |
|
497
|
0
|
|
0
|
|
|
0
|
my $s = $processed->{struct} || []; |
|
498
|
0
|
|
0
|
|
|
0
|
/^ $label (.*)/ and $show = $1 for @$s; |
|
499
|
|
|
|
|
|
|
} |
|
500
|
|
|
|
|
|
|
elsif(my $type = $processed->{_TYPE}) |
|
501
|
6
|
|
|
|
|
15
|
{ $show = $self->prefixed($type); |
|
502
|
|
|
|
|
|
|
} |
|
503
|
|
|
|
|
|
|
|
|
504
|
6
|
100
|
66
|
|
|
17
|
if($processed->{occur} && $processed->{occur} eq 'ABSTRACT') |
|
505
|
1
|
|
|
|
|
2
|
{ $show .= ' (abstract)'; |
|
506
|
|
|
|
|
|
|
} |
|
507
|
|
|
|
|
|
|
else |
|
508
|
|
|
|
|
|
|
{ # some complication to always produce the same tag for |
|
509
|
|
|
|
|
|
|
# regression tests... Instance uses a HASH... |
|
510
|
5
|
|
|
|
|
9
|
push @example_tags, $label; |
|
511
|
|
|
|
|
|
|
$example_nest ||= $processed->{kind} eq 'simple' |
|
512
|
5
|
100
|
50
|
|
|
30
|
? ($processed->{example} || '...') : '{...}'; |
|
|
|
|
66
|
|
|
|
|
|
513
|
|
|
|
|
|
|
} |
|
514
|
|
|
|
|
|
|
|
|
515
|
6
|
|
|
|
|
52
|
$tags{$label} = $show; |
|
516
|
|
|
|
|
|
|
} |
|
517
|
|
|
|
|
|
|
|
|
518
|
2
|
|
|
|
|
15
|
my $longest = max map length, keys %tags; |
|
519
|
2
|
|
|
|
|
32
|
my @lines = map sprintf(" %-${longest}s %s", $_, $tags{$_}), |
|
520
|
|
|
|
|
|
|
sort keys %tags; |
|
521
|
|
|
|
|
|
|
|
|
522
|
2
|
|
|
|
|
8
|
my $example_tag = (sort @example_tags)[0]; |
|
523
|
2
|
50
|
|
|
|
9
|
my $example = $example_tag ? "{ $example_tag => $example_nest }" |
|
524
|
|
|
|
|
|
|
: "undef # only abstract types known"; |
|
525
|
|
|
|
|
|
|
|
|
526
|
2
|
|
|
|
|
6
|
my $name = $self->prefixed($type); |
|
527
|
|
|
|
|
|
|
|
|
528
|
2
|
|
|
|
|
14
|
+{ kind => 'substitution group' |
|
529
|
|
|
|
|
|
|
, tag => $group |
|
530
|
|
|
|
|
|
|
, struct => [ "substitutionGroup $name", @lines ] |
|
531
|
|
|
|
|
|
|
, example => $example |
|
532
|
|
|
|
|
|
|
}; |
|
533
|
2
|
|
|
|
|
17
|
}; |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
sub makeXsiTypeSwitch($$$$) |
|
537
|
1
|
|
|
1
|
0
|
4
|
{ my ($self, $where, $elem, $default_type, $types) = @_; |
|
538
|
1
|
|
|
|
|
8
|
my @types = map " ".$self->prefixed($_), sort keys %$types; |
|
539
|
1
|
|
|
|
|
3
|
my $deftype = $self->prefixed($default_type); |
|
540
|
|
|
|
|
|
|
|
|
541
|
1
|
|
|
1
|
|
7
|
sub { +{ kind => 'xsi:type switch' |
|
542
|
|
|
|
|
|
|
, tag => $elem |
|
543
|
|
|
|
|
|
|
, struct => [ 'xsi:type alternatives:', @types ] |
|
544
|
|
|
|
|
|
|
, example => "{ XSI_TYPE => '$deftype', %data }" |
|
545
|
|
|
|
|
|
|
} |
|
546
|
1
|
|
|
|
|
5
|
}; |
|
547
|
|
|
|
|
|
|
} |
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
sub makeAnyAttribute |
|
550
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $handler, $yes, $no, $process) = @_; |
|
551
|
0
|
|
0
|
|
|
0
|
$yes ||= []; $no ||= []; |
|
|
0
|
|
0
|
|
|
0
|
|
|
552
|
0
|
0
|
|
|
|
0
|
$yes = [ map {$self->prefixed("{$_}") || $_} @$yes]; |
|
|
0
|
|
|
|
|
0
|
|
|
553
|
0
|
0
|
|
|
|
0
|
$no = [ map {$self->prefixed("{$_}") || $_} @$no]; |
|
|
0
|
|
|
|
|
0
|
|
|
554
|
0
|
0
|
|
|
|
0
|
my $occurs = @$yes ? "in @$yes" : @$no ? "not in @$no" : 'in any namespace'; |
|
|
|
0
|
|
|
|
|
|
|
555
|
0
|
|
|
0
|
|
0
|
bless sub { +{kind => 'attr' , struct => "any attribute $occurs" |
|
556
|
0
|
|
|
|
|
0
|
, tag => 'ANYATTR', example => 'AnySimple'} }, 'ANY'; |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
sub makeAnyElement |
|
560
|
0
|
|
|
0
|
0
|
0
|
{ my ($self, $path, $handler, $yes, $no, $process, $min, $max) = @_; |
|
561
|
0
|
|
0
|
|
|
0
|
$yes ||= []; $no ||= []; |
|
|
0
|
|
0
|
|
|
0
|
|
|
562
|
0
|
0
|
|
|
|
0
|
$yes = [ map {$self->prefixed("{$_}") || $_} @$yes]; |
|
|
0
|
|
|
|
|
0
|
|
|
563
|
0
|
0
|
|
|
|
0
|
$no = [ map {$self->prefixed("{$_}") || $_} @$no]; |
|
|
0
|
|
|
|
|
0
|
|
|
564
|
0
|
0
|
|
|
|
0
|
my $where = @$yes ? "in @$yes" : @$no ? "not in @$no" : 'in any namespace'; |
|
|
|
0
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
|
|
566
|
0
|
|
|
|
|
0
|
my $data = +{ kind => 'element', struct => "any element $where" |
|
567
|
|
|
|
|
|
|
, tag => "ANY", example => 'Anything' }; |
|
568
|
0
|
0
|
0
|
|
|
0
|
my $occur |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
569
|
|
|
|
|
|
|
= $max eq 'unbounded' && $min==0 ? 'occurs any number of times' |
|
570
|
|
|
|
|
|
|
: $max ne 'unbounded' && $max==1 && $min==0 ? 'is optional' |
|
571
|
|
|
|
|
|
|
: $max ne 'unbounded' && $max==1 && $min==1 ? '' # the usual case |
|
572
|
|
|
|
|
|
|
: "occurs $min <= # <= $max times"; |
|
573
|
0
|
0
|
0
|
|
|
0
|
$data->{occur} ||= $occur if $occur; |
|
574
|
0
|
|
0
|
|
|
0
|
$data->{is_array} = $max eq 'unbounded' || $max > 1; |
|
575
|
|
|
|
|
|
|
|
|
576
|
0
|
|
|
0
|
|
0
|
bless sub { +$data }, 'ANY'; |
|
|
0
|
|
|
|
|
0
|
|
|
577
|
|
|
|
|
|
|
} |
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub makeHook($$$$$$$) |
|
580
|
3
|
|
|
3
|
0
|
9
|
{ my ($self, $path, $r, $tag, $before, $replace, $after, $fulltype) = @_; |
|
581
|
|
|
|
|
|
|
|
|
582
|
3
|
50
|
33
|
|
|
10
|
return $r unless $before || $replace || $after; |
|
|
|
|
33
|
|
|
|
|
|
583
|
|
|
|
|
|
|
|
|
584
|
3
|
50
|
33
|
|
|
12
|
error __x"template only supports one production (replace) hook" |
|
585
|
|
|
|
|
|
|
if $replace && @$replace > 1; |
|
586
|
|
|
|
|
|
|
|
|
587
|
3
|
50
|
33
|
0
|
|
7
|
return sub {()} if $replace && grep {$_ eq 'SKIP'} @$replace; |
|
|
0
|
|
|
|
|
0
|
|
|
|
3
|
|
|
|
|
12
|
|
|
588
|
|
|
|
|
|
|
|
|
589
|
3
|
50
|
|
|
|
9
|
my @replace = $replace ? map {$self->_decodeReplace($path,$_)} @$replace:(); |
|
|
3
|
|
|
|
|
7
|
|
|
590
|
3
|
50
|
|
|
|
6
|
my @before = $before ? map {$self->_decodeBefore($path,$_) } @$before :(); |
|
|
0
|
|
|
|
|
0
|
|
|
591
|
3
|
50
|
|
|
|
5
|
my @after = $after ? map {$self->_decodeAfter($path,$_) } @$after :(); |
|
|
0
|
|
|
|
|
0
|
|
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
sub |
|
594
|
3
|
|
|
3
|
|
15
|
{ my $doc = XML::LibXML::Document->new; |
|
595
|
3
|
0
|
|
|
|
6
|
for(@before) { $_->($doc, $path, undef) or return } |
|
|
0
|
|
|
|
|
0
|
|
|
596
|
|
|
|
|
|
|
|
|
597
|
3
|
50
|
|
|
|
10
|
my $xml = @replace ? $replace[0]->($doc, $path, $r) : $r->(); |
|
598
|
3
|
50
|
|
|
|
6
|
defined $xml or return (); |
|
599
|
|
|
|
|
|
|
|
|
600
|
3
|
0
|
|
|
|
5
|
for(@after) { $xml = $_->($doc, $path, $xml) or return } |
|
|
0
|
|
|
|
|
0
|
|
|
601
|
3
|
|
|
|
|
11
|
$xml; |
|
602
|
|
|
|
|
|
|
} |
|
603
|
3
|
|
|
|
|
13
|
} |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
sub _decodeBefore($$) |
|
606
|
0
|
|
|
0
|
|
0
|
{ my ($self, $path, $call) = @_; |
|
607
|
0
|
0
|
|
|
|
0
|
return $call if ref $call eq 'CODE'; |
|
608
|
0
|
|
|
|
|
0
|
error __x"labeled before hook `{name}' undefined", name => $call; |
|
609
|
|
|
|
|
|
|
} |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
sub _decodeReplace($$) |
|
612
|
3
|
|
|
3
|
|
5
|
{ my ($self, $path, $call) = @_; |
|
613
|
3
|
50
|
|
|
|
12
|
return $call if ref $call eq 'CODE'; |
|
614
|
|
|
|
|
|
|
|
|
615
|
0
|
0
|
|
|
|
0
|
if($call eq 'COLLAPSE') |
|
616
|
|
|
|
|
|
|
{ return sub |
|
617
|
0
|
|
|
0
|
|
0
|
{ my ($tag, $path, $do) = @_; |
|
618
|
0
|
|
|
|
|
0
|
my $h = $do->(); |
|
619
|
0
|
|
|
|
|
0
|
$h->{elems} = [ { struct => [ 'content collapsed' ] |
|
620
|
|
|
|
|
|
|
, kind => 'collapsed' } ]; |
|
621
|
0
|
|
|
|
|
0
|
delete $h->{attrs}; |
|
622
|
0
|
|
|
|
|
0
|
$h; |
|
623
|
0
|
|
|
|
|
0
|
}; |
|
624
|
|
|
|
|
|
|
} |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# SKIP already handled |
|
627
|
0
|
|
|
|
|
0
|
error __x"labeled replace hook `{name}' undefined", name => $call; |
|
628
|
|
|
|
|
|
|
} |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
sub _decodeAfter($$) |
|
631
|
0
|
|
|
0
|
|
0
|
{ my ($self, $path, $call) = @_; |
|
632
|
0
|
0
|
|
|
|
0
|
return $call if ref $call eq 'CODE'; |
|
633
|
0
|
|
|
|
|
0
|
error __x"labeled after hook `{name}' undefined", name => $call; |
|
634
|
|
|
|
|
|
|
} |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
### |
|
638
|
|
|
|
|
|
|
### toPerl |
|
639
|
|
|
|
|
|
|
### |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub toPerl($%) |
|
642
|
16
|
|
|
16
|
0
|
78
|
{ my ($self, $ast, %args) = @_; |
|
643
|
16
|
50
|
|
|
|
52
|
$ast or return undef; |
|
644
|
|
|
|
|
|
|
|
|
645
|
16
|
|
|
|
|
21
|
my @lines; |
|
646
|
16
|
100
|
|
|
|
42
|
if($ast->{kind}) |
|
647
|
13
|
|
33
|
|
|
32
|
{ my $name = $ast->{_NAME} || $ast->{tag}; |
|
648
|
13
|
|
|
|
|
47
|
my $pref = $self->prefixed($name); |
|
649
|
13
|
50
|
|
|
|
63
|
push @lines, defined $pref |
|
650
|
|
|
|
|
|
|
? ("# Describing $ast->{kind} $pref", "# $name") |
|
651
|
|
|
|
|
|
|
: "# Describing $ast->{kind} $name"; |
|
652
|
|
|
|
|
|
|
} |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
push @lines |
|
655
|
|
|
|
|
|
|
, "#" |
|
656
|
|
|
|
|
|
|
, "# Produced by ".__PACKAGE__." version $VERSION" |
|
657
|
|
|
|
|
|
|
, "# on ".localtime() |
|
658
|
|
|
|
|
|
|
, "#" |
|
659
|
|
|
|
|
|
|
, "# BE WARNED: in most cases, the example below cannot be used without" |
|
660
|
|
|
|
|
|
|
, "# interpretation. The comments will guide you." |
|
661
|
|
|
|
|
|
|
, "#" |
|
662
|
16
|
50
|
|
|
|
54
|
unless $args{skip_header}; |
|
663
|
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
# add info about name-spaces |
|
665
|
16
|
|
|
|
|
118
|
foreach my $nsdecl (grep /^xmlns\:/, sort keys %$ast) |
|
666
|
1
|
|
50
|
|
|
8
|
{ push @lines, sprintf "# %-15s %s", $nsdecl, $ast->{$nsdecl} || '(none)'; |
|
667
|
|
|
|
|
|
|
} |
|
668
|
16
|
100
|
|
|
|
58
|
push @lines, '' if @lines; |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
# produce data tree |
|
671
|
16
|
|
|
|
|
48
|
push @lines, $self->_perlAny($ast, \%args); |
|
672
|
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
# remove leading 'type =>' |
|
674
|
16
|
|
|
|
|
70
|
for(my $linenr = 0; $linenr < @lines; $linenr++) |
|
675
|
73
|
100
|
|
|
|
227
|
{ next if $lines[$linenr] =~ m/^\s*\#/; |
|
676
|
29
|
100
|
|
|
|
113
|
next unless $lines[$linenr] =~ s/.*? \=\>\s*//; |
|
677
|
16
|
100
|
|
|
|
53
|
$lines[$linenr] =~ m/\S/ or splice @lines, $linenr, 1; |
|
678
|
16
|
|
|
|
|
27
|
last; |
|
679
|
|
|
|
|
|
|
} |
|
680
|
|
|
|
|
|
|
|
|
681
|
16
|
|
|
|
|
82
|
my $lines = join "\n", @lines; |
|
682
|
16
|
|
|
|
|
846
|
$lines =~ s/\,?\s*$/\n/; |
|
683
|
16
|
|
|
|
|
971
|
$lines; |
|
684
|
|
|
|
|
|
|
} |
|
685
|
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
my %seen; |
|
687
|
|
|
|
|
|
|
sub _perlAny($$); |
|
688
|
|
|
|
|
|
|
sub _perlAny($$) |
|
689
|
105
|
|
|
105
|
|
152
|
{ my ($self, $ast, $args) = @_; |
|
690
|
|
|
|
|
|
|
|
|
691
|
105
|
|
|
|
|
110
|
my ($pref, @lines); |
|
692
|
105
|
100
|
100
|
|
|
270
|
if($ast->{_TYPE} && $args->{show_type}) |
|
693
|
54
|
50
|
|
|
|
128
|
{ if($pref = $self->prefixed($ast->{_TYPE})) |
|
694
|
54
|
100
|
66
|
|
|
253
|
{ push @lines # not perfect, but a good attempt |
|
695
|
|
|
|
|
|
|
, $pref =~ m/^[aiou]/i && $pref !~ m/^(uni|eu)/i |
|
696
|
|
|
|
|
|
|
? "# is an $pref" : "# is a $pref"; |
|
697
|
|
|
|
|
|
|
} |
|
698
|
|
|
|
|
|
|
} |
|
699
|
|
|
|
|
|
|
|
|
700
|
105
|
100
|
100
|
|
|
264
|
if($ast->{struct} && $args->{show_struct}) |
|
701
|
56
|
|
|
|
|
67
|
{ my $struct = $ast->{struct}; |
|
702
|
56
|
100
|
|
|
|
145
|
my @struct = ref $struct ? @$struct : $struct; |
|
703
|
56
|
|
|
|
|
216
|
s/^/# /gm for @struct; |
|
704
|
56
|
|
|
|
|
91
|
push @lines, @struct; |
|
705
|
|
|
|
|
|
|
} |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
push @lines, "# $ast->{occur}" |
|
708
|
105
|
100
|
100
|
|
|
234
|
if $ast->{occur} && $args->{show_occur}; |
|
709
|
|
|
|
|
|
|
|
|
710
|
105
|
100
|
100
|
|
|
172
|
if($ast->{facets} && $args->{show_facets}) |
|
711
|
3
|
|
|
|
|
4
|
{ my $facets = $ast->{facets}; |
|
712
|
3
|
50
|
|
|
|
9
|
my @facets = ref $facets ? @$facets : $facets; |
|
713
|
3
|
|
|
|
|
17
|
s/^/# /gm for @facets; |
|
714
|
3
|
|
|
|
|
5
|
push @lines, @facets; |
|
715
|
|
|
|
|
|
|
} |
|
716
|
|
|
|
|
|
|
|
|
717
|
105
|
|
|
|
|
102
|
my @childs; |
|
718
|
105
|
100
|
|
|
|
172
|
push @childs, @{$ast->{attrs}} if $ast->{attrs}; |
|
|
21
|
|
|
|
|
33
|
|
|
719
|
105
|
100
|
|
|
|
154
|
push @childs, @{$ast->{elems}} if $ast->{elems}; |
|
|
46
|
|
|
|
|
76
|
|
|
720
|
105
|
50
|
|
|
|
155
|
push @childs, $ast->{body} if $ast->{body}; |
|
721
|
|
|
|
|
|
|
|
|
722
|
105
|
|
|
|
|
100
|
my @subs; |
|
723
|
105
|
|
|
|
|
131
|
foreach my $child (@childs) |
|
724
|
89
|
|
|
|
|
398
|
{ my @sub = $self->_perlAny($child, $args); |
|
725
|
89
|
50
|
|
|
|
163
|
@sub or next; |
|
726
|
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
# last line is code and gets comma |
|
728
|
89
|
50
|
|
|
|
545
|
$sub[-1] =~ s/\,?\s*$/,/ |
|
729
|
|
|
|
|
|
|
if $sub[-1] !~ m/\#\s/; |
|
730
|
|
|
|
|
|
|
|
|
731
|
89
|
100
|
|
|
|
197
|
if(ref $ast ne 'BLOCK') |
|
732
|
46
|
|
|
|
|
637
|
{ s/^(.)/$args->{indent}$1/ for @sub; |
|
733
|
|
|
|
|
|
|
} |
|
734
|
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
# seperator blank, sometimes |
|
736
|
89
|
100
|
100
|
|
|
343
|
unshift @sub, '' |
|
|
|
|
100
|
|
|
|
|
|
737
|
|
|
|
|
|
|
if $sub[0] =~ m/^\s*[#{]/ # } |
|
738
|
|
|
|
|
|
|
|| (@subs && $subs[-1] =~ m/[}\]]\,\s*$/); |
|
739
|
|
|
|
|
|
|
|
|
740
|
89
|
|
|
|
|
296
|
push @subs, @sub; |
|
741
|
|
|
|
|
|
|
} |
|
742
|
|
|
|
|
|
|
|
|
743
|
105
|
100
|
|
|
|
206
|
if(ref $ast eq 'REP-BLOCK') |
|
744
|
|
|
|
|
|
|
{ # repeated block |
|
745
|
3
|
50
|
|
|
|
8
|
@subs or @subs = ''; |
|
746
|
3
|
100
|
|
|
|
13
|
$subs[0] =~ s/^ /{ / or $subs[0] =~ s/^\s*$/{/; |
|
747
|
3
|
50
|
|
|
|
12
|
if($subs[-1] =~ m/\#\s/) { push @subs, "}," } |
|
|
0
|
|
|
|
|
0
|
|
|
748
|
3
|
|
|
|
|
11
|
else { $subs[-1] =~ s/$/ },/ } |
|
749
|
|
|
|
|
|
|
} |
|
750
|
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
# XML does not permit difficult tags, but we still check. |
|
752
|
105
|
|
100
|
|
|
205
|
my $tag = $ast->{tag} || ''; |
|
753
|
105
|
100
|
66
|
|
|
477
|
if(defined $tag && $tag !~ m/^[\w_][\w\d_]*$/) |
|
754
|
3
|
|
|
|
|
4
|
{ $tag =~ s/\\/\\\\/g; |
|
755
|
3
|
|
|
|
|
5
|
$tag =~ s/'/\\'/g; |
|
756
|
3
|
|
|
|
|
3
|
$tag = qq{'$tag'}; |
|
757
|
|
|
|
|
|
|
} |
|
758
|
|
|
|
|
|
|
|
|
759
|
105
|
|
100
|
|
|
238
|
my $kind = $ast->{kind} || ''; |
|
760
|
105
|
100
|
33
|
|
|
522
|
if(ref $ast eq 'REP-BLOCK') |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
761
|
3
|
|
|
|
|
79
|
{ s/^(.)/ $1/ for @subs; |
|
762
|
3
|
|
|
|
|
11
|
$subs[0] =~ s/^ ?/[/; |
|
763
|
3
|
|
|
|
|
12
|
push @lines, "$tag => ", @subs , ']'; |
|
764
|
|
|
|
|
|
|
} |
|
765
|
|
|
|
|
|
|
elsif(ref $ast eq 'BLOCK') |
|
766
|
22
|
|
|
|
|
57
|
{ push @lines, @subs; |
|
767
|
|
|
|
|
|
|
} |
|
768
|
|
|
|
|
|
|
elsif(@subs) |
|
769
|
21
|
100
|
|
|
|
55
|
{ length $subs[0] or shift @subs; |
|
770
|
21
|
100
|
|
|
|
56
|
if($ast->{is_array}) |
|
771
|
3
|
|
|
|
|
58
|
{ s/^(.)/ $1/ for @subs; |
|
772
|
3
|
|
|
|
|
12
|
$subs[0] =~ s/^[ ]{0,3}/[ {/; |
|
773
|
3
|
50
|
33
|
|
|
18
|
if($subs[-1] =~ m/\#\s/ || $self->{_style}==2) |
|
774
|
0
|
|
|
|
|
0
|
{ push @subs, "}, ], " } |
|
775
|
3
|
|
|
|
|
8
|
else { $subs[-1] .= ' }, ], ' } |
|
776
|
3
|
|
|
|
|
13
|
push @lines, "$tag =>", @subs; |
|
777
|
|
|
|
|
|
|
} |
|
778
|
|
|
|
|
|
|
else |
|
779
|
18
|
|
|
|
|
77
|
{ $subs[0] =~ s/^ /{ /; |
|
780
|
18
|
50
|
|
|
|
79
|
if($self->{_style}==2) |
|
|
|
50
|
|
|
|
|
|
|
781
|
0
|
|
|
|
|
0
|
{ push @subs, "}, "; |
|
782
|
0
|
0
|
|
|
|
0
|
$subs[-1] .= "# $pref" if $pref; |
|
783
|
|
|
|
|
|
|
} |
|
784
|
0
|
|
|
|
|
0
|
elsif($subs[-1] =~ m/\#\s/) { push @subs, "}, " } |
|
785
|
18
|
|
|
|
|
48
|
else { $subs[-1] .= ' },' } |
|
786
|
18
|
|
|
|
|
117
|
push @lines, "$tag =>", @subs; |
|
787
|
|
|
|
|
|
|
} |
|
788
|
|
|
|
|
|
|
} |
|
789
|
|
|
|
|
|
|
elsif($kind eq 'complex' || $kind eq 'mixed') # empty complex-type |
|
790
|
|
|
|
|
|
|
{ # if there is an "occurs", then there can always be more than one |
|
791
|
0
|
0
|
|
|
|
0
|
push @lines, $tag.' => '.($ast->{occur} ? '[{},]' : '{}'); |
|
792
|
|
|
|
|
|
|
} |
|
793
|
|
|
|
|
|
|
elsif($kind eq 'collapsed') {;} |
|
794
|
|
|
|
|
|
|
elsif($kind eq 'union') # union type |
|
795
|
0
|
|
|
|
|
0
|
{ foreach my $union ( @{$ast->{choice}} ) |
|
|
0
|
|
|
|
|
0
|
|
|
796
|
|
|
|
|
|
|
{ # remove examples |
|
797
|
0
|
|
|
|
|
0
|
my @l = grep { m/^#/ } $self->_perlAny($union, $args); |
|
|
0
|
|
|
|
|
0
|
|
|
798
|
0
|
|
|
|
|
0
|
s/^\#/# -/ for $l[0]; |
|
799
|
0
|
|
|
|
|
0
|
s/^\#/# / for @l[1..$#l]; |
|
800
|
0
|
|
|
|
|
0
|
push @lines, @l; |
|
801
|
|
|
|
|
|
|
} |
|
802
|
|
|
|
|
|
|
} |
|
803
|
|
|
|
|
|
|
elsif(!exists $ast->{example}) |
|
804
|
0
|
|
|
|
|
0
|
{ push @lines, "$tag => 'TEMPLATE-ERROR $ast->{kind}'"; |
|
805
|
|
|
|
|
|
|
} |
|
806
|
|
|
|
|
|
|
|
|
807
|
105
|
|
|
|
|
162
|
my $example = $ast->{example}; |
|
808
|
105
|
100
|
|
|
|
159
|
if(defined $example) |
|
809
|
59
|
50
|
100
|
|
|
369
|
{ $example = qq{"$example"} # in quotes unless |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
810
|
|
|
|
|
|
|
if $example !~ m/^[+-]?\d+(?:\.\d+)?$/ # numeric or |
|
811
|
|
|
|
|
|
|
&& $example !~ m/^\$/ # variable or |
|
812
|
|
|
|
|
|
|
&& $example !~ m/^bless\b/ # constructor or |
|
813
|
|
|
|
|
|
|
&& $example !~ m/^\$?[\w:]*\-\>/ # method call example |
|
814
|
|
|
|
|
|
|
&& $example !~ m/^\{.*\}$/ # anon HASH example |
|
815
|
|
|
|
|
|
|
&& $example !~ m/^\[.*\]$/; # anon ARRAY example |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
push @lines, "$tag => " |
|
818
|
59
|
100
|
|
|
|
232
|
. ($ast->{is_array} ? "[ $example, ]" : $example); |
|
819
|
|
|
|
|
|
|
} |
|
820
|
105
|
|
|
|
|
516
|
@lines; |
|
821
|
|
|
|
|
|
|
} |
|
822
|
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
### |
|
824
|
|
|
|
|
|
|
### toXML |
|
825
|
|
|
|
|
|
|
### |
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
sub toXML($$%) |
|
828
|
2
|
|
|
2
|
0
|
11
|
{ my ($self, $doc, $ast, %args) = @_; |
|
829
|
2
|
|
|
|
|
12
|
my $xml = $self->_xmlAny($doc, $ast, "\n$args{indent}", \%args); |
|
830
|
|
|
|
|
|
|
|
|
831
|
2
|
50
|
|
|
|
100
|
UNIVERSAL::isa($xml, 'XML::LibXML::Element') |
|
832
|
|
|
|
|
|
|
or return $xml; |
|
833
|
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
# add comment |
|
835
|
2
|
|
|
|
|
3
|
my $pkg = __PACKAGE__; |
|
836
|
2
|
|
|
|
|
104
|
my $now = localtime(); |
|
837
|
|
|
|
|
|
|
|
|
838
|
2
|
|
|
|
|
22
|
my $header = $doc->createComment( <<_HEADER . ' ' ); |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
BE WARNED: in most cases, the example below cannot be used without |
|
841
|
|
|
|
|
|
|
interpretation. The comments will guide you. |
|
842
|
|
|
|
|
|
|
Produced by $pkg version $VERSION |
|
843
|
|
|
|
|
|
|
on $now |
|
844
|
|
|
|
|
|
|
_HEADER |
|
845
|
|
|
|
|
|
|
|
|
846
|
2
|
50
|
|
|
|
15
|
unless($args{skip_header}) |
|
847
|
0
|
|
|
|
|
0
|
{ $xml->insertBefore($header, $xml->firstChild); |
|
848
|
0
|
|
|
|
|
0
|
$xml->insertBefore($doc->createTextNode("\n "), $header); |
|
849
|
|
|
|
|
|
|
} |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
# I use xsi:type myself, too late for the usual "used" counter |
|
852
|
|
|
|
|
|
|
$ast->{'xmlns:xsi'} ||= SCHEMA2001i |
|
853
|
2
|
100
|
50
|
|
|
11
|
if $args{show_type}; |
|
854
|
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
# add info about name-spaces |
|
856
|
2
|
|
|
|
|
15
|
foreach (sort keys %$ast) |
|
857
|
20
|
100
|
|
|
|
83
|
{ if( m/^xmlns\:(.*)/ ) |
|
858
|
6
|
|
|
|
|
18
|
{ $xml->setNamespace($ast->{$_}, $1, 0); |
|
859
|
|
|
|
|
|
|
} |
|
860
|
|
|
|
|
|
|
} |
|
861
|
|
|
|
|
|
|
|
|
862
|
2
|
|
|
|
|
29
|
$xml; |
|
863
|
|
|
|
|
|
|
} |
|
864
|
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
sub _xmlAny($$$$); |
|
866
|
|
|
|
|
|
|
sub _xmlAny($$$$) |
|
867
|
42
|
|
|
42
|
|
68
|
{ my ($self, $doc, $ast, $indent, $args) = @_; |
|
868
|
42
|
|
|
|
|
41
|
my @res; |
|
869
|
|
|
|
|
|
|
my $xsi = $self->_registerNSprefix('xsi', SCHEMA2001i, 1) |
|
870
|
42
|
100
|
|
|
|
91
|
if $args->{show_type}; |
|
871
|
|
|
|
|
|
|
|
|
872
|
42
|
|
|
|
|
41
|
my @comment; |
|
873
|
42
|
100
|
100
|
|
|
96
|
if($ast->{struct} && $args->{show_struct}) |
|
874
|
17
|
|
|
|
|
20
|
{ my $struct = $ast->{struct}; |
|
875
|
17
|
50
|
|
|
|
34
|
push @comment, ref $struct ? @$struct : $struct; |
|
876
|
|
|
|
|
|
|
} |
|
877
|
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
push @comment, $ast->{occur} |
|
879
|
42
|
100
|
100
|
|
|
65
|
if $ast->{occur} && $args->{show_occur}; |
|
880
|
|
|
|
|
|
|
|
|
881
|
42
|
100
|
100
|
|
|
65
|
if($ast->{facets} && $args->{show_facets}) |
|
882
|
2
|
|
|
|
|
3
|
{ my $facets = $ast->{facets}; |
|
883
|
2
|
50
|
|
|
|
7
|
push @comment, ref $facets eq 'ARRAY' ? @$facets : $facets; |
|
884
|
|
|
|
|
|
|
} |
|
885
|
|
|
|
|
|
|
|
|
886
|
42
|
50
|
66
|
|
|
94
|
if(defined $ast->{kind} && $ast->{kind} eq 'union') |
|
887
|
0
|
|
|
|
|
0
|
{ push @comment, map " $_->{type}", @{$ast->{choice}}; |
|
|
0
|
|
|
|
|
0
|
|
|
888
|
|
|
|
|
|
|
} |
|
889
|
|
|
|
|
|
|
|
|
890
|
42
|
100
|
|
|
|
37
|
my @attrs = @{$ast->{attrs} || []}; |
|
|
42
|
|
|
|
|
92
|
|
|
891
|
42
|
|
|
|
|
63
|
foreach my $attr (@attrs) |
|
892
|
8
|
|
|
|
|
52
|
{ push @res, $doc->createAttribute($attr->{tag}, $attr->{example}); |
|
893
|
8
|
|
|
|
|
21
|
my ($ns, $local) = unpack_type $attr->{_TYPE}; |
|
894
|
8
|
|
|
|
|
18
|
my $prefix = $self->_registerNSprefix('', $ns, 1); |
|
895
|
|
|
|
|
|
|
push @comment, "attr $attr->{tag} has type $prefix:$local" |
|
896
|
8
|
100
|
|
|
|
25
|
if $args->{show_type}; |
|
897
|
|
|
|
|
|
|
} |
|
898
|
|
|
|
|
|
|
|
|
899
|
42
|
|
|
|
|
56
|
my $nest_indent = $indent.$args->{indent}; |
|
900
|
42
|
100
|
|
|
|
63
|
if(@comment) |
|
901
|
13
|
|
|
|
|
71
|
{ my $comment = ' '.join("$nest_indent ", @comment) .' '; |
|
902
|
13
|
|
|
|
|
88
|
push @res |
|
903
|
|
|
|
|
|
|
, $doc->createTextNode($indent) |
|
904
|
|
|
|
|
|
|
, $doc->createComment($comment); |
|
905
|
|
|
|
|
|
|
} |
|
906
|
|
|
|
|
|
|
|
|
907
|
42
|
100
|
|
|
|
45
|
my @elems = @{$ast->{elems} || []}; |
|
|
42
|
|
|
|
|
102
|
|
|
908
|
42
|
|
|
|
|
52
|
foreach my $elem (@elems) |
|
909
|
40
|
100
|
100
|
|
|
135
|
{ if(ref $elem eq 'BLOCK' || ref $elem eq 'REP-BLOCK') |
|
|
|
50
|
|
|
|
|
|
|
910
|
12
|
|
|
|
|
44
|
{ push @res, $self->_xmlAny($doc, $elem, $indent, $args); |
|
911
|
|
|
|
|
|
|
} |
|
912
|
|
|
|
|
|
|
elsif($elem->{tag} eq '_') |
|
913
|
0
|
|
|
|
|
0
|
{ push @res, $doc->createTextNode($indent.$elem->{example}); |
|
914
|
|
|
|
|
|
|
} |
|
915
|
|
|
|
|
|
|
else |
|
916
|
28
|
|
|
|
|
66
|
{ my $node = $self->_xmlAny($doc, $elem, $nest_indent, $args); |
|
917
|
28
|
50
|
|
|
|
210
|
push @res, $doc->createTextNode($indent) |
|
918
|
|
|
|
|
|
|
if $node->isa('XML::LibXML::Element'); |
|
919
|
28
|
|
|
|
|
48
|
push @res, $node; |
|
920
|
|
|
|
|
|
|
} |
|
921
|
|
|
|
|
|
|
} |
|
922
|
|
|
|
|
|
|
|
|
923
|
42
|
|
|
|
|
191
|
(my $outdent = $indent) =~ s/$args->{indent}$//; # sorry |
|
924
|
|
|
|
|
|
|
|
|
925
|
42
|
100
|
|
|
|
83
|
if(my $example = $ast->{example}) |
|
926
|
22
|
100
|
|
|
|
132
|
{ push @res, $doc->createTextNode |
|
927
|
|
|
|
|
|
|
(@comment ? "$indent$example$outdent" : $example) |
|
928
|
|
|
|
|
|
|
} |
|
929
|
|
|
|
|
|
|
|
|
930
|
42
|
100
|
100
|
|
|
93
|
if($ast->{_TYPE} && $args->{show_type}) |
|
931
|
15
|
|
|
|
|
38
|
{ my $pref = $self->prefixed($ast->{_TYPE}); |
|
932
|
15
|
|
|
|
|
153
|
push @res, $doc->createAttribute("$xsi:type" => $pref); |
|
933
|
|
|
|
|
|
|
} |
|
934
|
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
return @res |
|
936
|
42
|
100
|
|
|
|
99
|
if wantarray; |
|
937
|
|
|
|
|
|
|
|
|
938
|
30
|
|
|
|
|
99
|
my $node = $doc->createElement($ast->{tag}); |
|
939
|
30
|
|
|
|
|
243
|
$node->addChild($_) for @res; |
|
940
|
30
|
100
|
|
|
|
364
|
$node->appendText($outdent) if @elems; |
|
941
|
30
|
|
|
|
|
89
|
$node; |
|
942
|
|
|
|
|
|
|
} |
|
943
|
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
sub makeBlocked($$$) |
|
945
|
0
|
|
|
0
|
0
|
|
{ my ($self, $where, $class, $type) = @_; |
|
946
|
0
|
|
|
|
|
|
panic "namespace blocking not yet supported for Templates"; |
|
947
|
|
|
|
|
|
|
} |
|
948
|
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
1; |