XQuery中的URI相对化

时间:2011-10-03 12:40:42

标签: xpath xquery

如何将URI重新激活到另一个URI?

URI1

file:/folder1/file2.txt

URI2

file:/folder1/folder2/file1.txt

需要的结果

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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