2022.06

Die Nutzung von XSLT3

Der Abschnitt beschreibt die Nutzung von XSLT3 zur Transformation von Layouts und Daten sowie die zusätzlichen MyCoRe-XSLT3-Funktionen.

Standardverhalten

Mit LTS 2022.06 ist Saxon und damit XSLT3 der Standardtransormer Prozess für alle Transformationen. Die Rückkehr zu XSLT1 ist über das folgende Property möglich.

1
  MCR.LayoutService.TransformerFactoryClass=org.apache.xalan.processor.TransformerFactoryImpl

Einbindung von Saxon in die MyCoRe-Transformation

In MyCoRe ist es möglich, einzelne gekapselte Transformationsprozesse, z. B. für Datenexporte, generieren von PDF-Dateien u. ä. bereits auf XSLT3 umzustellen, ohne dies schon für die Gesamtanwendung tun zu müssen. Saxon ist dabei das Mittel der Wahl. Um einen einzelnen Transformationsprozess umzustellen, sind folgende Konfigurations-Properties notwendig:

1
2
3
  MCR.ContentTransformer.{my_process}.Class=org.mycore.common.content.transformer.MCRXSLTransformer
  MCR.ContentTransformer.{my_process}.Stylesheet=xsl/{my_stylesheet}.xsl
  MCR.ContentTransformer.{my_process}.TransformerFactoryClass=net.sf.saxon.TransformerFactoryImpl

Wird die TransformerFactoryClass nicht gesetzt, ist Xalan der Fallback.

Unabhängig davon kann durch Konfiguration auch die gesamte Anwendung auf XSLT3 (Saxon) umgestellt werden, wenn dies alle verwendeten Transformations-Stylesheets unterstützen:

1
   MCR.LayoutService.TransformerFactoryClass=net.sf.saxon.TransformerFactoryImpl

Developer-Modus

Durch Setzen einiger Properties im Entwicklungssystem lässt sich die Arbeit mit XSLT-Stylesheets vereinfachen. So können Stylesheets zur Laufzeit überschrieben werden, ohne die Anwendung neu bauen zu müssen.

Die Details sind auf der Seite Developer-Tools beschrieben.

Migrationshinweise XSLT1 nach XSLT3

Grundsätzlich stehen bei XSLT3 keine XALAN-Extensions mehr zur Verfügung. Diese müssen bei der Migration ersetzt werden. Weiterhin sind die folgenden Code-Stellen zu überarbeiten. Diese Anleitung soll Hinweise zur Umstellung geben.

Ersetzung i18n:translate

XSLT1-Code

1
  <xsl:value-of xmlns:i18n="xalan://org.mycore.services.i18n.MCRTranslation" select="i18n:translate({i18n_property_string})" />

XSLT3-Code

1
2
3
  <xsl:value-of xmlns:mcri18n="http://www.mycore.de/xslt/i18n" select="mcri18n:translate({i18n_property_string})" />
  oder
  <xsl:value-of select="document(concat('i18n:',{i18n_property_string}))/i18n/text()" />

Ersetzung exsl:node-set

XSLT1-Code

1
  <xsl:for-each xmlns:exsl="http://exslt.org/common" select="exsl:node-set($list)/node()">

XSLT3-Code

1
  <xsl:for-each select="$list">

Ersetzung xalan:nodeset

XSLT1-Code

1
2
3
  <xsl:for-each select="xalan:nodeset($result)/content">
  ...
  </xsl:for-each>

XSLT3-Code

1
2
3
  <xsl:for-each select="$result/content">
  ...
  </xsl:for-each>

Ersetzung encoder:encode

XSLT1-Code

1
  <xsl:variable name="url" xmlns:encoder="xalan://java.net.URLEncoder" select="encoder:encode(string($RequestURL))" />

XSLT3-Code

1
  <xsl:vaiable name="url" xmlns:fn="http://www.w3.org/2005/xpath-functions" select="fn:encode-for-uri($RequestURL)" />

Ersetzung decoder:decode

XSLT1-Code

