line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
2
|
|
|
|
|
|
|
# Petal::Canonicalizer::XML - Builds an XML canonical Petal file |
3
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
4
|
|
|
|
|
|
|
# Author: Jean-Michel Hiver |
5
|
|
|
|
|
|
|
# Description: This modules mainly implements the XML::Parser |
6
|
|
|
|
|
|
|
# 'Stream' interface. It receives XML events and builds Petal |
7
|
|
|
|
|
|
|
# canonical data, i.e. |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# Hello |
10
|
|
|
|
|
|
|
# |
11
|
|
|
|
|
|
|
# Might be canonicalized to something like |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
# Hello |
15
|
|
|
|
|
|
|
# |
16
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
17
|
|
|
|
|
|
|
package Petal::Canonicalizer::XML; |
18
|
77
|
|
|
77
|
|
527
|
use Petal::Hash::String; |
|
77
|
|
|
|
|
166
|
|
|
77
|
|
|
|
|
2323
|
|
19
|
77
|
|
|
77
|
|
31788
|
use MKDoc::XML::Encode; |
|
77
|
|
|
|
|
17849
|
|
|
77
|
|
|
|
|
2070
|
|
20
|
77
|
|
|
77
|
|
488
|
use strict; |
|
77
|
|
|
|
|
142
|
|
|
77
|
|
|
|
|
1403
|
|
21
|
77
|
|
|
77
|
|
397
|
use warnings; |
|
77
|
|
|
|
|
130
|
|
|
77
|
|
|
|
|
1935
|
|
22
|
|
|
|
|
|
|
|
23
|
77
|
|
|
77
|
|
364
|
use vars qw /@Result @NodeStack/; |
|
77
|
|
|
|
|
129
|
|
|
77
|
|
|
|
|
296158
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# $class->process ($parser, $data_ref); |
27
|
|
|
|
|
|
|
# ------------------------------------- |
28
|
|
|
|
|
|
|
# returns undef if $parser object (i.e. a Petal::Parser::XML object) |
29
|
|
|
|
|
|
|
# could not parse the data which $data_ref pointed to. |
30
|
|
|
|
|
|
|
# |
31
|
|
|
|
|
|
|
# returns a reference to the canonicalized string otherwise. |
32
|
|
|
|
|
|
|
sub process |
33
|
|
|
|
|
|
|
{ |
34
|
206
|
|
|
206
|
0
|
783
|
my $class = shift; |
35
|
206
|
|
|
|
|
4266
|
my $parser = shift; |
36
|
206
|
|
|
|
|
442
|
my $data_ref = shift; |
37
|
206
|
50
|
|
|
|
607
|
$data_ref = (ref $data_ref) ? $data_ref : \$data_ref; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# grab anything that's before the first '<' tag |
40
|
206
|
|
|
|
|
1767
|
my ($header) = $$data_ref =~ /(^.*?)<(?!\?|\!)/sm; |
41
|
206
|
|
|
|
|
1968
|
$$data_ref =~ s/(^.*?)<(?!\?|\!)/\
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# grab the tags which the parser is going to strip |
44
|
|
|
|
|
|
|
# in order to reinclude them afterwards |
45
|
|
|
|
|
|
|
# my @decls = $$data_ref =~ /()/gsm; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# take the existing processing instructions out and replace |
48
|
|
|
|
|
|
|
# them with temporary xml-friendly handlers |
49
|
206
|
|
|
|
|
744
|
my $pis = $class->_processing_instructions_out ($data_ref); |
50
|
|
|
|
|
|
|
|
51
|
206
|
|
|
|
|
475
|
local @Result = (); |
52
|
206
|
|
|
|
|
334
|
local @NodeStack = (); |
53
|
|
|
|
|
|
|
|
54
|
206
|
|
|
|
|
666
|
$parser->process ($class, $data_ref); |
55
|
|
|
|
|
|
|
|
56
|
202
|
|
100
|
|
|
964
|
$header ||= ''; |
57
|
202
|
|
|
|
|
326
|
my $res = ''; |
58
|
202
|
100
|
|
|
|
626
|
$res .= $header unless ($Petal::CURRENT_INCLUDES > 1); |
59
|
202
|
|
|
|
|
1760
|
$res .= (join '', @Result); |
60
|
|
|
|
|
|
|
|
61
|
202
|
|
|
|
|
865
|
$class->_processing_instructions_in (\$res, $pis); |
62
|
|
|
|
|
|
|
|
63
|
202
|
|
|
|
|
1794
|
return \$res; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# _processing_instructions_out ($data_ref); |
68
|
|
|
|
|
|
|
# ----------------------------------------- |
69
|
|
|
|
|
|
|
# takes the existing processing instructions (i.e. blah ?>) |
70
|
|
|
|
|
|
|
# and replace them with temporary xml-friendly handlers (i.e. |
71
|
|
|
|
|
|
|
# [-- NBXNBBJBNJNBJVNK --] |
72
|
|
|
|
|
|
|
# |
73
|
|
|
|
|
|
|
# returns the blah ?> => [-- NBXNBBJBNJNBJVNK --] mapping |
74
|
|
|
|
|
|
|
# as a hashref |
75
|
|
|
|
|
|
|
# |
76
|
|
|
|
|
|
|
# NOTE: This is because processing instructions are special to |
77
|
|
|
|
|
|
|
# HTML::Parser, XML::Parser etc. and it's easier to just handle |
78
|
|
|
|
|
|
|
# them separately |
79
|
|
|
|
|
|
|
sub _processing_instructions_out |
80
|
|
|
|
|
|
|
{ |
81
|
206
|
|
|
206
|
|
342
|
my $class = shift; |
82
|
206
|
|
|
|
|
314
|
my $data_ref = shift; |
83
|
206
|
|
|
|
|
909
|
my %pis = map { $_ => $class->_compute_unique_string ($data_ref) } $$data_ref =~ /(<\?.*?\?>)/gsm; |
|
60
|
|
|
|
|
155
|
|
84
|
|
|
|
|
|
|
|
85
|
206
|
|
|
|
|
1002
|
while (my ($key, $value) = each %pis) { |
86
|
49
|
|
|
|
|
1630
|
$$data_ref =~ s/\Q$key\E/$value/gsm; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
206
|
|
|
|
|
462
|
return \%pis; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# _processing_instructions_in ($data_ref, $pis); |
94
|
|
|
|
|
|
|
# ---------------------------------------------- |
95
|
|
|
|
|
|
|
# takes the processing instructions mapping defined in the $pis |
96
|
|
|
|
|
|
|
# hashref and restores the processing instructions in the data |
97
|
|
|
|
|
|
|
# pointed by $data_ref |
98
|
|
|
|
|
|
|
sub _processing_instructions_in |
99
|
|
|
|
|
|
|
{ |
100
|
202
|
|
|
202
|
|
354
|
my $class = shift; |
101
|
202
|
|
|
|
|
289
|
my $data_ref = shift; |
102
|
202
|
|
|
|
|
287
|
my $pis = shift; |
103
|
202
|
|
|
|
|
350
|
while (my ($key, $value) = each %{$pis}) { |
|
251
|
|
|
|
|
1106
|
|
104
|
49
|
|
|
|
|
1606
|
$$data_ref =~ s/\Q$value\E/$key/gsm; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# _compute_unique_string ($data_ref) |
110
|
|
|
|
|
|
|
# ---------------------------------- |
111
|
|
|
|
|
|
|
# computes a string which does not exist in $$data_ref |
112
|
|
|
|
|
|
|
sub _compute_unique_string |
113
|
|
|
|
|
|
|
{ |
114
|
60
|
|
|
60
|
|
86
|
my $class = shift; |
115
|
60
|
|
|
|
|
71
|
my $data_ref = shift; |
116
|
60
|
|
|
|
|
138
|
my $string = '[-' . (join '', map { chr (ord ('a') + int rand 26) } 1..20) . '-]'; |
|
1200
|
|
|
|
|
2523
|
|
117
|
60
|
|
|
|
|
367
|
while (index ($$data_ref, $string) >= 0) |
118
|
|
|
|
|
|
|
{ |
119
|
0
|
|
|
|
|
0
|
$string = '[-' . (join '', map { chr (ord ('a') + int rand 26) } 1..20) . '-]'; |
|
0
|
|
|
|
|
0
|
|
120
|
|
|
|
|
|
|
} |
121
|
60
|
|
|
|
|
219
|
return $string; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# $class->StartTag(); |
126
|
|
|
|
|
|
|
# ------------------- |
127
|
|
|
|
|
|
|
# Called for every start tag with a second parameter of the element type. |
128
|
|
|
|
|
|
|
# It will check for special PETAL attributes like petal:if, petal:loop, etc... |
129
|
|
|
|
|
|
|
# and rewrite the start tag into @Result accordingly. |
130
|
|
|
|
|
|
|
# |
131
|
|
|
|
|
|
|
# For example |
132
|
|
|
|
|
|
|
# |
133
|
|
|
|
|
|
|
# |
134
|
|
|
|
|
|
|
# |
135
|
|
|
|
|
|
|
# Is rewritten |
136
|
|
|
|
|
|
|
# |
137
|
|
|
|
|
|
|
# ... |
138
|
|
|
|
|
|
|
sub StartTag |
139
|
|
|
|
|
|
|
{ |
140
|
1306
|
|
|
1306
|
0
|
3965
|
Petal::load_code_generator(); # we will use it later |
141
|
|
|
|
|
|
|
|
142
|
1306
|
|
|
|
|
1861
|
my $class = shift; |
143
|
1306
|
|
|
|
|
2406
|
push @NodeStack, {}; |
144
|
1306
|
100
|
|
|
|
3010
|
return if ($class->_is_inside_content_or_replace()); |
145
|
|
|
|
|
|
|
|
146
|
1299
|
|
|
|
|
1826
|
my $tag = $_; |
147
|
1299
|
|
|
|
|
6711
|
($tag) = $tag =~ /^<\s*((?:\w|\:|\-)*)/; |
148
|
1299
|
|
|
|
|
5221
|
my $att = { %_ }; |
149
|
|
|
|
|
|
|
|
150
|
1299
|
|
|
|
|
3798
|
$class->_use_macro ($tag, $att); |
151
|
1299
|
|
|
|
|
2984
|
$class->_on_error ($tag, $att); |
152
|
1299
|
|
|
|
|
3075
|
$class->_define ($tag, $att); |
153
|
1299
|
|
|
|
|
3075
|
$class->_define_slot ($tag, $att); |
154
|
1299
|
|
|
|
|
2852
|
$class->_condition ($tag, $att); |
155
|
1299
|
|
|
|
|
3056
|
$class->_repeat ($tag, $att); |
156
|
1299
|
100
|
66
|
|
|
2715
|
$class->_is_xinclude ($tag) and $class->_xinclude ($tag, $att) and return; |
157
|
1253
|
|
|
|
|
3672
|
$class->_replace ($tag, $att); |
158
|
|
|
|
|
|
|
|
159
|
1253
|
|
|
|
|
1963
|
my $petal = quotemeta ($Petal::NS); |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# if a petal:replace attribute was set, then at this point _is_inside_content_or_replace() |
162
|
|
|
|
|
|
|
# should return TRUE and this code should not be executed |
163
|
1253
|
100
|
|
|
|
2022
|
unless ($class->_is_inside_content_or_replace()) |
164
|
|
|
|
|
|
|
{ |
165
|
|
|
|
|
|
|
# for every attribute which is not a petal: attribute, |
166
|
|
|
|
|
|
|
# we need to convert $variable into |
167
|
1224
|
|
|
|
|
1555
|
foreach my $key (keys %{$att}) |
|
1224
|
|
|
|
|
4273
|
|
168
|
|
|
|
|
|
|
{ |
169
|
2008
|
100
|
|
|
|
5984
|
next if ($key =~ /^$petal:/); |
170
|
1922
|
|
|
|
|
3355
|
my $text = $att->{$key}; |
171
|
1922
|
|
|
|
|
2218
|
my $token_re = $Petal::Hash::String::TOKEN_RE; |
172
|
1922
|
|
|
|
|
6532
|
my @vars = $text =~ /$token_re/gsm; |
173
|
1922
|
|
|
|
|
2956
|
my %vars = map { $_ => 1 } @vars; |
|
3
|
|
|
|
|
27
|
|
174
|
1922
|
|
|
|
|
2971
|
@vars = sort { length ($b) <=> length ($a) } keys %vars; |
|
0
|
|
|
|
|
0
|
|
175
|
1922
|
|
|
|
|
2610
|
foreach my $var (@vars) |
176
|
|
|
|
|
|
|
{ |
177
|
3
|
|
|
|
|
18
|
my $command = $var; |
178
|
3
|
|
|
|
|
23
|
$command =~ s/^\$//; |
179
|
3
|
|
|
|
|
25
|
$command =~ s/^\{//; |
180
|
3
|
|
|
|
|
13
|
$command =~ s/\}$//; |
181
|
3
|
|
|
|
|
16
|
$command = $class->_encode_backslash_semicolon ($command); |
182
|
3
|
|
|
|
|
20
|
$command = ""; |
183
|
3
|
|
|
|
|
59
|
$text =~ s/\Q$var\E/$command/g; |
184
|
|
|
|
|
|
|
} |
185
|
1922
|
|
|
|
|
4356
|
$att->{$key} = $text; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# processes the petal:attributes instruction |
189
|
1224
|
|
|
|
|
3610
|
$class->_attributes ($tag, $att); |
190
|
|
|
|
|
|
|
|
191
|
1224
|
|
|
|
|
2032
|
my @att_str = (); |
192
|
1224
|
|
|
|
|
1436
|
foreach my $key (keys %{$att}) |
|
1224
|
|
|
|
|
3062
|
|
193
|
|
|
|
|
|
|
{ |
194
|
1987
|
100
|
|
|
|
5699
|
next if ($key =~ /^$petal:/); |
195
|
1930
|
|
|
|
|
3458
|
my $value = $att->{$key}; |
196
|
1930
|
100
|
|
|
|
3334
|
if ($value =~ /^<\?attr/) |
197
|
|
|
|
|
|
|
{ |
198
|
45
|
|
|
|
|
127
|
push @att_str, $value; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
else |
201
|
|
|
|
|
|
|
{ |
202
|
1885
|
|
|
|
|
4208
|
my $tokens = Petal::CodeGenerator->_tokenize (\$value); |
203
|
|
|
|
|
|
|
my @res = map { |
204
|
|
|
|
|
|
|
($_ =~ /$Petal::CodeGenerator::PI_RE/s) ? |
205
|
|
|
|
|
|
|
$_ : |
206
|
1884
|
100
|
|
|
|
5061
|
do { |
207
|
1881
|
|
|
|
|
2987
|
$_ =~ s/\&/&/g; |
208
|
1881
|
|
|
|
|
2386
|
$_ =~ s/\</g; |
209
|
1881
|
|
|
|
|
2242
|
$_ =~ s/\>/>/g; |
210
|
1881
|
|
|
|
|
2377
|
$_ =~ s/\"/"/g; |
211
|
1881
|
|
|
|
|
4138
|
$_; |
212
|
|
|
|
|
|
|
}; |
213
|
1885
|
|
|
|
|
2275
|
} @{$tokens}; |
|
1885
|
|
|
|
|
2559
|
|
214
|
1885
|
|
|
|
|
7899
|
push @att_str, $key . '="' . (join '', @res) . '"'; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
1224
|
|
|
|
|
3186
|
my $att_str = join " ", @att_str; |
219
|
|
|
|
|
|
|
|
220
|
1224
|
100
|
|
|
|
3086
|
if (defined $att->{"$petal:omit-tag"}) |
221
|
|
|
|
|
|
|
{ |
222
|
5
|
|
100
|
|
|
23
|
my $expression = $att->{"$petal:omit-tag"} || 'string:1'; |
223
|
5
|
|
|
|
|
16
|
$NodeStack[$#NodeStack]->{'omit-tag'} = $expression; |
224
|
5
|
100
|
66
|
|
|
60
|
push @Result, (defined $att_str and $att_str) ? |
225
|
|
|
|
|
|
|
"<$tag $att_str>" : |
226
|
|
|
|
|
|
|
"<$tag>"; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
else |
229
|
|
|
|
|
|
|
{ |
230
|
1219
|
100
|
66
|
|
|
6380
|
push @Result, (defined $att_str and $att_str) ? "<$tag $att_str>" : "<$tag>"; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
1224
|
|
|
|
|
3254
|
$class->_content ($tag, $att); |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# $class->EndTag(); |
239
|
|
|
|
|
|
|
# ----------------- |
240
|
|
|
|
|
|
|
# Called for every end tag with a second parameter of the element type. |
241
|
|
|
|
|
|
|
# It will check in the @NodeStack to see if this end-tag also needs to close |
242
|
|
|
|
|
|
|
# some 'condition' or 'repeat' statements, i.e. |
243
|
|
|
|
|
|
|
# |
244
|
|
|
|
|
|
|
# |
245
|
|
|
|
|
|
|
# |
246
|
|
|
|
|
|
|
# Could be rewritten |
247
|
|
|
|
|
|
|
# |
248
|
|
|
|
|
|
|
# |
249
|
|
|
|
|
|
|
# |
250
|
|
|
|
|
|
|
# If the starting LI used a loop, i.e. |
251
|
|
|
|
|
|
|
sub EndTag |
252
|
|
|
|
|
|
|
{ |
253
|
1306
|
|
|
1306
|
0
|
1761
|
my $class = shift; |
254
|
1306
|
100
|
|
|
|
2152
|
return if ($class->_is_inside_content_or_replace ( 'endtag' )); |
255
|
|
|
|
|
|
|
|
256
|
1294
|
|
|
|
|
6489
|
my ($tag) = $_ =~ /^<\/\s*((?:\w|\:|\-)*)/; |
257
|
1294
|
|
|
|
|
2329
|
my $node = pop (@NodeStack); |
258
|
|
|
|
|
|
|
|
259
|
1294
|
100
|
|
|
|
2623
|
return if ($class->_is_xinclude ($tag)); |
260
|
|
|
|
|
|
|
|
261
|
1248
|
100
|
66
|
|
|
3364
|
unless (defined $node->{replace} and $node->{replace}) |
262
|
|
|
|
|
|
|
{ |
263
|
1224
|
100
|
|
|
|
2321
|
if (exists $node->{'omit-tag'}) |
264
|
|
|
|
|
|
|
{ |
265
|
5
|
|
|
|
|
13
|
my $expression = $node->{'omit-tag'}; |
266
|
5
|
|
|
|
|
22
|
push @Result, "$tag>"; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
else |
269
|
|
|
|
|
|
|
{ |
270
|
1219
|
|
|
|
|
3362
|
push @Result, "$tag>"; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
1248
|
|
100
|
|
|
3810
|
my $repeat = $node->{repeat} || '0'; |
275
|
1248
|
|
100
|
|
|
3168
|
my $condition = $node->{condition} || '0'; |
276
|
1248
|
|
100
|
|
|
2938
|
my $define_slot = $node->{define_slot} || '0'; |
277
|
1248
|
|
|
|
|
2783
|
push @Result, map { '' } 1 .. ($repeat+$condition+$define_slot); |
|
58
|
|
|
|
|
157
|
|
278
|
|
|
|
|
|
|
|
279
|
1248
|
100
|
66
|
|
|
3101
|
unless (defined $node->{replace} and $node->{replace}) |
280
|
|
|
|
|
|
|
{ |
281
|
1224
|
100
|
|
|
|
3585
|
if (exists $node->{'on-error'}) |
282
|
|
|
|
|
|
|
{ |
283
|
4
|
|
|
|
|
8
|
my $expression = $node->{'on-error'}; |
284
|
4
|
|
|
|
|
23
|
push @Result, ""; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# $class->Text(); |
291
|
|
|
|
|
|
|
# --------------- |
292
|
|
|
|
|
|
|
# Called just before start or end tags. |
293
|
|
|
|
|
|
|
# Turns all variables such as $foo:bar into |
294
|
|
|
|
|
|
|
sub Text |
295
|
|
|
|
|
|
|
{ |
296
|
2118
|
|
|
2118
|
0
|
2877
|
my $class = shift; |
297
|
2118
|
100
|
|
|
|
3526
|
return if ($class->_is_inside_content_or_replace()); |
298
|
2017
|
|
|
|
|
2893
|
my $text = $_; |
299
|
2017
|
|
|
|
|
2700
|
my $token_re = $Petal::Hash::String::TOKEN_RE; |
300
|
2017
|
|
|
|
|
9713
|
my @vars = $text =~ /$token_re/gsm; |
301
|
2017
|
|
|
|
|
3355
|
my %vars = map { $_ => 1 } @vars; |
|
64
|
|
|
|
|
272
|
|
302
|
2017
|
|
|
|
|
4020
|
@vars = sort { length ($b) <=> length ($a) } keys %vars; |
|
25
|
|
|
|
|
137
|
|
303
|
2017
|
|
|
|
|
3213
|
foreach my $var (@vars) |
304
|
|
|
|
|
|
|
{ |
305
|
64
|
|
|
|
|
138
|
my $command = $var; |
306
|
64
|
|
|
|
|
273
|
$command =~ s/^\$//; |
307
|
64
|
|
|
|
|
142
|
$command =~ s/^\{//; |
308
|
64
|
|
|
|
|
125
|
$command =~ s/\}$//; |
309
|
64
|
|
|
|
|
160
|
$command = $class->_encode_backslash_semicolon ($command); |
310
|
64
|
|
|
|
|
179
|
$command = ""; |
311
|
64
|
|
|
|
|
923
|
$text =~ s/\Q$var\E/$command/g; |
312
|
|
|
|
|
|
|
} |
313
|
2017
|
|
|
|
|
8060
|
push @Result, $text; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# _is_inside_content_or_replace(); |
318
|
|
|
|
|
|
|
# -------------------------------- |
319
|
|
|
|
|
|
|
# Returns TRUE if @NodeStack contains a node which has a |
320
|
|
|
|
|
|
|
# 'content' or a 'replace' attribute set. |
321
|
|
|
|
|
|
|
sub _is_inside_content_or_replace |
322
|
|
|
|
|
|
|
{ |
323
|
18855
|
|
|
18855
|
|
20925
|
my $class = shift; |
324
|
18855
|
|
|
|
|
19549
|
my $endtag = shift; |
325
|
18855
|
|
|
|
|
19801
|
my $tmp = undef; |
326
|
18855
|
100
|
|
|
|
27165
|
$tmp = pop (@NodeStack) if ($endtag); |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# WHY do I have to do this? |
329
|
18855
|
100
|
100
|
|
|
29658
|
return 1 if (defined $tmp and $tmp->{'use-macro'}); |
330
|
18846
|
|
|
|
|
33564
|
for (my $i=@NodeStack - 1; $i >= 0; $i--) |
331
|
|
|
|
|
|
|
{ |
332
|
|
|
|
|
|
|
return 1 if ( defined $NodeStack[$i]->{'replace'} or |
333
|
|
|
|
|
|
|
defined $NodeStack[$i]->{'content'} or |
334
|
63943
|
100
|
100
|
|
|
251378
|
defined $NodeStack[$i]->{'use-macro'} ); |
|
|
|
100
|
|
|
|
|
335
|
|
|
|
|
|
|
} |
336
|
18631
|
100
|
|
|
|
26957
|
push @NodeStack, $tmp if (defined $tmp); |
337
|
18631
|
|
|
|
|
34430
|
return; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# _split_expression ($expr); |
342
|
|
|
|
|
|
|
# -------------------------- |
343
|
|
|
|
|
|
|
# Splits multiple semicolon separated expressions, which |
344
|
|
|
|
|
|
|
# are mainly used for the petal:attributes attribute, i.e. |
345
|
|
|
|
|
|
|
# would turn "href document.uri; lang document.lang; xml:lang document.lang" |
346
|
|
|
|
|
|
|
# into ("href document.uri", "lang document.lang", "xml:lang document.lang") |
347
|
|
|
|
|
|
|
sub _split_expression |
348
|
|
|
|
|
|
|
{ |
349
|
220
|
|
|
220
|
|
329
|
my $class = shift; |
350
|
220
|
|
|
|
|
296
|
my $expression = shift; |
351
|
220
|
100
|
66
|
|
|
1516
|
my @tokens = map { (defined $_ and $_) ? $_ : () } |
|
296
|
|
|
|
|
1480
|
|
352
|
|
|
|
|
|
|
split /(\s|\r|\n)*(?
|
353
|
|
|
|
|
|
|
$expression; |
354
|
|
|
|
|
|
|
|
355
|
220
|
|
|
|
|
443
|
return map { s/^(\s|\n|\r)+//sm; |
|
270
|
|
|
|
|
860
|
|
356
|
270
|
|
|
|
|
1319
|
s/(\s|\n|\r)+$//sm; |
357
|
270
|
100
|
|
|
|
914
|
($_ eq '') ? () : $_ } @tokens; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
# _condition; |
362
|
|
|
|
|
|
|
# ----------- |
363
|
|
|
|
|
|
|
# Rewrites statements into |
364
|
|
|
|
|
|
|
# |
365
|
|
|
|
|
|
|
sub _on_error |
366
|
|
|
|
|
|
|
{ |
367
|
1411
|
|
|
1411
|
|
1713
|
my $class = shift; |
368
|
1411
|
100
|
|
|
|
2138
|
return if ($class->_is_inside_content_or_replace()); |
369
|
|
|
|
|
|
|
|
370
|
1402
|
|
|
|
|
2165
|
my $petal = quotemeta ($Petal::NS); |
371
|
1402
|
|
|
|
|
1706
|
my $tag = shift; |
372
|
1402
|
|
|
|
|
1619
|
my $att = shift; |
373
|
1402
|
|
100
|
|
|
3384
|
my $expr = delete $att->{"$petal:on-error"} || return; |
374
|
|
|
|
|
|
|
|
375
|
4
|
|
|
|
|
11
|
$expr = $class->_encode_backslash_semicolon ($expr); |
376
|
4
|
|
|
|
|
11
|
push @Result, ""; |
377
|
4
|
|
|
|
|
11
|
$NodeStack[$#NodeStack]->{'on-error'} = $expr; |
378
|
4
|
|
|
|
|
7
|
return 1; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# _define; |
383
|
|
|
|
|
|
|
# -------- |
384
|
|
|
|
|
|
|
# Rewrites statements into |
385
|
|
|
|
|
|
|
# canonical |
386
|
|
|
|
|
|
|
sub _define |
387
|
|
|
|
|
|
|
{ |
388
|
1411
|
|
|
1411
|
|
1750
|
my $class = shift; |
389
|
1411
|
100
|
|
|
|
2207
|
return if ($class->_is_inside_content_or_replace()); |
390
|
|
|
|
|
|
|
|
391
|
1402
|
|
|
|
|
1818
|
my $petal = $Petal::NS; |
392
|
1402
|
|
|
|
|
1719
|
my $tag = shift; |
393
|
1402
|
|
|
|
|
1541
|
my $att = shift; |
394
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:set"} || |
395
|
|
|
|
|
|
|
delete $att->{"$petal:def"} || |
396
|
1402
|
|
100
|
|
|
7732
|
delete $att->{"$petal:define"} || return; |
397
|
|
|
|
|
|
|
|
398
|
16
|
|
|
|
|
126
|
$expr = $class->_encode_backslash_semicolon ($expr); |
399
|
16
|
|
|
|
|
79
|
push @Result, map { "" } $class->_split_expression ($expr); |
|
23
|
|
|
|
|
83
|
|
400
|
16
|
|
|
|
|
38
|
return 1; |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# _condition; |
405
|
|
|
|
|
|
|
# ----------- |
406
|
|
|
|
|
|
|
# Rewrites statements into |
407
|
|
|
|
|
|
|
# |
408
|
|
|
|
|
|
|
sub _condition |
409
|
|
|
|
|
|
|
{ |
410
|
1411
|
|
|
1411
|
|
1786
|
my $class = shift; |
411
|
1411
|
100
|
|
|
|
2136
|
return if ($class->_is_inside_content_or_replace()); |
412
|
|
|
|
|
|
|
|
413
|
1402
|
|
|
|
|
1845
|
my $petal = $Petal::NS; |
414
|
1402
|
|
|
|
|
1750
|
my $tag = shift; |
415
|
1402
|
|
|
|
|
1705
|
my $att = shift; |
416
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:if"} || |
417
|
1402
|
|
100
|
|
|
5573
|
delete $att->{"$petal:condition"} || return; |
418
|
|
|
|
|
|
|
|
419
|
40
|
|
|
|
|
149
|
$expr = $class->_encode_backslash_semicolon ($expr); |
420
|
40
|
|
|
|
|
123
|
my @new = map { "" } $class->_split_expression ($expr); |
|
41
|
|
|
|
|
186
|
|
421
|
40
|
|
|
|
|
99
|
push @Result, @new; |
422
|
40
|
|
|
|
|
163
|
$NodeStack[$#NodeStack]->{condition} = scalar @new; |
423
|
40
|
|
|
|
|
113
|
return 1; |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
# _define_slot; |
428
|
|
|
|
|
|
|
# ----------- |
429
|
|
|
|
|
|
|
# Rewrites statements into |
430
|
|
|
|
|
|
|
# |
431
|
|
|
|
|
|
|
sub _define_slot |
432
|
|
|
|
|
|
|
{ |
433
|
1411
|
|
|
1411
|
|
1724
|
my $class = shift; |
434
|
1411
|
100
|
|
|
|
2279
|
return if ($class->_is_inside_content_or_replace()); |
435
|
|
|
|
|
|
|
|
436
|
1402
|
|
|
|
|
1773
|
my $metal = $Petal::MT_NS; |
437
|
1402
|
|
|
|
|
1814
|
my $tag = shift; |
438
|
1402
|
|
|
|
|
1659
|
my $att = shift; |
439
|
1402
|
|
100
|
|
|
3275
|
my $expr = delete $att->{"$metal:define-slot"} || return; |
440
|
|
|
|
|
|
|
|
441
|
4
|
|
|
|
|
17
|
$expr = $class->_encode_backslash_semicolon ($expr); |
442
|
4
|
|
|
|
|
14
|
my @new = map { "" } $class->_split_expression ($expr); |
|
4
|
|
|
|
|
17
|
|
443
|
4
|
|
|
|
|
10
|
push @Result, @new; |
444
|
4
|
|
|
|
|
16
|
$NodeStack[$#NodeStack]->{define_slot} = 2 * scalar @new; |
445
|
4
|
|
|
|
|
9
|
return 1; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
# _repeat; |
450
|
|
|
|
|
|
|
# -------- |
451
|
|
|
|
|
|
|
# Rewrites statements into |
452
|
|
|
|
|
|
|
# |
453
|
|
|
|
|
|
|
sub _repeat |
454
|
|
|
|
|
|
|
{ |
455
|
1411
|
|
|
1411
|
|
1740
|
my $class = shift; |
456
|
1411
|
100
|
|
|
|
2300
|
return if ($class->_is_inside_content_or_replace()); |
457
|
|
|
|
|
|
|
|
458
|
1402
|
|
|
|
|
1735
|
my $petal = $Petal::NS; |
459
|
1402
|
|
|
|
|
1744
|
my $tag = shift; |
460
|
1402
|
|
|
|
|
1655
|
my $att = shift; |
461
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:for"} || |
462
|
|
|
|
|
|
|
delete $att->{"$petal:foreach"} || |
463
|
|
|
|
|
|
|
delete $att->{"$petal:loop"} || |
464
|
1402
|
|
100
|
|
|
10216
|
delete $att->{"$petal:repeat"} || return; |
465
|
|
|
|
|
|
|
|
466
|
30
|
|
|
|
|
117
|
my @exprs = $class->_split_expression ($expr); |
467
|
30
|
|
|
|
|
68
|
my @new = (); |
468
|
30
|
|
|
|
|
78
|
foreach $expr (@exprs) |
469
|
|
|
|
|
|
|
{ |
470
|
30
|
|
|
|
|
90
|
$expr = $class->_encode_backslash_semicolon ($expr); |
471
|
30
|
|
|
|
|
129
|
push @new, "" |
472
|
|
|
|
|
|
|
} |
473
|
30
|
|
|
|
|
66
|
push @Result, @new; |
474
|
30
|
|
|
|
|
100
|
$NodeStack[$#NodeStack]->{repeat} = scalar @new; |
475
|
30
|
|
|
|
|
71
|
return 1; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# _replace; |
480
|
|
|
|
|
|
|
# --------- |
481
|
|
|
|
|
|
|
# Rewrites as |
482
|
|
|
|
|
|
|
# All the descendent nodes of 'tag' will be skipped |
483
|
|
|
|
|
|
|
sub _replace |
484
|
|
|
|
|
|
|
{ |
485
|
1364
|
|
|
1364
|
|
1688
|
my $class = shift; |
486
|
1364
|
100
|
|
|
|
2289
|
return if ($class->_is_inside_content_or_replace()); |
487
|
|
|
|
|
|
|
|
488
|
1355
|
|
|
|
|
1808
|
my $petal = $Petal::NS; |
489
|
1355
|
|
|
|
|
1698
|
my $tag = shift; |
490
|
1355
|
|
|
|
|
1559
|
my $att = shift; |
491
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:replace"} || |
492
|
1355
|
|
100
|
|
|
5694
|
delete $att->{"$petal:outer"} || return; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
my @new = map { |
495
|
29
|
|
|
|
|
118
|
$_ = $class->_encode_backslash_semicolon ($_); |
|
29
|
|
|
|
|
116
|
|
496
|
29
|
|
|
|
|
122
|
""; |
497
|
|
|
|
|
|
|
} $class->_split_expression ($expr); |
498
|
|
|
|
|
|
|
|
499
|
29
|
|
|
|
|
89
|
push @Result, @new; |
500
|
29
|
|
|
|
|
87
|
$NodeStack[$#NodeStack]->{replace} = 'true'; |
501
|
29
|
|
|
|
|
70
|
return 1; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
# _use_macro; |
506
|
|
|
|
|
|
|
# ----------- |
507
|
|
|
|
|
|
|
# Rewrites |
508
|
|
|
|
|
|
|
# All the descendent nodes of 'tag' will be skipped |
509
|
|
|
|
|
|
|
sub _use_macro |
510
|
|
|
|
|
|
|
{ |
511
|
1411
|
|
|
1411
|
|
1929
|
my $class = shift; |
512
|
1411
|
50
|
|
|
|
2231
|
return if ($class->_is_inside_content_or_replace()); |
513
|
|
|
|
|
|
|
|
514
|
1411
|
|
|
|
|
1815
|
my $metal = $Petal::MT_NS; |
515
|
|
|
|
|
|
|
|
516
|
1411
|
|
|
|
|
1830
|
my $tag = shift; |
517
|
1411
|
|
|
|
|
1568
|
my $att = shift; |
518
|
1411
|
|
100
|
|
|
3933
|
my $expr = delete $att->{"$metal:use-macro"} || return; |
519
|
|
|
|
|
|
|
|
520
|
9
|
|
|
|
|
26
|
push @Result, qq||; |
521
|
9
|
|
|
|
|
44
|
$NodeStack[$#NodeStack]->{'use-macro'} = 'true'; |
522
|
9
|
|
|
|
|
18
|
return 1; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
# _attributes; |
527
|
|
|
|
|
|
|
# ------------ |
528
|
|
|
|
|
|
|
# Rewrites |
529
|
|
|
|
|
|
|
# as |
530
|
|
|
|
|
|
|
sub _attributes |
531
|
|
|
|
|
|
|
{ |
532
|
1326
|
|
|
1326
|
|
1812
|
my $class = shift; |
533
|
1326
|
50
|
|
|
|
2097
|
return if ($class->_is_inside_content_or_replace()); |
534
|
|
|
|
|
|
|
|
535
|
1326
|
|
|
|
|
1744
|
my $petal = $Petal::NS; |
536
|
1326
|
|
|
|
|
1722
|
my $tag = shift; |
537
|
1326
|
|
|
|
|
1559
|
my $att = shift; |
538
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:att"} || |
539
|
|
|
|
|
|
|
delete $att->{"$petal:attr"} || |
540
|
|
|
|
|
|
|
delete $att->{"$petal:atts"} || |
541
|
1326
|
|
100
|
|
|
10305
|
delete $att->{"$petal:attributes"} || return; |
542
|
|
|
|
|
|
|
|
543
|
37
|
|
|
|
|
166
|
foreach my $string ($class->_split_expression ($expr)) |
544
|
|
|
|
|
|
|
{ |
545
|
53
|
50
|
|
|
|
137
|
next unless (defined $string); |
546
|
53
|
50
|
|
|
|
242
|
next if ($string =~ /^\s*$/); |
547
|
53
|
|
|
|
|
479
|
my ($attr, $expr) = $string =~ /^\s*([A-Za-z_:][A-Za-z0-9_:.-]*)\s+(.*?)\s*$/; |
548
|
53
|
50
|
33
|
|
|
240
|
if (not defined $attr or not defined $expr) |
549
|
|
|
|
|
|
|
{ |
550
|
0
|
|
|
|
|
0
|
warn "Attributes expression '$string' does not seem valid - Skipped"; |
551
|
0
|
|
|
|
|
0
|
next; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
53
|
|
|
|
|
153
|
$expr = $class->_encode_backslash_semicolon ($expr); |
555
|
53
|
|
|
|
|
285
|
$att->{$attr} = ""; |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
|
558
|
37
|
|
|
|
|
77
|
return 1; |
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
# _content; |
563
|
|
|
|
|
|
|
# --------- |
564
|
|
|
|
|
|
|
# Rewrites as |
565
|
|
|
|
|
|
|
# All the descendent nodes of 'tag' will be skipped |
566
|
|
|
|
|
|
|
sub _content |
567
|
|
|
|
|
|
|
{ |
568
|
1326
|
|
|
1326
|
|
1818
|
my $class = shift; |
569
|
1326
|
50
|
|
|
|
2401
|
return if ($class->_is_inside_content_or_replace()); |
570
|
|
|
|
|
|
|
|
571
|
1326
|
|
|
|
|
1763
|
my $petal = $Petal::NS; |
572
|
1326
|
|
|
|
|
1738
|
my $tag = shift; |
573
|
1326
|
|
|
|
|
1641
|
my $att = shift; |
574
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:content"} || |
575
|
|
|
|
|
|
|
delete $att->{"$petal:contents"} || |
576
|
1326
|
|
100
|
|
|
11638
|
delete $att->{"$petal:inner"} || return; |
577
|
|
|
|
|
|
|
my @new = map { |
578
|
64
|
|
|
|
|
237
|
$_ = $class->_encode_backslash_semicolon ($_); |
|
64
|
|
|
|
|
192
|
|
579
|
64
|
|
|
|
|
282
|
""; |
580
|
|
|
|
|
|
|
} $class->_split_expression ($expr); |
581
|
64
|
|
|
|
|
173
|
push @Result, @new; |
582
|
64
|
|
|
|
|
237
|
$NodeStack[$#NodeStack]->{content} = 'true'; |
583
|
64
|
|
|
|
|
337
|
return 1; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
# _xinclude ($tag, $att); |
588
|
|
|
|
|
|
|
# ----------------------- |
589
|
|
|
|
|
|
|
# Rewrites into |
590
|
|
|
|
|
|
|
# . |
591
|
|
|
|
|
|
|
sub _xinclude |
592
|
|
|
|
|
|
|
{ |
593
|
47
|
|
|
47
|
|
76
|
my $class = shift; |
594
|
47
|
50
|
|
|
|
91
|
return if ($class->_is_inside_content_or_replace()); |
595
|
|
|
|
|
|
|
|
596
|
47
|
|
|
|
|
80
|
my $tag = shift; |
597
|
47
|
|
|
|
|
67
|
my $att = shift; |
598
|
|
|
|
|
|
|
|
599
|
47
|
50
|
|
|
|
89
|
if ($class->_is_xinclude ($tag)) |
600
|
|
|
|
|
|
|
{ |
601
|
|
|
|
|
|
|
# strip remaining Petal tags |
602
|
47
|
|
|
|
|
93
|
my $petal = quotemeta ($Petal::NS); |
603
|
47
|
50
|
|
|
|
69
|
$att = { map { $_ =~ /^$petal:/ ? () : $_ => $att->{$_} } keys %{$att} }; |
|
47
|
|
|
|
|
388
|
|
|
47
|
|
|
|
|
210
|
|
604
|
|
|
|
|
|
|
|
605
|
47
|
|
|
|
|
119
|
my $expr = delete $att->{'href'}; |
606
|
47
|
|
|
|
|
111
|
$expr = $class->_encode_backslash_semicolon ($expr); |
607
|
47
|
|
|
|
|
184
|
push @Result, ""; |
608
|
|
|
|
|
|
|
} |
609
|
47
|
|
|
|
|
295
|
return 1; |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
# _is_xinclude ($tag); |
614
|
|
|
|
|
|
|
# -------------------- |
615
|
|
|
|
|
|
|
# Returns TRUE if $tag is a Xinclude directive, |
616
|
|
|
|
|
|
|
# FALSE otherwise. |
617
|
|
|
|
|
|
|
sub _is_xinclude |
618
|
|
|
|
|
|
|
{ |
619
|
2860
|
|
|
2860
|
|
3817
|
my $class = shift; |
620
|
2860
|
|
|
|
|
3279
|
my $tag = shift; |
621
|
2860
|
|
|
|
|
3627
|
my $xi = quotemeta ($Petal::XI_NS); |
622
|
2860
|
|
|
|
|
13241
|
return $tag =~ /^$xi:/ |
623
|
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
sub _encode_backslash_semicolon |
627
|
|
|
|
|
|
|
{ |
628
|
354
|
|
|
354
|
|
523
|
my $class = shift; |
629
|
354
|
|
|
|
|
472
|
my $data = shift; |
630
|
354
|
|
|
|
|
2879
|
$data =~ s/($MKDoc::XML::Encode::XML_Encode_Pattern)/&$MKDoc::XML::Encode::XML_Encode{$1}\\;/go; |
631
|
354
|
|
|
|
|
798
|
return $data; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
1; |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
__END__ |