| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package XML::Saxon::XSLT2; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
20396
|
use 5.008; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
31
|
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
24
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
76
|
|
|
7
|
1
|
|
|
1
|
|
875
|
use IO::Handle; |
|
|
1
|
|
|
|
|
7268
|
|
|
|
1
|
|
|
|
|
45
|
|
|
8
|
1
|
|
|
1
|
|
7
|
use Scalar::Util qw[blessed]; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
85
|
|
|
9
|
1
|
|
|
1
|
|
1573
|
use XML::LibXML; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.007'; |
|
12
|
|
|
|
|
|
|
my $classpath; |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
BEGIN |
|
15
|
|
|
|
|
|
|
{ |
|
16
|
|
|
|
|
|
|
foreach my $path (qw( |
|
17
|
|
|
|
|
|
|
/usr/share/java/saxon9he.jar |
|
18
|
|
|
|
|
|
|
/usr/local/share/java/saxon9he.jar |
|
19
|
|
|
|
|
|
|
/usr/share/java/saxonb.jar |
|
20
|
|
|
|
|
|
|
/usr/local/share/java/saxonb.jar)) |
|
21
|
|
|
|
|
|
|
{ |
|
22
|
|
|
|
|
|
|
$classpath = $path if -e $path; |
|
23
|
|
|
|
|
|
|
last if defined $classpath; |
|
24
|
|
|
|
|
|
|
} |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
require Inline; |
|
27
|
|
|
|
|
|
|
} |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub import |
|
30
|
|
|
|
|
|
|
{ |
|
31
|
|
|
|
|
|
|
my ($class, @args) = @_; |
|
32
|
|
|
|
|
|
|
shift @args |
|
33
|
|
|
|
|
|
|
if @args && exists $args[0] && defined $args[0] && $args[0] =~ /^[\d\.\_]{1,10}$/; |
|
34
|
|
|
|
|
|
|
Inline->import(Java => 'DATA', CLASSPATH=>$classpath, @args); |
|
35
|
|
|
|
|
|
|
} |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub new |
|
38
|
|
|
|
|
|
|
{ |
|
39
|
|
|
|
|
|
|
my ($class, $xslt, $baseurl) = @_; |
|
40
|
|
|
|
|
|
|
$xslt = $class->_xml($xslt); |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
if ($baseurl) |
|
43
|
|
|
|
|
|
|
{ |
|
44
|
|
|
|
|
|
|
return bless { 'transformer' => XML::Saxon::XSLT2::Transformer->new($xslt, $baseurl) }, $class; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
else |
|
47
|
|
|
|
|
|
|
{ |
|
48
|
|
|
|
|
|
|
return bless { 'transformer' => XML::Saxon::XSLT2::Transformer->new($xslt) }, $class; |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub parameters |
|
53
|
|
|
|
|
|
|
{ |
|
54
|
|
|
|
|
|
|
my ($self, %params) = @_; |
|
55
|
|
|
|
|
|
|
$self->{'transformer'}->paramClear(); |
|
56
|
|
|
|
|
|
|
while (my ($k,$v) = each %params) |
|
57
|
|
|
|
|
|
|
{ |
|
58
|
|
|
|
|
|
|
if (ref $v eq 'ARRAY') |
|
59
|
|
|
|
|
|
|
{ |
|
60
|
|
|
|
|
|
|
(my $type, $v) = @$v; |
|
61
|
|
|
|
|
|
|
my $func = 'paramAdd' . { |
|
62
|
|
|
|
|
|
|
double => 'Double', |
|
63
|
|
|
|
|
|
|
string => 'String', |
|
64
|
|
|
|
|
|
|
long => 'Long', |
|
65
|
|
|
|
|
|
|
'int' => 'Long', |
|
66
|
|
|
|
|
|
|
integer => 'Long', |
|
67
|
|
|
|
|
|
|
decimal => 'Decimal', |
|
68
|
|
|
|
|
|
|
float => 'Float', |
|
69
|
|
|
|
|
|
|
boolean => 'Boolean', |
|
70
|
|
|
|
|
|
|
bool => 'Boolean', |
|
71
|
|
|
|
|
|
|
qname => 'QName', |
|
72
|
|
|
|
|
|
|
uri => 'URI', |
|
73
|
|
|
|
|
|
|
date => 'Date', |
|
74
|
|
|
|
|
|
|
datetime => 'DateTime', |
|
75
|
|
|
|
|
|
|
}->{lc $type}; |
|
76
|
|
|
|
|
|
|
croak "$type is not a supported type" |
|
77
|
|
|
|
|
|
|
if $func eq 'paramAdd'; |
|
78
|
|
|
|
|
|
|
$self->{'transformer'}->$func($k, $v); |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
elsif (blessed($v) && $v->isa('DateTime')) |
|
81
|
|
|
|
|
|
|
{ |
|
82
|
|
|
|
|
|
|
$self->{'transformer'}->paramAddDateTime($k, "$v"); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
elsif (blessed($v) && $v->isa('Math::BigInt')) |
|
85
|
|
|
|
|
|
|
{ |
|
86
|
|
|
|
|
|
|
$self->{'transformer'}->paramAddLong($k, $v->bstr); |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
elsif (blessed($v) && $v->isa('URI')) |
|
89
|
|
|
|
|
|
|
{ |
|
90
|
|
|
|
|
|
|
$self->{'transformer'}->paramAddURI($k, "$v"); |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
else |
|
93
|
|
|
|
|
|
|
{ |
|
94
|
|
|
|
|
|
|
$self->{'transformer'}->paramAddString($k, "$v"); |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
return $self; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub transform |
|
101
|
|
|
|
|
|
|
{ |
|
102
|
|
|
|
|
|
|
my ($self, $doc, $type) = @_; |
|
103
|
|
|
|
|
|
|
$type = ($type =~ /^(text|html|xhtml|xml)$/i) ? (lc $type) : 'default'; |
|
104
|
|
|
|
|
|
|
$doc = $self->_xml($doc); |
|
105
|
|
|
|
|
|
|
return $self->{'transformer'}->transform($doc, $type); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub transform_document |
|
109
|
|
|
|
|
|
|
{ |
|
110
|
|
|
|
|
|
|
my $self = shift; |
|
111
|
|
|
|
|
|
|
my $r = $self->transform(@_); |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
$self->{'parser'} ||= XML::LibXML->new; |
|
114
|
|
|
|
|
|
|
return $self->{'parser'}->parse_string($r); |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub messages |
|
118
|
|
|
|
|
|
|
{ |
|
119
|
|
|
|
|
|
|
my ($self) = @_; |
|
120
|
|
|
|
|
|
|
return @{ $self->{'transformer'}->messages }; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub media_type |
|
124
|
|
|
|
|
|
|
{ |
|
125
|
|
|
|
|
|
|
my ($self, $default) = @_; |
|
126
|
|
|
|
|
|
|
return $self->{'transformer'}->media_type || $default; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub doctype_public |
|
130
|
|
|
|
|
|
|
{ |
|
131
|
|
|
|
|
|
|
my ($self, $default) = @_; |
|
132
|
|
|
|
|
|
|
return $self->{'transformer'}->doctype_public || $default; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub doctype_system |
|
136
|
|
|
|
|
|
|
{ |
|
137
|
|
|
|
|
|
|
my ($self, $default) = @_; |
|
138
|
|
|
|
|
|
|
return $self->{'transformer'}->doctype_system || $default; |
|
139
|
|
|
|
|
|
|
} |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub version |
|
142
|
|
|
|
|
|
|
{ |
|
143
|
|
|
|
|
|
|
my ($self, $default) = @_; |
|
144
|
|
|
|
|
|
|
return $self->{'transformer'}->version || $default; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub encoding |
|
148
|
|
|
|
|
|
|
{ |
|
149
|
|
|
|
|
|
|
my ($self, $default) = @_; |
|
150
|
|
|
|
|
|
|
return $self->{'transformer'}->encoding || $default; |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub _xml |
|
154
|
|
|
|
|
|
|
{ |
|
155
|
|
|
|
|
|
|
my ($proto, $xml) = @_; |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
if (blessed($xml) && $xml->isa('XML::LibXML::Document')) |
|
158
|
|
|
|
|
|
|
{ |
|
159
|
|
|
|
|
|
|
return $xml->toString; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
elsif (blessed($xml) && $xml->isa('IO::Handle')) |
|
162
|
|
|
|
|
|
|
{ |
|
163
|
|
|
|
|
|
|
local $/; |
|
164
|
|
|
|
|
|
|
my $str = <$xml>; |
|
165
|
|
|
|
|
|
|
return $str; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
elsif (ref $xml eq 'GLOB') |
|
168
|
|
|
|
|
|
|
{ |
|
169
|
|
|
|
|
|
|
local $/; |
|
170
|
|
|
|
|
|
|
my $str = <$xml>; |
|
171
|
|
|
|
|
|
|
return $str; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
return $xml; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
1; |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 NAME |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
XML::Saxon::XSLT2 - process XSLT 2.0 using Saxon 9.x. |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
use XML::Saxon::XSLT2; |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# make sure to open filehandle in right encoding |
|
188
|
|
|
|
|
|
|
open(my $input, '<:encoding(UTF-8)', 'path/to/xml') or die $!; |
|
189
|
|
|
|
|
|
|
open(my $xslt, '<:encoding(UTF-8)', 'path/to/xslt') or die $!; |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
my $trans = XML::Saxon::XSLT2->new($xslt, $baseurl); |
|
192
|
|
|
|
|
|
|
my $output = $trans->transform($input); |
|
193
|
|
|
|
|
|
|
print $output; |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
my $output2 = $trans->transform_document($input); |
|
196
|
|
|
|
|
|
|
my @paragraphs = $output2->getElementsByTagName('p'); |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
This module implements XSLT 1.0 and 2.0 using Saxon 9.x via L. |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
It expects Saxon to be installed in either '/usr/share/java/saxon9he.jar' |
|
203
|
|
|
|
|
|
|
or '/usr/local/share/java/saxon9he.jar'. Future versions should be more |
|
204
|
|
|
|
|
|
|
flexible. The saxon9he.jar file can be found at L - |
|
205
|
|
|
|
|
|
|
just dowload the latest Java release of Saxon-HE 9.x, open the Zip archive, |
|
206
|
|
|
|
|
|
|
extract saxon9he.jar and save it to one of the two directories above. |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head2 Import |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
use XML::Saxon::XSLT2; |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
You can include additional parameters which will be passed straight on to |
|
213
|
|
|
|
|
|
|
Inline::Java, like this: |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
use XML::Saxon::XSLT2 EXTRA_JAVA_ARGS => '-Xmx256m'; |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
The C function I be called. If you load this module without |
|
218
|
|
|
|
|
|
|
importing it, it will not work. (Don't worry, it won't pollute your namespace.) |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=head2 Constructor |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=over 4 |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=item C<< XML::Saxon::XSLT2->new($xslt, [$baseurl]) >> |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
Creates a new transformation. $xslt may be a string, a file handle or an |
|
227
|
|
|
|
|
|
|
L. $baseurl is an optional base URL for resolving |
|
228
|
|
|
|
|
|
|
relative URL references in, for instance, Exsl:importE links. |
|
229
|
|
|
|
|
|
|
Otherwise, the current directory is assumed to be the base. (For base URIs |
|
230
|
|
|
|
|
|
|
which are filesystem directories, remember to include the trailing slash.) |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=back |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head2 Methods |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=over 4 |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item C<< $trans->parameters($key=>$value, $key2=>$value2, ...) >> |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Sets transformation parameters prior to running the transformation. |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
Each key is a parameter name. |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Each value is the parameter value. This may be a scalar, in which case |
|
245
|
|
|
|
|
|
|
it's treated as an xs:string; a L object, which is treated as |
|
246
|
|
|
|
|
|
|
an xs:dateTime; a L object, xs:anyURI; a L, xs:long; |
|
247
|
|
|
|
|
|
|
or an arrayref where the first element is the type and the second the |
|
248
|
|
|
|
|
|
|
value. For example: |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
$trans->parameters( |
|
251
|
|
|
|
|
|
|
now => DateTime->now, |
|
252
|
|
|
|
|
|
|
madrid_is_capital_of_spain => [ boolean => 1 ], |
|
253
|
|
|
|
|
|
|
price_of_fish => [ decimal => '1.99' ], |
|
254
|
|
|
|
|
|
|
my_link => URI->new('http://example.com/'), |
|
255
|
|
|
|
|
|
|
your_link => [ uri => 'http://example.net/' ], |
|
256
|
|
|
|
|
|
|
); |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
The following types are supported via the arrayref notation: float, double, |
|
259
|
|
|
|
|
|
|
long (alias int, integer), decimal, bool (alias boolean), string, qname, uri, |
|
260
|
|
|
|
|
|
|
date, datetime. These are case-insensitive. |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=item C<< $trans->transform($doc, [$output_method]) >> |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Run a transformation, returning the output as a string. |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
$doc may be a string, a file handle or an L. |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
$output_method may be 'xml', 'xhtml', 'html' or 'text' to override |
|
269
|
|
|
|
|
|
|
the XSLT output method; or 'default' to use the output method specified |
|
270
|
|
|
|
|
|
|
in the XSLT file. 'default' is the default. In the current release, |
|
271
|
|
|
|
|
|
|
'default' is broken. :-( |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=item C<< $trans->transform_document($doc, [$output_method]) >> |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
As per , but returns the output as an L. |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
This method is slower than C. |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=item C<< $trans->messages >> |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
Returns a list of string representations of messages output by |
|
282
|
|
|
|
|
|
|
Exsl:messageE during the last transformation run. |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item C<< $trans->media_type($default) >> |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Returns the output media type for the transformation. |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
If the transformation doesn't specify an output type, returns the default. |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=item C<< $trans->doctype_public($default) >> |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
Returns the output DOCTYPE public identifier for the transformation. |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
If the transformation doesn't specify a doctype, returns the default. |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item C<< $trans->doctype_system($default) >> |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Returns the output DOCTYPE system identifier for the transformation. |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
If the transformation doesn't specify a doctype, returns the default. |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item C<< $trans->version($default) >> |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
Returns the output XML version for the transformation. |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
If the transformation doesn't specify a version, returns the default. |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=item C<< $trans->encoding($default) >> |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Returns the output encoding for the transformation. |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
If the transformation doesn't specify an encoding, returns the default. |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=back |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=head1 BUGS |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Please report any bugs to L. |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
L is probably more reliable in terms of easy installation on a |
|
323
|
|
|
|
|
|
|
variety of platforms, and it allows you to define your own XSLT extension |
|
324
|
|
|
|
|
|
|
functions. However, the libxslt library that it's based on only supports XSLT |
|
325
|
|
|
|
|
|
|
1.0. |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
This module uses L. |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
L. |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 AUTHOR |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Toby Inkster Etobyink@cpan.orgE. |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
Copyright 2010-2012 Toby Inkster |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify it |
|
340
|
|
|
|
|
|
|
under the same terms as Perl itself. |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=cut |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
__DATA__ |