1
  <xsl:variable name="url" xmlns:decoder="xalan://java.net.URLDecoder" select="decoder:decode(string($paramValue),'UTF-8')" />

XSLT3-Code

1
  <xsl:vaiable name="url" select="$paramValue" disable-output-escaping="yes" />

Ersetzung str:tokenizer

XSLT1-Code

1
2
3
  <xsl:for-each xmlns:str="http://exslt.org/strings" select="str:tokenize($MCR.Mail.Recipients,',')">
  ...
  </xsl:for-each>

XSLT3-Code

1
2
3
  <xsl:for-each xmlns:fn="http://www.w3.org/2005/xpath-functions" select="fn:tokenize($MCR.Mail.Recipients,',')">
  ...
  </xsl:for-each>

MyCoRe XSLT3 Funktionen

MyCoRe stellt für bestimmte Aufgaben (Mehrsprachigkeit, Verarbeitung von Klassifikationen, ...) eigene XSLT3-Funktionen als Alternative zu den URI-Resolvern bereit. Diese Funktionen werden im Folgenden beschrieben. Jedes der angegebenen Stylesheets muss dabei inkludiert werden. Weiterhin muss der jeweilige Namespace definiert werden.

I18N Integration

MyCoRe-Komponente: mycore-base
Stylesheet: xslt/functions/i18n.xsl
Namespace: xmlns:mcri18n="http://www.mycore.de/xslt/i18n"

Für die Integration von I18N-Properties sind zwei XSLT-Funktionen konzipiert. Die erste Funktion enthält als Argument nur den String des einzelnen Properties. In der zweiten Variante können der Transformation zusätzliche Argumente mitgegeben werden.

mcri18n:translate()

1
2
  <xsl:value-of select="mcri18n:translate({i18n_property_string})" />
  <xsl:value-of select="mcri18n:translate('my_message_string')" />

mcri18n:translate-with-params()

1
2
  <xsl:value-of select="mcri18n:translate-with-params({i18n_property_string}, ({arg_1}, ...))" />
  <xsl:value-of select="mcri18n:translate-with-params('my_message_string_with_args', ('arg_1', 'arg_2'))" />

 

XSLT3-Funktionen für Zugriffsrechte

MyCoRe-Komponente: mycore-base
Stylesheet: xslt/functions/acl.xsl
Namespace: xmlns:mcracl="http://www.mycore.de/xslt/acl"

mcracl:check-permission()

Es wurde eine XSLT Funktion konzipiert, welche die Zugriffsrechte für Objekte und Permissions testet und eine boolschen Wert als Ergebnis zurückgibt. Die Funktion hat zwei Parameter id und permission.
Dabei kann id auch den Wert der leeren Sequenz () annehmen.

1
2
  mcracl:check-permission({id}, {permission})
  mcracl:check-permission((), {permission})

Hier die Beispiele dazu:

1
2
  mcracl:check-permission('mir_mods_00004711', 'delete')
  mcracl:check-permission((), 'create-mods')

 

XSLT3-Funktionen für MyCoRe-Properties

MyCoRe-Komponente: mycore-base
Stylesheet: xslt/functions/property.xsl
Namespace: xmlns:mcrproperty="http://www.mycore.de/xslt/property"

mcrproperty:one()

Diese Funktion gibt den Wert eines einzelnen Properties als String zurück.
Im Parameter key wird der Schlüssel des Properties übergeben.

1
  mcrproperty:one({key})

zum Beispiel:

1
2
3
4
  <h3><xsl:value-of select="mcrproperty:one('MCR.NameOfProject')" /></h3>
  
  <!-- Ausgabe: -->
  <h3>MIR</h3>

mcrproperty:all()

Diese Funktion gibt eine Liste von Properties zurück.
Im Parameter keyPrefix wird das Prefix für die Schlüssel der benötigten Properties übergeben.

1
  mcrproperty:all({keyPrefix})

