Релятивизация URI в XQuery - PullRequest
       17

Релятивизация URI в XQuery

0 голосов
/ 03 октября 2011

Как связать URI с другим URI?

uri1

file:/folder1/file2.txt

uri2

file:/folder1/folder2/file1.txt

необходимый результат

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

Ответы [ 2 ]

2 голосов
/ 03 октября 2011

Примерно так (перепишет в 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 голосов
/ 03 октября 2011

Вы можете использовать токены для получения каталогов, а затем использовать рекурсивную функцию для вычисления желаемого результата.Примерно так (проверено на 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)
...