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 |