ACTION QT4CG-080-01: what does DocBook do to “relatevize” URIs?

Here’s the answer. 

<xsl:function name="f:relative-path" as="xs:string">
  <xsl:param name="base" as="xs:string"/>
  <xsl:param name="path" as="xs:string"/>

  <xsl:choose>
    <xsl:when test="exists(f:uri-scheme($path)) and f:uri-scheme($path) ne 'file'">
      <!-- It starts with a non-file: scheme, just assume it's absolute. -->
      <xsl:sequence select="$path"/>
    </xsl:when>
    <xsl:otherwise>
      <!-- Strip away variant forms of file: (file:/, file://, file:///, ...) -->
      <!-- In particular, file:/C:/path vs. file:///C:/path on Windows -->
      <xsl:variable name="bpath" select="replace($base, '^file:/+', '')"/>
      <xsl:variable name="ppath" select="replace($path, '^file:/+', '')"/>

      <xsl:variable name="base-parts" select="tokenize($bpath, '/')[position() lt last()]"/>
      <xsl:variable name="path-parts" select="tokenize($ppath, '/')"/>

      <!--
          <xsl:message select="'BP:', $base-parts"/>
          <xsl:message select="'PP:', $path-parts"/>
      -->

      <xsl:variable name="common-prefix" as="xs:string*">
        <xsl:iterate select="$base-parts">
          <xsl:param name="pos" select="1"/>
          <xsl:param name="common" select="()"/>
          <xsl:on-completion select="$common"/>
          <xsl:if test="$base-parts[$pos] = $path-parts[$pos]">
            <xsl:next-iteration>
              <xsl:with-param name="pos" select="$pos + 1"/>
              <xsl:with-param name="common" select="($common, $base-parts[$pos])"/>
            </xsl:next-iteration>
          </xsl:if>
        </xsl:iterate>
      </xsl:variable>

      <!--
          <xsl:message select="'CP:', $common-prefix"/>
      -->

      <xsl:variable name="base-tail"
                    select="$base-parts[position() gt count($common-prefix)]"/>
      <xsl:variable name="path-tail"
                    select="$path-parts[position() gt count($common-prefix)]"/>

      <!--
          <xsl:message select="'BT:', $base-tail"/>
          <xsl:message select="'PT:', $path-tail"/>
      -->

      <xsl:variable name="final-parts" as="xs:string*">
        <xsl:for-each select="1 to count($base-tail)">
          <xsl:sequence select="'..'"/>
        </xsl:for-each>
        <xsl:sequence select="$path-tail"/>
      </xsl:variable>

      <xsl:sequence select="string-join($final-parts, '/')"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>  


                                        Be seeing you,
                                          norm

--
Norm Tovey-Walsh
Saxonica

Received on Monday, 17 June 2024 16:00:04 UTC