Browse Source

Bug 13262 - Add parameters to XSLT Handler transform method

This patch adds an optional hashref argument to the XSLT_Handler
transform() method. It allows you to send key => value pairs
parameters to the XML::LibXSLT object, which you can reference
in a XSLT via <xsl:param name="XXX" />.

The parameter value is evaluated as an XPath query, so you can only
pass quoted strings (i.e. "'test'") or numbers. Otherwise, the
XSLT engine will interpret it as a Xpath query and will run it
on the XML that you're transforming.

The most common use case is sending strings to a XSLT. In my case,
this is an OAI-PMH identifier that comes in a OAI response but not
the actual metadata. See the following link from the official POD:


1) Run "perl t/db_dependent/XSLT_Handler.t". If all tests pass,
you should be free to sign off. Feel free to inspect the last
test in XSLT_Handler.t and the XSL in test04.xsl to see how it

If you really want to be thorough, you could write your own test
cases using mine as an example.

Alternatively, you could go into C4::XSLT, and try to pass a
value to a parameter in the search results or the detail page,
but that might be a bit over the top.

It's a pretty simple patch.

Signed-off-by: Tomas Cohen Arazi <>
David Cook 8 years ago
committed by Tomas Cohen Arazi
  1. 16
  2. 25
  3. 18


@ -132,8 +132,8 @@ __PACKAGE__->mk_accessors(qw( do_not_return_source print_warns ));
my $output= $xslt_engine->transform( $xml, $xsltfilename );
#$output = $xslt_engine->transform({ xml => $xml, file => $file });
#$output = $xslt_engine->transform({ xml => $xml, code => $code });
#$output = $xslt_engine->transform({ xml => $xml, file => $file, [parameters => $parameters] });
#$output = $xslt_engine->transform({ xml => $xml, code => $code, [parameters => $parameters] });
if( $xslt_engine->err ) {
#decide what to do on failure..
@ -156,10 +156,12 @@ sub transform {
# old style: $xml, $filename
# new style: $hashref
my ( $xml, $filename, $xsltcode );
my $parameters = {};
if( ref $_[0] eq 'HASH' ) {
$xml = $_[0]->{xml};
$xsltcode = $_[0]->{code};
$filename = $_[0]->{file} if !$xsltcode; #xsltcode gets priority
$parameters = $_[0]->{parameters} if ref $_[0]->{parameters} eq 'HASH';
} else {
( $xml, $filename ) = @_;
@ -192,7 +194,15 @@ sub transform {
return $retval;
my $str = eval {
my $result = $stsh->transform($source);
#$parameters is an optional hashref that contains
#key-value pairs to be sent to the XSLT.
#Numbers may be bare but strings must be double quoted
#(e.g. "'string'" or '"string"'). See XML::LibXSLT for
#more details.
#NOTE: Parameters are not cached. They are provided for
#each different transform.
my $result = $stsh->transform($source, %$parameters);
if ($@) {


@ -21,7 +21,7 @@ use Modern::Perl;
use FindBin;
use File::Slurp;
use Test::More tests => 37;
use Test::More tests => 40;
use Test::Warn;
use Koha::XSLT_Handler;
@ -156,4 +156,27 @@ $output= $engine->transform( $xml_2, $xsltfile_3 );
is( $engine->err, undef, 'Unexpected error on transform with third xsl' );
is( $engine->refresh, 3, 'Final test on clearing cache' );
my $xsltfile_4 = 'test04.xsl';
is( -e $path.$xsltfile_4, 1, "Found my test stylesheet $xsltfile_4" );
exit if !-e $path.$xsltfile_4;
$xsltfile_4 = $path.$xsltfile_4;
my $parameters = { injected_variable => "'this is a test'",};
$output = $engine->transform({
xml => $xml_1,
file => $xsltfile_4,
parameters => $parameters,
require XML::LibXML;
my $dom = XML::LibXML->load_xml(string => $output);
my $result = $dom->find( '/just_a_tagname' );
is ( $result->to_literal(), 'this is a test', "Successfully injected string into XSLT parameter/variable");
$output = $engine->transform({
xml => $xml_1,
file => $xsltfile_4,
my $dom = XML::LibXML->load_xml(string => $output);
my $result = $dom->find( '/just_a_tagname' );
is ( $result->to_literal(), '', "As expected, no XSLT parameters/variables were added");
#End of tests


@ -0,0 +1,18 @@
<xsl:stylesheet version="1.0"
<xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
<xsl:param name="injected_variable" />
<xsl:template match="/">
<xsl:template match="node()">
<xsl:value-of select="$injected_variable"/>