XSLT Overview

== What does XSLT do? ==
XSLT is used to take marcxml from zebra / elasticsearch and render as html on Opac/Staff search results and detail pages.
This is governed by the following system preferences:
variable 	explanation 	default file
OPACXSLTDetailsDisplay	details page display on OPAC 	MARC21slim2OPACDetail.xsl
OPACXSLTListsDisplay 	lists pages display on OPAC (Virtual Shelves)	MARC21slim2OPACResults.xsl
OPACXSLTResultsDisplay	results page display on OPAC 	MARC21slim2OPACResults.xsl
XSLTDetailsDisplay 	details page display on intranet 	MARC21slim2intranetDetail.xsl
XSLTListsDisplay 	lists pages display on intranet 	MARC21slim2intranetResults.xsl
XSLTResultsDisplay 	results page display on intranet 	MARC21slim2intranetResults.xsl
By default, public and private lists (aka virtual shelves) use the same xslt as the search results, but the sysprefs are separate so that they can be made different.
You can use the command 'xsltproc' to transform a marcxml file into html:
xsltproc \
 koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl \
 test.marcxml > test.html
== A minimal example ==
To understand what is going on inside the Detail.xsl and Results.xsl files, it will help to see simplified examples of the xsl and marcxml files. We'll call the first minimal.xslt.
<!DOCTYPE stylesheet >
<xsl:stylesheet
 version="1.0" 
 xmlns:marc="http://www.loc.gov/MARC21/slim" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:template match="marc:record">
 Hello, World!
 </xsl:template>
</xsl:stylesheet>
The <xsl:stylesheet> tag contains several xml namespaces, which define that xml tags that the xslt transformation will work on. www.loc.gov/MARC21/slim contains the definition for marcxml for MARC21. It defines
the leader, controlfield, datafield and subfield tags that
the stylesheet will be transforming.
All transformations happen inside the <xsl:template match="marc:record"> tag. Free form text inside this tag is displayed literally on the output page.
Here's a minimal marcxml record, which we'll call minimal.marcxml.
<?xml version="1.0" encoding="UTF-8"?>
<record
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
 xmlns="http://www.loc.gov/MARC21/slim">
</record>
It contains no tags inside <record>, this file simply gives the xslt tranformation a marc record to process, as is necessary in <xsl:template match="marc:record">.
Here's what happens when we run xsltproc on minimal.xslt and minimal.marcxml:
$ xsltproc minimal.xslt minimal.marcxml
<?xml version="1.0"?>
 Hello, World!
 
Because there are no marc tags to transform in minimal.marcxml, and because we didn't define any transformations in minimal.xslt, we simply print the text Hello, World!.
== XSLT templates and variables ==
The <xsl:template> tag can also be used to define a transformation that can be called with arguments, much like a function or subroutine would be called in a programming language.
Here we have a template called printControlNumber, which takes controlnumber as an argument (in xslt, this is known as a parameter or param). This template will print the string " controlnumber is ", followed by the value of the param. 
<xsl:template name="printControlNumber">
 <xsl:param name="controlnumber"/>
 controlnumber is <xsl:value-of select="$controlnumber" />
</xsl:template>
Variables are interpolated using <xsl:value-of select="$controlnumber" />.
It is also possible to create a variable outside of a template using <xsl:variable name="foo">...</xsl:variable>. The variables can be also be used via the same '$' syntax: the variable foo is dereferenced as $foo.
== Example of XSLT template use ==
Here's an example xslt file (we'll call it template_example.xslt), which uses the printControlNumber template:
<!DOCTYPE stylesheet >
<xsl:stylesheet version="1.0" xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:template name="printControlNumber">
 <xsl:param name="controlnumber"/>
 controlnumber is <xsl:value-of select="$controlnumber" />
 </xsl:template>
 <xsl:template match="marc:record">
 <xsl:call-template name="printControlNumber">
 <xsl:with-param name="controlnumber" select="'(OCoLC)2776588'" />
 </xsl:call-template>
 </xsl:template>
