2010-06-25 5 views
6

Je voudrais que mon fichier de sortie généré contienne des chemins de fichier pointant vers un chemin relatif à la feuille de style. L'emplacement de la feuille de style peut changer et je ne souhaite pas utiliser de paramètre pour la feuille de style. Ma solution pour cela est d'obtenir l'URI complet stylesheet:Faire des manipulations de chemin de fichier dans XSLT

<xsl:variable name="stylesheetURI" select="document-uri(document(''))" /> 

Maintenant, je ne ai besoin de couper le nom de fichier $stylesheetURI. Cela m'a incité à écrire des clones XSLT 2.0 des fonctions PHP basename et dirname:

<xsl:function name="de:basename"> 
    <xsl:param name="file"></xsl:param> 
    <xsl:sequence select="tokenize($file, '/')[last()]" /> 
</xsl:function> 

<xsl:function name="de:dirname"> 
    <xsl:param name="file"></xsl:param> 
    <xsl:sequence 
     select="string-join(tokenize($file, '/')[position() != last()], '/')" /> 
</xsl:function> 

Maintenant, je peux faire quelque chose comme ça dans mon modèle:

<img src="{concat(de:dirname($stylesheetURI),'/img/myimage,png')}" /> 

Ma question est: Y at-il une meilleure/des moyens plus rapides pour accomplir cela avec natif XSLT 2.0?

+0

J'ai aimé travailler sur cette question (+1). Voir ma réponse pour ce qui semble être 25% plus rapide. :) –

Répondre

7

J'ai testé (pas trop extensive) ces fonctions et ils semblent réaliser 25% plus rapide que le fourni. Bien sûr, les résultats dépendent de la longueur de la chaîne et du nombre de qualificatifs:

<xsl:function name="de:basename" as="xs:string"> 
    <xsl:param name="pfile" as="xs:string"/> 
    <xsl:sequence select= 
    "de:reverseStr(substring-before(de:reverseStr($pfile), '/')) 
    " /> 
    </xsl:function> 

    <xsl:function name="de:dirname" as="xs:string"> 
    <xsl:param name="pfile" as="xs:string"/> 
    <xsl:sequence select= 
    "de:reverseStr(substring-after(de:reverseStr($pfile), '/')) 
    " /> 
    </xsl:function> 

    <xsl:function name="de:reverseStr" as="xs:string"> 
    <xsl:param name="pStr" as="xs:string"/> 

    <xsl:sequence select= 
    "codepoints-to-string(reverse(string-to-codepoints($pStr)))"/> 
    </xsl:function> 
+0

Wow! Serait-ce parce que l'implémentation de la séquence (avec tokenize et string-join) a plus de coûts que la manipulation de chaînes? Mais, string-to-codonits ne renvoie-t-il pas aussi une séquence? –

+0

@Alejandro: tokenize() fait beaucoup de travail - analyser char par char et placer chaque jeton dans un élément séparé. Partout où substring-before() ou substring-after() balaye seulement jusqu'à la première occurence. –

Questions connexes