2011-10-03 81 views
0

如何將URI相對化爲另一個URI?XQuery中的URI相對化

URI1

file:/folder1/file2.txt 

URI2

file:/folder1/folder2/file1.txt 

需要的結果

relativize-method($uri1, $uri2) == '../file2.txt' 

回答

2

像這樣(將重寫它XQuery中):

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:my="my:my"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/*"> 
    <xsl:sequence select="my:RelativeUrl(url[1], url[2])"/> 
</xsl:template> 

<xsl:function name="my:RelativeUrl" as="xs:string"> 
    <xsl:param name="pUrl" as="xs:string"/> 
    <xsl:param name="pBase" as="xs:string"/> 

    <xsl:variable name="vurlSegments" select="tokenize($pUrl, '/')"/> 
    <xsl:variable name="vbaseSegments" select="tokenize($pBase, '/')"/> 

    <xsl:variable name="vCommonPrefixLength" select= 
    "(for $i in 1 to count($vbaseSegments) 
     return 
     if($vbaseSegments[$i] ne $vurlSegments[$i]) 
      then $i -1 
      else() 
    )[1] 
    "/> 

    <xsl:variable name="vUpSteps" select= 
    "count($vbaseSegments) -$vCommonPrefixLength "/> 

    <xsl:sequence select= 
    "string-join 
     (
       (
       (for $i in 1 to $vUpSteps 
        return 
         '..' 
       ), 
       (for $k in 1 to count($vurlSegments) - $vCommonPrefixLength 
        return 
        $vurlSegments[$vCommonPrefixLength + $k] 
       ) 
       ), 

        '/' 
     ) 
    "/> 
</xsl:function> 
</xsl:stylesheet> 

當此XML文檔上施加

<t> 
<url>file:/folder1/file2.txt</url> 
<url>file:/folder1/folder2/file1.txt</url> 
</t> 

想要的,正確的結果產生

../../file2.txt 
2

你可以記號化得到的目錄,然後使用遞歸函數來計算期望的結果。像下面(上try.zorba-xquery.com測試):

declare function local:compute-relative-uri($absolute as xs:string, 
              $current as xs:string) 
{ 
    local:compute-relative-uri-aux(tokenize($absolute, "/"), 
           tokenize($current, "/")) 
}; 

declare function local:compute-relative-uri-aux($absolute as xs:string*, 
               $current as xs:string*) 
{ 
    if (head($absolute) eq head($current)) 
    then 
    local:compute-relative-uri-aux(tail($absolute), tail($current)) 
    else 
    let $steps := (for $dir in 1 to count($current) - 1 return "..", $absolute) 
    return string-join($steps, "/") 
}; 

let $absolute := "file:/folder1/file2.txt" 
let $current := "file:/folder1/folder2/file1.txt" 
return 
    local:compute-relative-uri($absolute, $current)