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__ |