zum Beispiel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  <xsl:variable name="props" select="mcrproperty:all('MCR.Solr.Core.')" />
  <xsl:copy-of select="$props" />
  
  <!-- Ausgabe: -->
  <properties>
    <entry key="MCR.Solr.Core.main.Name">mir_main</entry>
    <entry key="MCR.Solr.Core.classification.Name">mir_class</entry>
    <entry key="MCR.Solr.Core.main.ServerURL">http://localhost:8983/</entry>
    <entry key="MCR.Solr.Core.classification.ServerURL">http://localhost:8983/</entry>
  </properties>
1
2
3
4
5
6
7
8
9
  <xsl:for-each select="mcrproperty:all('MCR.Solr.Core.')/entry">
    <span><xsl:value-of select="@key" /> = <xsl:value-of select="." /></span>
  </xsl:for-each>
  
  <!-- Ausgabe: -->
  <span>MCR.Solr.Core.main.Name = mir_main</span>
  <span>MCR.Solr.Core.classification.Name = mir_class</span>
  <span>MCR.Solr.Core.main.ServerURL = http://localhost:8983/</span>
  <span>MCR.Solr.Core.classification.ServerURL = http://localhost:8983/</span>

mcrproperty:map()

Diese Funktion gibt eine XSL-Map von Properties zurück.
Im Parameter keyPrefix wird das Prefix für die Schlüssel der benötigten Properties übergeben.

1
  mcrproperty:map({keyPrefix})

zum Beispiel:

1
2
3
4
5
  <xsl:variable name="propMap" select="mcrproperty:map('MCR.Solr.Core.')" />
  <span><xsl:value-of select="map:get($propMap, 'MCR.Solr.Core.main.Name')" /></span>
  
  <!-- Ausgabe: -->
  <span>mir_main</span>

 

XSLT3-Funktionen für MODS

MyCoRe-Komponente: mycore-mods
Stylesheet: xslt/functions/mods.xsl
Namespace: xmlns:mcrmods="http://www.mycore.de/xslt/mods"

mcrmods:to-mycoreclass()

liefert Klassifikationsdaten im MyCoRe-XML-Format zurück für ein Element (1. Parameter) und einen mode (2. Parameter). Der erste Parameter ist ein MODS-Element, das ggf. eine Klassifikationsangabe enthält (siehe mcrmods:is-supported()). Der mode-Parameter kann entweder parent oder single sein. Bei parent werden alle Elternkategorien mit ausgeliefert (die gesuchte Kategorie ist also die, die keine Kinder mehr enthält). Bei single wird nur die gewünschte Kategorie mit allen Labels zurückgeliefert - eingebettet in das bekannte mycoreclass-XML-Element.

Hier ein Beispiel dazu:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  <xsl:variable name="diniclass">
    <mods:classification displayLabel="dini"
                         authorityURI="http://mycore.de/mir/classifications/diniPublType" 
                         valueURI="http://mycore.de/mir/classifications/diniPublType#StillImage" />
  </xsl:variable>
  
  <xsl:copy-of select="mcrmods:to-mycoreclass($diniclass/*, 'single')" />
  <!-- Ausgabe: -->
  <mycoreclass ID="diniPublType">
    <label xml:lang="en" text="DINI publication- and document types" description="general vocabulary..." />
    <label xml:lang="de" text="DINI Publikations- und Dokumenttypen" description="Gemeinsames Vokabular..." />
    <categories>
      <category ID="StillImage">
        <label xml:lang="en" text="still image" />
        <label xml:lang="de" text="Einzelbild" description="Eine statische visuelle Darstellung.." />
      </category>
    </categories>
  </mycoreclass>  
  
  <xsl:copy-of select="mcrmods:to-mycoreclass($diniclass/*, 'parent')" />
  <!-- Ausgabe: -->
  <mycoreclass ID="diniPublType">
    <label xml:lang="en" text="DINI publication- and document types" description="general vocabulary..." />
    <label xml:lang="de" text="DINI Publikations- und Dokumenttypen" description="Gemeinsames Vokabular..." />
    <categories>
      <category ID="Image">
        <label xml:lang="de" text="Bild" description="Eine nicht textgebundene visuelle Darstellung..."/>
        <label xml:lang="en" text="image" description="A visual representation other than text." />
        <category ID="StillImage">
          <label xml:lang="en" text="still image" />
          <label xml:lang="de" text="Einzelbild" description="Eine statische visuelle Darstellung..." />
        </category>
      </category>
    </categories>
  </mycoreclass>

