- 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