<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/pool/xslt_ht.xslt" type="application/xml"?>
<xsl:stylesheet
  xmlns:d = "http://herbaer.de/xmlns/20051201/doc"
  xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
  xmlns:xl = "http://www.w3.org/1999/xlink"
  version = "1.0"
  exclude-result-prefixes = "xl"
>
<!--
  Hilfsvorlagen zu Dateipfaden
  2020-12-12 Herbert Schiemann <h.schiemann@herbaer.de>
  Borkener Str. 167, 46284 Dorsten, Germany
  GPL Version 2 oder neuer
-->
<d:info xmlns="http://herbaer.de/xmlns/20051201/doc">
  <title>path.xslt</title>
  <subtitle>Hilfsvorlagen zu Dateipfaden</subtitle>
  <date>2020-12-12</date>
  <author>
    <personname>
      <firstname>Herbert</firstname>
      <surname>Schiemann</surname>
    </personname>
    <email>h.schiemann@herbaer.de</email>
  </author>
</d:info>

<d:section xmlns="http://herbaer.de/xmlns/20051201/doc" role="stylesheet">
  <para>
Im allgemeinen sind relative Dateipfade absoluten Dateipfaden vorzuziehen.
Wenn man eine XML-Datei im Dateisystem verschiebt, die eine xml-stylesheet-Anweisung
mit einem relativen Verweis-Pfad enthält, dann ist die xml-stylesheet-Anweisung
anzupassen. XSLT-Anweisungen zur HTML-Ansicht erzeugen oft Verweise auf CSS- und
Javascript-Dateien. Die Pfade zu den Verweiszielen müssen ebenfalls angepasst werden.
Die Lösung: die XSLT-Datei enthält Dateipfade, die relativ zu der XSLT-Datei sind,
und kombiniert diese Dateipfade mit dem Dateipfad aus der xml-stylesheet-Anweisung
zum Ziel-Dateipfad. Diese Datei enthält die Vorlagen zu dieser Lösung.
  </para>
  <para>
Zum Test dienen die Dateien
<filename class="directory"><replaceable
>KLEIDER</replaceable>/catalog/src/dbdump/</filename><filename>test_path.xml</filename>
und
<filename class="directory"><replaceable
>KLEIDER</replaceable>/catalog/src/dbdump/</filename><filename>test_path.xslt</filename>.
  </para>
</d:section>

<d:para>
Der Verzeichnis-Teil eines Dateipfades bis zum letzten '/'
</d:para>
<xsl:template name="path.dir">
  <!-- der Pfad -->
  <xsl:param name="pth" select="."/>
  <xsl:if test="contains ($pth, '/')">
    <xsl:value-of select="concat(substring-before ($pth, '/'), '/')"/>
    <xsl:call-template name="path.dir">
      <xsl:with-param name="pth" select="substring-after ($pth, '/')"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

<d:para>
Der Dateiname-Teil eines Dateipfades nach dem letzten '/'
</d:para>
<xsl:template name="path.file">
  <!-- der Pfad -->
  <xsl:param name="pth" select="."/>
  <xsl:choose>
    <xsl:when test="contains ($pth, '/')">
      <xsl:call-template name="path.file">
        <xsl:with-param name="pth" select="substring-after ($pth, '/')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$pth"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<d:para>
Verzeichnis-Teil des Dateipfades der xml-stylesheet - Anweisung
</d:para>
<xsl:variable name="path.dir_sspi">
  <xsl:call-template name="path.dir">
    <xsl:with-param
      name = "pth"
      select = "
        substring-before (
        substring-after (
        substring-after (/processing-instruction('xml-stylesheet'), 'href'),
        '&quot;'),
        '&quot;')
      "
    />
  </xsl:call-template>
</xsl:variable>

<d:section xmlns="http://herbaer.de/xmlns/20051201/doc">
  <para>
Verkettet zwei Pfade
<parameter>prf</parameter>
(Wert "<literal><replaceable>PRF</replaceable></literal>")
und <parameter>sfx</parameter>
(Wert "<literal><replaceable>SFX</replaceable></literal>").
  </para>
  <para>
Wenn
<parameter>prf</parameter> leer oder "<literal>.</literal>" ist
oder
<parameter>sfx</parameter> mit "<literal>/</literal>" beginnt,
ist das Ergebnis
"<literal><replaceable>SFX</replaceable></literal>".
  </para>
  <para>
Wenn
<parameter>sfx</parameter> leer ist, ist das Ergebnis
"<literal><replaceable>PRF</replaceable></literal>".
  </para>
  <para>
Wenn
<parameter>prf</parameter> "<literal>/</literal>" oder "<literal>/.</literal>" ist,
ist das Ergebnis "<literal>/<replaceable>SFX</replaceable></literal>".
  </para>
  <para>
Wenn <parameter>prf</parameter> den Wert
"<literal>./<replaceable>PRFREST</replaceable></literal>" hat,
wird diese Vorlage mit den Parametern
"<literal><replaceable>PRFREST</replaceable></literal>" und
"<literal><replaceable>SFX</replaceable></literal>"
aufgerufen.
  </para>
  <para>
