- From: Norm Tovey-Walsh <norm@saxonica.com>
- Date: Mon, 17 Jun 2024 16:59:55 +0100
- To: "public-xslt-40@w3.org" <public-xslt-40@w3.org>
- Message-ID: <m28qz336h0.fsf@saxonica.com>
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