</xsl:stylesheet>
We use <xsl:call-template name="printControlNumber"> to call printControlNumber, and <xsl:with-param name="controlnumber" select="'(OCoLC)2776588'" /> to pass the literal string (OCoLC)2776588 as the praram named controlnumber.
This is analagous to calling
printControlNumber( { controlnumber => '(OCoLC)2776588' } )
in Perl. Again, because we're not operating on any marcxml tags, we'll use minimal.marcxml
$ xsltproc template_example.xslt minimal.marcxml
<?xml version="1.0"?>
 controlnumber is (OCoLC)2776588
In perl terms, this would look like
#! /usr/bin/perl
sub printControlNumber {
 my $param = shift;
 print( "controlnumber is $param->{controlnumber}\n");
}
printControlNumber( { controlnumber => '(OCoLC)2776588' } );
== Operating on marc tags ==
We'll add a 773$w tag containing (OCoLC)2776588 to our minimal minimal.marcxml file, and call it template_example2.marcxml
<?xml version="1.0" encoding="UTF-8"?>
<record
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
 xmlns="http://www.loc.gov/MARC21/slim">
 <datafield tag="773" ind1=" " ind2=" ">
 <subfield code="w">(OCoLC)2776588</subfield>
 </datafield>
</record>
The XSLT changes a bit, because we need to loop through the datafields; then we can use marc:subfield inside the select:
<!DOCTYPE stylesheet >
<xsl:stylesheet version="1.0" xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:template name="printControlNumber">
 <xsl:param name="controlnumber"/>
 controlnumber is <xsl:value-of select="$controlnumber" />
 </xsl:template>
 <xsl:template match="marc:record">
 <xsl:for-each select="marc:datafield[@tag=773]">
 <xsl:call-template name="printControlNumber">
 <xsl:with-param name="controlnumber" select="marc:subfield[@code='w']"/>
 </xsl:call-template>
 </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
The output looks the same, but now nothing is hardcoded in the xslt.
xsltproc template_example2.xslt template_example2.marcxml
<?xml version="1.0"?>
 controlnumber is (OCoLC)2776588
The Detail.xsl and Results.xsl files are largely built using the features above, in various combinations.
== The MARC21slimUtils.xsl template library ==
The file
./koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21slimUtils.xsl
Contains a few pre-built templates:
Name 	Description
extractControlNumber	is used to extract the control number (record number) from MARC tags 773/80/85 [etc.] subfield $w.
m880Select 	Display Alternate Graphic Representation (MARC 880) for selected latin "base"tags
showRDAtag264 	shows selected information from tag 264
== Passing variables via xsltproc command line options ==
Calling xsltproc --param XXX YYY flag can be used to set variable XXX to value YYY.
Koha's sysprefs get written into the marc record:
<xsl:variable name="UseControlNumber"
 select="marc:sysprefs/marc:syspref[@name='UseControlNumber']"/>
Using xsltproc --param UseControlNumber 1 allows us to bypass the system preference and run this from the command line.
xsltproc \
 --param UseControlNumber 1 \
 koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl \
 test.marcxml > test.html
Here are the variables that are used, and the sysprefs that govern them:
XSLT Variable 	Syspref
AlternateHoldingsField 	AlternateHoldingsField
AlternateHoldingsSeparator	AlternateHoldingsSeparator
AlternateHoldingsSubfields	AlternateHoldingsField
BiblioDefaultView 	BiblioDefaultView
DisplayIconsXSLT 	DisplayIconsXSLT
DisplayOPACiconsXSLT 	DisplayOPACiconsXSLT
IdRef 	IdRef
IntranetBiblioDefaultView 	IntranetBiblioDefaultView
OPACBaseURL 	OPACBaseURL
OPACItemLocation 	OPACItemLocation
OPACResultsLibrary 	OPACResultsLibrary
OPACTrackClicks 	TrackClicks
OPACURLOpenInNewWindow 	OPACURLOpenInNewWindow
OpacSuppression 	OpacSuppression
Show856uAsImage 	Display856uAsImage
Show856uAsImage 	OPACDisplay856uAsImage
TraceSubjectSubdivisions 	TraceSubjectSubdivisions
URLLinkText 	URLLinkText
UseAuthoritiesForTracings 	UseAuthoritiesForTracings
UseControlNumber 	UseControlNumber
hidelostitems 	hidelostitems
singleBranchMode 	singleBranchMode
theme 	opacthemes