Wenn <parameter>sfx</parameter> den Wert
"<literal>./<replaceable>SFXREST</replaceable></literal>" hat,
wird diese Vorlage mit den Parametern
"<literal><replaceable>PRF</replaceable></literal>"
und "<literal><replaceable>SFXREST</replaceable></literal>"
aufgerufen.
  </para>
  <para>
Wenn <parameter>prf</parameter> den Wert
"<literal><replaceable>PRFSTART</replaceable>/</literal>"
oder "<literal><replaceable>PRFSTART</replaceable>/.</literal>" hat,
wird diese Vorlage mit den Parametern
"<literal><replaceable>PRFSTART</replaceable></literal>" und
"<literal><replaceable>SFX</replaceable></literal>"
aufgerufen.
  </para>
  <para>
Wenn <parameter>sfx</parameter> nicht mit "<literal>../</literal>" anfängt,
ist das Ergebnis
"<literal><replaceable>PRF</replaceable>/<replaceable>SFX</replaceable></literal>".
  </para>
  <para>
<parameter>sfx</parameter> hat den Wert
"<literal>../<replaceable>SF</replaceable></literal>",
<parameter>prf</parameter> hat den Wert
"<literal><replaceable>PDIR</replaceable><replaceable>PLOCAL</replaceable></literal>",
wobei "<literal><replaceable>PLOCAL</replaceable></literal>"
nicht leer ist und nicht das Zeichen "<literal>/</literal>" enthält.
  </para>
  <para>
Wenn
"<literal><replaceable>PLOCAL</replaceable></literal>" "<literal>..</literal>" ist,
ist das Ergebnis
"<literal><replaceable>PRF</replaceable>/<replaceable>SFX</replaceable></literal>".
  </para>
  <para>
Andernfalls wird diese Vorlage (<varname>path.cat</varname>)
mit den Parametern
"<literal><replaceable>PDER</replaceable></literal>"
und "<literal><replaceable>SF</replaceable></literal>"
aufgerufen.
  </para>
</d:section>
<xsl:template name="path.cat">
  <!-- der erste Pfad -->
  <xsl:param name="prf" select="$path.dir_sspi"/>
  <!-- der Unter-Pfad -->
  <xsl:param name="sfx" select="."/>
  <xsl:choose>
    <xsl:when test="string-length ($prf) = 0 or $prf = '.' or starts-with ($sfx, '/')">
      <xsl:value-of select="$sfx"/>
    </xsl:when>
    <xsl:when test="string-length ($sfx) = 0">
      <xsl:value-of select="$prf"/>
    </xsl:when>
    <xsl:when test="$prf = '/' or $prf = '/.'">
      <xsl:value-of select="concat ('/', $sfx)"/>
    </xsl:when>
    <xsl:when test="starts-with ($prf, './')">
      <xsl:call-template name="path.cat">
        <xsl:with-param name="prf" select="substring ($prf, 3)"/>
        <xsl:with-param name="sfx" select="$sfx"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="starts-with ($sfx, './')">
      <xsl:call-template name="path.cat">
        <xsl:with-param name="prf" select="$prf"/>
        <xsl:with-param name="sfx" select="substring ($sfx, 3)"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="substring ($prf, string-length ($prf)) = '/'">
      <xsl:call-template name="path.cat">
        <xsl:with-param name="prf" select="substring ($prf, 1, string-length ($prf) - 1)"
        />
        <xsl:with-param name="sfx" select="$sfx"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="string-length($prf) &gt; 1 and substring ($prf, string-length($prf) - 1) = '/.'"
    >
      <xsl:call-template name="path.cat">
        <xsl:with-param name="prf" select="substring ($prf, 1, string-length ($prf) - 2)"
        />
        <xsl:with-param name="sfx" select="$sfx"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="not (starts-with ($sfx, '../'))">
      <xsl:value-of select="concat ($prf, '/', $sfx)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="f">
        <xsl:call-template name="path.file">
          <xsl:with-param name="pth" select="$prf"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:choose>
        <xsl:when test="$f = '..'">
          <xsl:value-of select="concat ($prf, '/', $sfx)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="path.cat">
            <xsl:with-param name="prf">
              <xsl:call-template name="path.dir">
                <xsl:with-param name="pth" select="$prf"/>
              </xsl:call-template>
            </xsl:with-param>
            <xsl:with-param name="sfx" select="substring ($sfx, 4)"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template><!-- path.cat -->

<d:para>
Verkettet den Pfad aus der xml-stylesheet - Anweisung
mit einem relativen Pfad.
</d:para>
<xsl:template name="path.stylepath">
  <!-- der (relative) Pfad -->
  <xsl:param name="pth" select="."/>
  <xsl:call-template name="path.cat">
    <xsl:with-param name="prf" select="$path.dir_sspi"/>
    <xsl:with-param name="sfx" select="$pth"/>
  </xsl:call-template>
</xsl:template><!-- path.stylepath -->

</xsl:stylesheet>
