Lines 26-31
Koha::XSLT_Handler - Facilitate use of XSLT transformations
Link Here
|
26 |
use Koha::XSLT_Handler; |
26 |
use Koha::XSLT_Handler; |
27 |
my $xslt_engine = Koha::XSLT_Handler->new; |
27 |
my $xslt_engine = Koha::XSLT_Handler->new; |
28 |
my $output = $xslt_engine->transform($xml, $xsltfilename); |
28 |
my $output = $xslt_engine->transform($xml, $xsltfilename); |
|
|
29 |
$output = $xslt_engine->transform({ xml => $xml, file => $file }); |
30 |
$output = $xslt_engine->transform({ xml => $xml, code => $code }); |
29 |
my $err= $xslt_engine->err; # error number |
31 |
my $err= $xslt_engine->err; # error number |
30 |
my $errstr= $xslt_engine->errstr; # error message |
32 |
my $errstr= $xslt_engine->errstr; # error message |
31 |
$xslt_engine->refresh($xsltfilename); |
33 |
$xslt_engine->refresh($xsltfilename); |
Lines 129-134
__PACKAGE__->mk_accessors(qw( do_not_return_source print_warns ));
Link Here
|
129 |
=head2 transform |
131 |
=head2 transform |
130 |
|
132 |
|
131 |
my $output= $xslt_engine->transform( $xml, $xsltfilename ); |
133 |
my $output= $xslt_engine->transform( $xml, $xsltfilename ); |
|
|
134 |
#Alternatively: |
135 |
#$output = $xslt_engine->transform({ xml => $xml, file => $file }); |
136 |
#$output = $xslt_engine->transform({ xml => $xml, code => $code }); |
132 |
if( $xslt_engine->err ) { |
137 |
if( $xslt_engine->err ) { |
133 |
#decide what to do on failure.. |
138 |
#decide what to do on failure.. |
134 |
} |
139 |
} |
Lines 136-141
__PACKAGE__->mk_accessors(qw( do_not_return_source print_warns ));
Link Here
|
136 |
|
141 |
|
137 |
Pass a xml string and a fully qualified path of a XSLT file. |
142 |
Pass a xml string and a fully qualified path of a XSLT file. |
138 |
Instead of a filename, you may also pass a URL. |
143 |
Instead of a filename, you may also pass a URL. |
|
|
144 |
You may also pass the contents of a xsl file as a string like $code above. |
139 |
If you do not pass a filename, the last file used is assumed. |
145 |
If you do not pass a filename, the last file used is assumed. |
140 |
Returns the transformed string. |
146 |
Returns the transformed string. |
141 |
Check the error number in err to know if something went wrong. |
147 |
Check the error number in err to know if something went wrong. |
Lines 144-182
__PACKAGE__->mk_accessors(qw( do_not_return_source print_warns ));
Link Here
|
144 |
=cut |
150 |
=cut |
145 |
|
151 |
|
146 |
sub transform { |
152 |
sub transform { |
147 |
my ( $self, $orgxml, $file ) = @_; |
153 |
my $self = shift; |
|
|
154 |
|
155 |
#check parameters |
156 |
# old style: $xml, $filename |
157 |
# new style: $hashref |
158 |
my ( $xml, $filename, $xsltcode ); |
159 |
if( ref $_[0] eq 'HASH' ) { |
160 |
$xml = $_[0]->{xml}; |
161 |
$xsltcode = $_[0]->{code}; |
162 |
$filename = $_[0]->{file} if !$xsltcode; #xsltcode gets priority |
163 |
} else { |
164 |
( $xml, $filename ) = @_; |
165 |
} |
148 |
|
166 |
|
149 |
#Initialized yet? |
167 |
#Initialized yet? |
150 |
if ( !$self->{xslt_hash} ) { |
168 |
if ( !$self->{xslt_hash} ) { |
151 |
$self->_init; |
169 |
$self->_init; |
152 |
} |
170 |
} |
153 |
else { |
171 |
else { |
154 |
$self->_set_error; #clear error |
172 |
$self->_set_error; #clear last error |
155 |
} |
173 |
} |
156 |
my $retval = $self->{do_not_return_source} ? undef : $orgxml; |
174 |
my $retval = $self->{do_not_return_source} ? undef : $xml; |
157 |
|
175 |
|
158 |
#check if no string passed |
176 |
#check if no string passed |
159 |
if ( !defined $orgxml ) { |
177 |
if ( !defined $xml ) { |
160 |
$self->_set_error(7); |
178 |
$self->_set_error(7); |
161 |
return; #always undef |
179 |
return; #always undef |
162 |
} |
180 |
} |
163 |
|
181 |
|
164 |
#If no file passed, use the last file again |
|
|
165 |
if ( !$file ) { |
166 |
if ( !$self->{last_xsltfile} ) { |
167 |
$self->_set_error(1); |
168 |
return $retval; |
169 |
} |
170 |
$file = $self->{last_xsltfile}; |
171 |
} |
172 |
|
173 |
#load stylesheet |
182 |
#load stylesheet |
174 |
my $stsh = $self->{xslt_hash}->{$file} // $self->_load($file); |
183 |
my $key = $self->_load( $filename, $xsltcode ); |
|
|
184 |
my $stsh = $key? $self->{xslt_hash}->{$key}: undef; |
175 |
return $retval if $self->{err}; |
185 |
return $retval if $self->{err}; |
176 |
|
186 |
|
177 |
#parse input and transform |
187 |
#parse input and transform |
178 |
my $parser = XML::LibXML->new(); |
188 |
my $parser = XML::LibXML->new(); |
179 |
my $source = eval { $parser->parse_string($orgxml) }; |
189 |
my $source = eval { $parser->parse_string($xml) }; |
180 |
if ($@) { |
190 |
if ($@) { |
181 |
$self->_set_error( 5, $@ ); |
191 |
$self->_set_error( 5, $@ ); |
182 |
return $retval; |
192 |
return $retval; |
Lines 189-195
sub transform {
Link Here
|
189 |
$self->_set_error( 6, $@ ); |
199 |
$self->_set_error( 6, $@ ); |
190 |
return $retval; |
200 |
return $retval; |
191 |
} |
201 |
} |
192 |
$self->{last_xsltfile} = $file; |
202 |
$self->{last_xsltfile} = $key; |
193 |
return $str; |
203 |
return $str; |
194 |
} |
204 |
} |
195 |
|
205 |
|
Lines 246-261
sub _init {
Link Here
|
246 |
# Internal routine for loading a new stylesheet. |
256 |
# Internal routine for loading a new stylesheet. |
247 |
|
257 |
|
248 |
sub _load { |
258 |
sub _load { |
249 |
my ( $self, $file ) = @_; |
259 |
my ( $self, $filename, $code ) = @_; |
|
|
260 |
my ( $digest, $codelen, $salt, $rv ); |
261 |
$salt = 'AZ'; #just a constant actually |
262 |
|
263 |
#If no file or code passed, use the last file again |
264 |
if ( !$filename && !$code ) { |
265 |
my $last = $self->{last_xsltfile}; |
266 |
if ( !$last || !exists $self->{xslt_hash}->{$last} ) { |
267 |
$self->_set_error(1); |
268 |
return; |
269 |
} |
270 |
return $last; |
271 |
} |
250 |
|
272 |
|
251 |
if ( !$file || ( $file !~ /^https?:\/\// && !-e $file ) ) { |
273 |
#check if it is loaded already |
|
|
274 |
if( $code ) { |
275 |
$codelen = length( $code ); |
276 |
$digest = eval { crypt($code, $salt) }; |
277 |
if( $digest && exists $self->{xslt_hash}->{$digest.$codelen} ) { |
278 |
return $digest.$codelen; |
279 |
} |
280 |
} elsif( $filename && exists $self->{xslt_hash}->{$filename} ) { |
281 |
return $filename; |
282 |
} |
283 |
|
284 |
#Check file existence (skipping URLs) |
285 |
if( $filename && $filename !~ /^https?:\/\// && !-e $filename ) { |
252 |
$self->_set_error(2); |
286 |
$self->_set_error(2); |
253 |
return; |
287 |
return; |
254 |
} |
288 |
} |
255 |
|
289 |
|
256 |
#load sheet |
290 |
#load sheet |
257 |
my $parser = XML::LibXML->new; |
291 |
my $parser = XML::LibXML->new; |
258 |
my $style_doc = eval { $parser->load_xml( location => $file ) }; |
292 |
my $style_doc = eval { |
|
|
293 |
$parser->load_xml( $self->_load_xml_args($filename, $code) ) |
294 |
}; |
259 |
if ($@) { |
295 |
if ($@) { |
260 |
$self->_set_error( 3, $@ ); |
296 |
$self->_set_error( 3, $@ ); |
261 |
return; |
297 |
return; |
Lines 263-275
sub _load {
Link Here
|
263 |
|
299 |
|
264 |
#parse sheet |
300 |
#parse sheet |
265 |
my $xslt = XML::LibXSLT->new; |
301 |
my $xslt = XML::LibXSLT->new; |
266 |
$self->{xslt_hash}->{$file} = eval { $xslt->parse_stylesheet($style_doc) }; |
302 |
$rv = $code? $digest.$codelen: $filename; |
|
|
303 |
$self->{xslt_hash}->{$rv} = eval { $xslt->parse_stylesheet($style_doc) }; |
267 |
if ($@) { |
304 |
if ($@) { |
268 |
$self->_set_error( 4, $@ ); |
305 |
$self->_set_error( 4, $@ ); |
269 |
delete $self->{xslt_hash}->{$file}; |
306 |
delete $self->{xslt_hash}->{$rv}; |
270 |
return; |
307 |
return; |
271 |
} |
308 |
} |
272 |
return $self->{xslt_hash}->{$file}; |
309 |
return $rv; |
|
|
310 |
} |
311 |
|
312 |
sub _load_xml_args { |
313 |
my $self = shift; |
314 |
return $_[1]? { 'string' => $_[1]//'' }: { 'location' => $_[0]//'' }; |
273 |
} |
315 |
} |
274 |
|
316 |
|
275 |
# _set_error |
317 |
# _set_error |
276 |
- |
|
|