mcrmods:to-category()

liefert für ein gegebenes Element ein MyCoRe-Category-XML-Element zurück. Der Parameter ist ein MODS-Element, das ggf. eine Klassifikationsangabe enthält (s.o.). Es wird das <category> XML-Element mit allen Labels zurückgeliefert.

Hier ein Beispiel dazu:

1
2
3
4
5
6
  <xsl:copy-of select="mcrmods:to-category($diniclass/*)" />
  <!-- Ausgabe: -->
  <category ID="StillImage">
    <label xml:lang="en" text="still image" />
    <label xml:lang="de" text="Einzelbild" description="Eine statische visuelle Darstellung..." />
  </category>

mcrmods:mcrmods:to-uri() internal

liefert für ein Element eine modsclass:-URI zurück für den MCRModsClassificationURIResolver, wenn das Element eine Klassifikationsangabe enthält (z.B. über @authorityURI und @valueURI). Diese Funktion wird hauptsächlich intern verwendet.

Hier ein Beispiel dazu

1
2
3
4
5
6
7
8
9
  <xsl:variable name="modsclass">
    <mods:classification authorityURI="http://mycore.de/mir/classifications/accesscondition" 
                         valueURI="http://mycore.de/mir/classifications/accesscondition#openaccess" 
                         displayLabel="accesscondition">frei zugänglich (Open Access)</mods:classification>
  </xsl:variable>
  <xsl:value-of select="mcrmods:to-uri($modsclass/*)" />
  
  <!-- Ausgabe: -->
  modsclass:/uri/http%3A%2F%2Frosdok.uni-rostock.de%2Fclassifications%2Faccesscondition/http%3A%2F%2Frosdok.uni-rostock.de%2Fclassifications%2Faccesscondition%23openaccess

mcrmods:is-supported() internal

gibt true für ein MODS-Element (s.o.) zurück, wenn es prinzipiell geeignet ist eine Klassifikationsangabe zu enthalten. Das ist eine hauptsächlich intern benutzte Hilfsfunktion.

Hier die Beispiele dazu:

1
2
  mcrmods:is-supported(mods:classification)  —> IMMER true
  mcrmods:is-supported(/mycoreobject)  —> IMMER false

 

XSLT3-Funktionen für Klassifikationen

MyCoRe-Komponente: mycore-base
Stylesheet: xslt/functions/classification.xsl
Namespace: xmlns:mcrclass="http://www.mycore.de/xslt/classification"

mcrclass:current-label()

gibt für ein MyCoRe-Klassifikations-Element oder ein MyCoRe-Category-Element das Label-Element in der aktuellen Sprache zurück. Als Fallback wird zuerst versucht, das Label der Default-Sprache und anschließend das erste Label der Klassifikation zurückzuliefern.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  <xsl:variable name="categ">
    <category ID="published">
       <label xml:lang="en" text="published" />
       <label xml:lang="de" text="veröffentlicht" />
    </category>
  </xsl:variable>
  <xsl:value-of select="mcrclass:current-label($categ/*)" />
  
  <!-- Rückgabe (in deutsch-sprachiger Anwendung): -->
  <label xml:lang="de" text="veröffentlicht" /> 

mcrclass:current-label-text()

verhält sich wie die vorhergehende Funktion, gibt jedoch direkt den Wert des Labels für die Anzeige zurück.

1
2
3
4
  <xsl:value-of select="mcrclass:current-label-text($categ/*)" />
  
  <!-- Rückgabe (in deutsch-sprachiger Anwendung): -->
  veröffentlicht 
Diese Funktionen lassen sich auch mit den Funktionen für MODS kombinieren, z.B.:

1
2
3
4
  Label: <xsl:value-of select="mcrclass:current-label-text(mcrmods:to-category($diniclass/*))" />
  
  <!-- Rückgabe (in deutsch-sprachiger Anwendung): -->
  Label: Einzelbild