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
|
|
257
|
use Petal::Hash::String; |
|
77
|
|
|
|
|
75
|
|
|
77
|
|
|
|
|
1703
|
|
19
|
77
|
|
|
77
|
|
27372
|
use MKDoc::XML::Encode; |
|
77
|
|
|
|
|
12658
|
|
|
77
|
|
|
|
|
1557
|
|
20
|
77
|
|
|
77
|
|
305
|
use strict; |
|
77
|
|
|
|
|
78
|
|
|
77
|
|
|
|
|
1089
|
|
21
|
77
|
|
|
77
|
|
220
|
use warnings; |
|
77
|
|
|
|
|
76
|
|
|
77
|
|
|
|
|
1525
|
|
22
|
|
|
|
|
|
|
|
23
|
77
|
|
|
77
|
|
216
|
use vars qw /@Result @NodeStack/; |
|
77
|
|
|
|
|
80
|
|
|
77
|
|
|
|
|
205338
|
|
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
|
238
|
my $class = shift; |
35
|
206
|
|
|
|
|
299
|
my $parser = shift; |
36
|
206
|
|
|
|
|
251
|
my $data_ref = shift; |
37
|
206
|
50
|
|
|
|
489
|
$data_ref = (ref $data_ref) ? $data_ref : \$data_ref; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# grab anything that's before the first '<' tag |
40
|
206
|
|
|
|
|
1243
|
my ($header) = $$data_ref =~ /(^.*?)<(?!\?|\!)/sm; |
41
|
206
|
|
|
|
|
1727
|
$$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
|
|
|
|
|
544
|
my $pis = $class->_processing_instructions_out ($data_ref); |
50
|
|
|
|
|
|
|
|
51
|
206
|
|
|
|
|
398
|
local @Result = (); |
52
|
206
|
|
|
|
|
258
|
local @NodeStack = (); |
53
|
|
|
|
|
|
|
|
54
|
206
|
|
|
|
|
541
|
$parser->process ($class, $data_ref); |
55
|
|
|
|
|
|
|
|
56
|
202
|
|
100
|
|
|
680
|
$header ||= ''; |
57
|
202
|
|
|
|
|
195
|
my $res = ''; |
58
|
202
|
100
|
|
|
|
524
|
$res .= $header unless ($Petal::CURRENT_INCLUDES > 1); |
59
|
202
|
|
|
|
|
1245
|
$res .= (join '', @Result); |
60
|
|
|
|
|
|
|
|
61
|
202
|
|
|
|
|
623
|
$class->_processing_instructions_in (\$res, $pis); |
62
|
|
|
|
|
|
|
|
63
|
202
|
|
|
|
|
1336
|
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
|
|
235
|
my $class = shift; |
82
|
206
|
|
|
|
|
212
|
my $data_ref = shift; |
83
|
206
|
|
|
|
|
829
|
my %pis = map { $_ => $class->_compute_unique_string ($data_ref) } $$data_ref =~ /(<\?.*?\?>)/gsm; |
|
60
|
|
|
|
|
113
|
|
84
|
|
|
|
|
|
|
|
85
|
206
|
|
|
|
|
774
|
while (my ($key, $value) = each %pis) { |
86
|
49
|
|
|
|
|
1254
|
$$data_ref =~ s/\Q$key\E/$value/gsm; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
206
|
|
|
|
|
323
|
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
|
|
236
|
my $class = shift; |
101
|
202
|
|
|
|
|
200
|
my $data_ref = shift; |
102
|
202
|
|
|
|
|
196
|
my $pis = shift; |
103
|
202
|
|
|
|
|
227
|
while (my ($key, $value) = each %{$pis}) { |
|
251
|
|
|
|
|
787
|
|
104
|
49
|
|
|
|
|
1128
|
$$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
|
|
54
|
my $class = shift; |
115
|
60
|
|
|
|
|
49
|
my $data_ref = shift; |
116
|
60
|
|
|
|
|
81
|
my $string = '[-' . (join '', map { chr (ord ('a') + int rand 26) } 1..20) . '-]'; |
|
1200
|
|
|
|
|
1567
|
|
117
|
60
|
|
|
|
|
327
|
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
|
|
|
|
|
168
|
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
|
2248
|
Petal::load_code_generator(); # we will use it later |
141
|
|
|
|
|
|
|
|
142
|
1306
|
|
|
|
|
1154
|
my $class = shift; |
143
|
1306
|
|
|
|
|
1531
|
push @NodeStack, {}; |
144
|
1306
|
100
|
|
|
|
2362
|
return if ($class->_is_inside_content_or_replace()); |
145
|
|
|
|
|
|
|
|
146
|
1299
|
|
|
|
|
1133
|
my $tag = $_; |
147
|
1299
|
|
|
|
|
4756
|
($tag) = $tag =~ /^<\s*((?:\w|\:|\-)*)/; |
148
|
1299
|
|
|
|
|
3212
|
my $att = { %_ }; |
149
|
|
|
|
|
|
|
|
150
|
1299
|
|
|
|
|
2353
|
$class->_use_macro ($tag, $att); |
151
|
1299
|
|
|
|
|
1910
|
$class->_on_error ($tag, $att); |
152
|
1299
|
|
|
|
|
1880
|
$class->_define ($tag, $att); |
153
|
1299
|
|
|
|
|
2027
|
$class->_define_slot ($tag, $att); |
154
|
1299
|
|
|
|
|
1810
|
$class->_condition ($tag, $att); |
155
|
1299
|
|
|
|
|
1969
|
$class->_repeat ($tag, $att); |
156
|
1299
|
100
|
66
|
|
|
1948
|
$class->_is_xinclude ($tag) and $class->_xinclude ($tag, $att) and return; |
157
|
1253
|
|
|
|
|
2023
|
$class->_replace ($tag, $att); |
158
|
|
|
|
|
|
|
|
159
|
1253
|
|
|
|
|
1109
|
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
|
|
|
|
1682
|
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
|
|
|
|
|
884
|
foreach my $key (keys %{$att}) |
|
1224
|
|
|
|
|
3070
|
|
168
|
|
|
|
|
|
|
{ |
169
|
2008
|
100
|
|
|
|
4565
|
next if ($key =~ /^$petal:/); |
170
|
1922
|
|
|
|
|
2040
|
my $text = $att->{$key}; |
171
|
1922
|
|
|
|
|
1365
|
my $token_re = $Petal::Hash::String::TOKEN_RE; |
172
|
1922
|
|
|
|
|
4232
|
my @vars = $text =~ /$token_re/gsm; |
173
|
1922
|
|
|
|
|
1925
|
my %vars = map { $_ => 1 } @vars; |
|
3
|
|
|
|
|
12
|
|
174
|
1922
|
|
|
|
|
1988
|
@vars = sort { length ($b) <=> length ($a) } keys %vars; |
|
0
|
|
|
|
|
0
|
|
175
|
1922
|
|
|
|
|
2003
|
foreach my $var (@vars) |
176
|
|
|
|
|
|
|
{ |
177
|
3
|
|
|
|
|
8
|
my $command = $var; |
178
|
3
|
|
|
|
|
15
|
$command =~ s/^\$//; |
179
|
3
|
|
|
|
|
8
|
$command =~ s/^\{//; |
180
|
3
|
|
|
|
|
20
|
$command =~ s/\}$//; |
181
|
3
|
|
|
|
|
9
|
$command = $class->_encode_backslash_semicolon ($command); |
182
|
3
|
|
|
|
|
9
|
$command = ""; |
183
|
3
|
|
|
|
|
34
|
$text =~ s/\Q$var\E/$command/g; |
184
|
|
|
|
|
|
|
} |
185
|
1922
|
|
|
|
|
2924
|
$att->{$key} = $text; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# processes the petal:attributes instruction |
189
|
1224
|
|
|
|
|
2397
|
$class->_attributes ($tag, $att); |
190
|
|
|
|
|
|
|
|
191
|
1224
|
|
|
|
|
1278
|
my @att_str = (); |
192
|
1224
|
|
|
|
|
926
|
foreach my $key (keys %{$att}) |
|
1224
|
|
|
|
|
2154
|
|
193
|
|
|
|
|
|
|
{ |
194
|
1987
|
100
|
|
|
|
4311
|
next if ($key =~ /^$petal:/); |
195
|
1930
|
|
|
|
|
2084
|
my $value = $att->{$key}; |
196
|
1930
|
100
|
|
|
|
2289
|
if ($value =~ /^<\?attr/) |
197
|
|
|
|
|
|
|
{ |
198
|
45
|
|
|
|
|
72
|
push @att_str, $value; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
else |
201
|
|
|
|
|
|
|
{ |
202
|
1885
|
|
|
|
|
3245
|
my $tokens = Petal::CodeGenerator->_tokenize (\$value); |
203
|
|
|
|
|
|
|
my @res = map { |
204
|
|
|
|
|
|
|
($_ =~ /$Petal::CodeGenerator::PI_RE/s) ? |
205
|
|
|
|
|
|
|
$_ : |
206
|
1884
|
100
|
|
|
|
3596
|
do { |
207
|
1881
|
|
|
|
|
1769
|
$_ =~ s/\&/&/g; |
208
|
1881
|
|
|
|
|
1497
|
$_ =~ s/\</g; |
209
|
1881
|
|
|
|
|
1410
|
$_ =~ s/\>/>/g; |
210
|
1881
|
|
|
|
|
1397
|
$_ =~ s/\"/"/g; |
211
|
1881
|
|
|
|
|
2823
|
$_; |
212
|
|
|
|
|
|
|
}; |
213
|
1885
|
|
|
|
|
1318
|
} @{$tokens}; |
|
1885
|
|
|
|
|
1819
|
|
214
|
1885
|
|
|
|
|
5470
|
push @att_str, $key . '="' . (join '', @res) . '"'; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
1224
|
|
|
|
|
1841
|
my $att_str = join " ", @att_str; |
219
|
|
|
|
|
|
|
|
220
|
1224
|
100
|
|
|
|
2271
|
if (defined $att->{"$petal:omit-tag"}) |
221
|
|
|
|
|
|
|
{ |
222
|
5
|
|
100
|
|
|
26
|
my $expression = $att->{"$petal:omit-tag"} || 'string:1'; |
223
|
5
|
|
|
|
|
13
|
$NodeStack[$#NodeStack]->{'omit-tag'} = $expression; |
224
|
5
|
100
|
66
|
|
|
40
|
push @Result, (defined $att_str and $att_str) ? |
225
|
|
|
|
|
|
|
"<$tag $att_str>" : |
226
|
|
|
|
|
|
|
"<$tag>"; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
else |
229
|
|
|
|
|
|
|
{ |
230
|
1219
|
100
|
66
|
|
|
5160
|
push @Result, (defined $att_str and $att_str) ? "<$tag $att_str>" : "<$tag>"; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
1224
|
|
|
|
|
2354
|
$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
|
1112
|
my $class = shift; |
254
|
1306
|
100
|
|
|
|
1711
|
return if ($class->_is_inside_content_or_replace ( 'endtag' )); |
255
|
|
|
|
|
|
|
|
256
|
1294
|
|
|
|
|
4780
|
my ($tag) = $_ =~ /^<\/\s*((?:\w|\:|\-)*)/; |
257
|
1294
|
|
|
|
|
1457
|
my $node = pop (@NodeStack); |
258
|
|
|
|
|
|
|
|
259
|
1294
|
100
|
|
|
|
1978
|
return if ($class->_is_xinclude ($tag)); |
260
|
|
|
|
|
|
|
|
261
|
1248
|
100
|
66
|
|
|
2620
|
unless (defined $node->{replace} and $node->{replace}) |
262
|
|
|
|
|
|
|
{ |
263
|
1224
|
100
|
|
|
|
1553
|
if (exists $node->{'omit-tag'}) |
264
|
|
|
|
|
|
|
{ |
265
|
5
|
|
|
|
|
6
|
my $expression = $node->{'omit-tag'}; |
266
|
5
|
|
|
|
|
15
|
push @Result, "$tag>"; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
else |
269
|
|
|
|
|
|
|
{ |
270
|
1219
|
|
|
|
|
2155
|
push @Result, "$tag>"; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
1248
|
|
100
|
|
|
3362
|
my $repeat = $node->{repeat} || '0'; |
275
|
1248
|
|
100
|
|
|
2656
|
my $condition = $node->{condition} || '0'; |
276
|
1248
|
|
100
|
|
|
2680
|
my $define_slot = $node->{define_slot} || '0'; |
277
|
1248
|
|
|
|
|
2472
|
push @Result, map { '' } 1 .. ($repeat+$condition+$define_slot); |
|
58
|
|
|
|
|
98
|
|
278
|
|
|
|
|
|
|
|
279
|
1248
|
100
|
66
|
|
|
2754
|
unless (defined $node->{replace} and $node->{replace}) |
280
|
|
|
|
|
|
|
{ |
281
|
1224
|
100
|
|
|
|
2911
|
if (exists $node->{'on-error'}) |
282
|
|
|
|
|
|
|
{ |
283
|
4
|
|
|
|
|
5
|
my $expression = $node->{'on-error'}; |
284
|
4
|
|
|
|
|
15
|
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
|
1622
|
my $class = shift; |
297
|
2118
|
100
|
|
|
|
2554
|
return if ($class->_is_inside_content_or_replace()); |
298
|
2017
|
|
|
|
|
1696
|
my $text = $_; |
299
|
2017
|
|
|
|
|
1560
|
my $token_re = $Petal::Hash::String::TOKEN_RE; |
300
|
2017
|
|
|
|
|
6748
|
my @vars = $text =~ /$token_re/gsm; |
301
|
2017
|
|
|
|
|
2385
|
my %vars = map { $_ => 1 } @vars; |
|
64
|
|
|
|
|
181
|
|
302
|
2017
|
|
|
|
|
2762
|
@vars = sort { length ($b) <=> length ($a) } keys %vars; |
|
28
|
|
|
|
|
72
|
|
303
|
2017
|
|
|
|
|
2322
|
foreach my $var (@vars) |
304
|
|
|
|
|
|
|
{ |
305
|
64
|
|
|
|
|
77
|
my $command = $var; |
306
|
64
|
|
|
|
|
208
|
$command =~ s/^\$//; |
307
|
64
|
|
|
|
|
95
|
$command =~ s/^\{//; |
308
|
64
|
|
|
|
|
91
|
$command =~ s/\}$//; |
309
|
64
|
|
|
|
|
122
|
$command = $class->_encode_backslash_semicolon ($command); |
310
|
64
|
|
|
|
|
150
|
$command = ""; |
311
|
64
|
|
|
|
|
797
|
$text =~ s/\Q$var\E/$command/g; |
312
|
|
|
|
|
|
|
} |
313
|
2017
|
|
|
|
|
5797
|
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
|
|
12360
|
my $class = shift; |
324
|
18855
|
|
|
|
|
11687
|
my $endtag = shift; |
325
|
18855
|
|
|
|
|
11170
|
my $tmp = undef; |
326
|
18855
|
100
|
|
|
|
21049
|
$tmp = pop (@NodeStack) if ($endtag); |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# WHY do I have to do this? |
329
|
18855
|
100
|
66
|
|
|
22856
|
return 1 if (defined $tmp and $tmp->{'use-macro'}); |
330
|
18846
|
|
|
|
|
28609
|
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
|
|
|
275162
|
defined $NodeStack[$i]->{'use-macro'} ); |
|
|
|
100
|
|
|
|
|
335
|
|
|
|
|
|
|
} |
336
|
18631
|
100
|
|
|
|
20904
|
push @NodeStack, $tmp if (defined $tmp); |
337
|
18631
|
|
|
|
|
26710
|
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
|
|
207
|
my $class = shift; |
350
|
220
|
|
|
|
|
186
|
my $expression = shift; |
351
|
220
|
100
|
66
|
|
|
855
|
my @tokens = map { (defined $_ and $_) ? $_ : () } |
|
296
|
|
|
|
|
1039
|
|
352
|
|
|
|
|
|
|
split /(\s|\r|\n)*(?
|
353
|
|
|
|
|
|
|
$expression; |
354
|
|
|
|
|
|
|
|
355
|
220
|
|
|
|
|
264
|
return map { s/^(\s|\n|\r)+//sm; |
|
270
|
|
|
|
|
564
|
|
356
|
270
|
|
|
|
|
993
|
s/(\s|\n|\r)+$//sm; |
357
|
270
|
100
|
|
|
|
699
|
($_ eq '') ? () : $_ } @tokens; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
# _condition; |
362
|
|
|
|
|
|
|
# ----------- |
363
|
|
|
|
|
|
|
# Rewrites statements into |
364
|
|
|
|
|
|
|
# |
365
|
|
|
|
|
|
|
sub _on_error |
366
|
|
|
|
|
|
|
{ |
367
|
1411
|
|
|
1411
|
|
1073
|
my $class = shift; |
368
|
1411
|
100
|
|
|
|
1603
|
return if ($class->_is_inside_content_or_replace()); |
369
|
|
|
|
|
|
|
|
370
|
1402
|
|
|
|
|
1459
|
my $petal = quotemeta ($Petal::NS); |
371
|
1402
|
|
|
|
|
1200
|
my $tag = shift; |
372
|
1402
|
|
|
|
|
921
|
my $att = shift; |
373
|
1402
|
|
100
|
|
|
2742
|
my $expr = delete $att->{"$petal:on-error"} || return; |
374
|
|
|
|
|
|
|
|
375
|
4
|
|
|
|
|
10
|
$expr = $class->_encode_backslash_semicolon ($expr); |
376
|
4
|
|
|
|
|
7
|
push @Result, ""; |
377
|
4
|
|
|
|
|
9
|
$NodeStack[$#NodeStack]->{'on-error'} = $expr; |
378
|
4
|
|
|
|
|
5
|
return 1; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# _define; |
383
|
|
|
|
|
|
|
# -------- |
384
|
|
|
|
|
|
|
# Rewrites statements into |
385
|
|
|
|
|
|
|
# canonical |
386
|
|
|
|
|
|
|
sub _define |
387
|
|
|
|
|
|
|
{ |
388
|
1411
|
|
|
1411
|
|
1164
|
my $class = shift; |
389
|
1411
|
100
|
|
|
|
1636
|
return if ($class->_is_inside_content_or_replace()); |
390
|
|
|
|
|
|
|
|
391
|
1402
|
|
|
|
|
1152
|
my $petal = $Petal::NS; |
392
|
1402
|
|
|
|
|
1101
|
my $tag = shift; |
393
|
1402
|
|
|
|
|
1029
|
my $att = shift; |
394
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:set"} || |
395
|
|
|
|
|
|
|
delete $att->{"$petal:def"} || |
396
|
1402
|
|
100
|
|
|
7273
|
delete $att->{"$petal:define"} || return; |
397
|
|
|
|
|
|
|
|
398
|
16
|
|
|
|
|
46
|
$expr = $class->_encode_backslash_semicolon ($expr); |
399
|
16
|
|
|
|
|
42
|
push @Result, map { "" } $class->_split_expression ($expr); |
|
23
|
|
|
|
|
61
|
|
400
|
16
|
|
|
|
|
29
|
return 1; |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# _condition; |
405
|
|
|
|
|
|
|
# ----------- |
406
|
|
|
|
|
|
|
# Rewrites statements into |
407
|
|
|
|
|
|
|
# |
408
|
|
|
|
|
|
|
sub _condition |
409
|
|
|
|
|
|
|
{ |
410
|
1411
|
|
|
1411
|
|
1146
|
my $class = shift; |
411
|
1411
|
100
|
|
|
|
1591
|
return if ($class->_is_inside_content_or_replace()); |
412
|
|
|
|
|
|
|
|
413
|
1402
|
|
|
|
|
1127
|
my $petal = $Petal::NS; |
414
|
1402
|
|
|
|
|
1027
|
my $tag = shift; |
415
|
1402
|
|
|
|
|
950
|
my $att = shift; |
416
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:if"} || |
417
|
1402
|
|
100
|
|
|
5040
|
delete $att->{"$petal:condition"} || return; |
418
|
|
|
|
|
|
|
|
419
|
40
|
|
|
|
|
108
|
$expr = $class->_encode_backslash_semicolon ($expr); |
420
|
40
|
|
|
|
|
94
|
my @new = map { "" } $class->_split_expression ($expr); |
|
41
|
|
|
|
|
120
|
|
421
|
40
|
|
|
|
|
74
|
push @Result, @new; |
422
|
40
|
|
|
|
|
98
|
$NodeStack[$#NodeStack]->{condition} = scalar @new; |
423
|
40
|
|
|
|
|
60
|
return 1; |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
# _define_slot; |
428
|
|
|
|
|
|
|
# ----------- |
429
|
|
|
|
|
|
|
# Rewrites statements into |
430
|
|
|
|
|
|
|
# |
431
|
|
|
|
|
|
|
sub _define_slot |
432
|
|
|
|
|
|
|
{ |
433
|
1411
|
|
|
1411
|
|
1062
|
my $class = shift; |
434
|
1411
|
100
|
|
|
|
1674
|
return if ($class->_is_inside_content_or_replace()); |
435
|
|
|
|
|
|
|
|
436
|
1402
|
|
|
|
|
1092
|
my $metal = $Petal::MT_NS; |
437
|
1402
|
|
|
|
|
1103
|
my $tag = shift; |
438
|
1402
|
|
|
|
|
985
|
my $att = shift; |
439
|
1402
|
|
100
|
|
|
2605
|
my $expr = delete $att->{"$metal:define-slot"} || return; |
440
|
|
|
|
|
|
|
|
441
|
4
|
|
|
|
|
13
|
$expr = $class->_encode_backslash_semicolon ($expr); |
442
|
4
|
|
|
|
|
13
|
my @new = map { "" } $class->_split_expression ($expr); |
|
4
|
|
|
|
|
12
|
|
443
|
4
|
|
|
|
|
7
|
push @Result, @new; |
444
|
4
|
|
|
|
|
10
|
$NodeStack[$#NodeStack]->{define_slot} = 2 * scalar @new; |
445
|
4
|
|
|
|
|
6
|
return 1; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
# _repeat; |
450
|
|
|
|
|
|
|
# -------- |
451
|
|
|
|
|
|
|
# Rewrites statements into |
452
|
|
|
|
|
|
|
# |
453
|
|
|
|
|
|
|
sub _repeat |
454
|
|
|
|
|
|
|
{ |
455
|
1411
|
|
|
1411
|
|
1182
|
my $class = shift; |
456
|
1411
|
100
|
|
|
|
1644
|
return if ($class->_is_inside_content_or_replace()); |
457
|
|
|
|
|
|
|
|
458
|
1402
|
|
|
|
|
1154
|
my $petal = $Petal::NS; |
459
|
1402
|
|
|
|
|
1114
|
my $tag = shift; |
460
|
1402
|
|
|
|
|
1007
|
my $att = shift; |
461
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:for"} || |
462
|
|
|
|
|
|
|
delete $att->{"$petal:foreach"} || |
463
|
|
|
|
|
|
|
delete $att->{"$petal:loop"} || |
464
|
1402
|
|
100
|
|
|
9657
|
delete $att->{"$petal:repeat"} || return; |
465
|
|
|
|
|
|
|
|
466
|
30
|
|
|
|
|
85
|
my @exprs = $class->_split_expression ($expr); |
467
|
30
|
|
|
|
|
46
|
my @new = (); |
468
|
30
|
|
|
|
|
48
|
foreach $expr (@exprs) |
469
|
|
|
|
|
|
|
{ |
470
|
30
|
|
|
|
|
73
|
$expr = $class->_encode_backslash_semicolon ($expr); |
471
|
30
|
|
|
|
|
96
|
push @new, "" |
472
|
|
|
|
|
|
|
} |
473
|
30
|
|
|
|
|
47
|
push @Result, @new; |
474
|
30
|
|
|
|
|
67
|
$NodeStack[$#NodeStack]->{repeat} = scalar @new; |
475
|
30
|
|
|
|
|
54
|
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
|
|
1043
|
my $class = shift; |
486
|
1364
|
100
|
|
|
|
1574
|
return if ($class->_is_inside_content_or_replace()); |
487
|
|
|
|
|
|
|
|
488
|
1355
|
|
|
|
|
1156
|
my $petal = $Petal::NS; |
489
|
1355
|
|
|
|
|
1112
|
my $tag = shift; |
490
|
1355
|
|
|
|
|
946
|
my $att = shift; |
491
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:replace"} || |
492
|
1355
|
|
100
|
|
|
4891
|
delete $att->{"$petal:outer"} || return; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
my @new = map { |
495
|
29
|
|
|
|
|
71
|
$_ = $class->_encode_backslash_semicolon ($_); |
|
29
|
|
|
|
|
69
|
|
496
|
29
|
|
|
|
|
92
|
""; |
497
|
|
|
|
|
|
|
} $class->_split_expression ($expr); |
498
|
|
|
|
|
|
|
|
499
|
29
|
|
|
|
|
41
|
push @Result, @new; |
500
|
29
|
|
|
|
|
76
|
$NodeStack[$#NodeStack]->{replace} = 'true'; |
501
|
29
|
|
|
|
|
47
|
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
|
|
1165
|
my $class = shift; |
512
|
1411
|
50
|
|
|
|
1795
|
return if ($class->_is_inside_content_or_replace()); |
513
|
|
|
|
|
|
|
|
514
|
1411
|
|
|
|
|
1186
|
my $metal = $Petal::MT_NS; |
515
|
|
|
|
|
|
|
|
516
|
1411
|
|
|
|
|
1217
|
my $tag = shift; |
517
|
1411
|
|
|
|
|
1013
|
my $att = shift; |
518
|
1411
|
|
100
|
|
|
3014
|
my $expr = delete $att->{"$metal:use-macro"} || return; |
519
|
|
|
|
|
|
|
|
520
|
9
|
|
|
|
|
23
|
push @Result, qq||; |
521
|
9
|
|
|
|
|
19
|
$NodeStack[$#NodeStack]->{'use-macro'} = 'true'; |
522
|
9
|
|
|
|
|
17
|
return 1; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
# _attributes; |
527
|
|
|
|
|
|
|
# ------------ |
528
|
|
|
|
|
|
|
# Rewrites |
529
|
|
|
|
|
|
|
# as |
530
|
|
|
|
|
|
|
sub _attributes |
531
|
|
|
|
|
|
|
{ |
532
|
1326
|
|
|
1326
|
|
1008
|
my $class = shift; |
533
|
1326
|
50
|
|
|
|
1590
|
return if ($class->_is_inside_content_or_replace()); |
534
|
|
|
|
|
|
|
|
535
|
1326
|
|
|
|
|
1195
|
my $petal = $Petal::NS; |
536
|
1326
|
|
|
|
|
1095
|
my $tag = shift; |
537
|
1326
|
|
|
|
|
929
|
my $att = shift; |
538
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:att"} || |
539
|
|
|
|
|
|
|
delete $att->{"$petal:attr"} || |
540
|
|
|
|
|
|
|
delete $att->{"$petal:atts"} || |
541
|
1326
|
|
100
|
|
|
9243
|
delete $att->{"$petal:attributes"} || return; |
542
|
|
|
|
|
|
|
|
543
|
37
|
|
|
|
|
96
|
foreach my $string ($class->_split_expression ($expr)) |
544
|
|
|
|
|
|
|
{ |
545
|
53
|
50
|
|
|
|
97
|
next unless (defined $string); |
546
|
53
|
50
|
|
|
|
147
|
next if ($string =~ /^\s*$/); |
547
|
53
|
|
|
|
|
280
|
my ($attr, $expr) = $string =~ /^\s*([A-Za-z_:][A-Za-z0-9_:.-]*)\s+(.*?)\s*$/; |
548
|
53
|
50
|
33
|
|
|
177
|
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
|
|
|
|
|
94
|
$expr = $class->_encode_backslash_semicolon ($expr); |
555
|
53
|
|
|
|
|
188
|
$att->{$attr} = ""; |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
|
558
|
37
|
|
|
|
|
51
|
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
|
|
1042
|
my $class = shift; |
569
|
1326
|
50
|
|
|
|
1601
|
return if ($class->_is_inside_content_or_replace()); |
570
|
|
|
|
|
|
|
|
571
|
1326
|
|
|
|
|
1096
|
my $petal = $Petal::NS; |
572
|
1326
|
|
|
|
|
1029
|
my $tag = shift; |
573
|
1326
|
|
|
|
|
959
|
my $att = shift; |
574
|
|
|
|
|
|
|
my $expr = delete $att->{"$petal:content"} || |
575
|
|
|
|
|
|
|
delete $att->{"$petal:contents"} || |
576
|
1326
|
|
100
|
|
|
10105
|
delete $att->{"$petal:inner"} || return; |
577
|
|
|
|
|
|
|
my @new = map { |
578
|
64
|
|
|
|
|
148
|
$_ = $class->_encode_backslash_semicolon ($_); |
|
64
|
|
|
|
|
136
|
|
579
|
64
|
|
|
|
|
199
|
""; |
580
|
|
|
|
|
|
|
} $class->_split_expression ($expr); |
581
|
64
|
|
|
|
|
99
|
push @Result, @new; |
582
|
64
|
|
|
|
|
150
|
$NodeStack[$#NodeStack]->{content} = 'true'; |
583
|
64
|
|
|
|
|
253
|
return 1; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
# _xinclude ($tag, $att); |
588
|
|
|
|
|
|
|
# ----------------------- |
589
|
|
|
|
|
|
|
# Rewrites into |
590
|
|
|
|
|
|
|
# . |
591
|
|
|
|
|
|
|
sub _xinclude |
592
|
|
|
|
|
|
|
{ |
593
|
47
|
|
|
47
|
|
48
|
my $class = shift; |
594
|
47
|
50
|
|
|
|
79
|
return if ($class->_is_inside_content_or_replace()); |
595
|
|
|
|
|
|
|
|
596
|
47
|
|
|
|
|
137
|
my $tag = shift; |
597
|
47
|
|
|
|
|
39
|
my $att = shift; |
598
|
|
|
|
|
|
|
|
599
|
47
|
50
|
|
|
|
74
|
if ($class->_is_xinclude ($tag)) |
600
|
|
|
|
|
|
|
{ |
601
|
|
|
|
|
|
|
# strip remaining Petal tags |
602
|
47
|
|
|
|
|
51
|
my $petal = quotemeta ($Petal::NS); |
603
|
47
|
50
|
|
|
|
47
|
$att = { map { $_ =~ /^$petal:/ ? () : $_ => $att->{$_} } keys %{$att} }; |
|
47
|
|
|
|
|
299
|
|
|
47
|
|
|
|
|
117
|
|
604
|
|
|
|
|
|
|
|
605
|
47
|
|
|
|
|
80
|
my $expr = delete $att->{'href'}; |
606
|
47
|
|
|
|
|
89
|
$expr = $class->_encode_backslash_semicolon ($expr); |
607
|
47
|
|
|
|
|
163
|
push @Result, ""; |
608
|
|
|
|
|
|
|
} |
609
|
47
|
|
|
|
|
263
|
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
|
|
2258
|
my $class = shift; |
620
|
2860
|
|
|
|
|
2002
|
my $tag = shift; |
621
|
2860
|
|
|
|
|
2282
|
my $xi = quotemeta ($Petal::XI_NS); |
622
|
2860
|
|
|
|
|
10370
|
return $tag =~ /^$xi:/ |
623
|
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
sub _encode_backslash_semicolon |
627
|
|
|
|
|
|
|
{ |
628
|
354
|
|
|
354
|
|
333
|
my $class = shift; |
629
|
354
|
|
|
|
|
290
|
my $data = shift; |
630
|
354
|
|
|
|
|
2022
|
$data =~ s/($MKDoc::XML::Encode::XML_Encode_Pattern)/&$MKDoc::XML::Encode::XML_Encode{$1}\\;/go; |
631
|
354
|
|
|
|
|
521
|
return $data; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
1; |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
__END__ |