2010-06-25 17 views
6

Me gustaría que mi archivo de salida generado contenga rutas de archivos que apuntan a una ruta relativa a la hoja de estilos. La ubicación de la hoja de estilos puede cambiar y no quiero usar un parámetro para la hoja de estilos. Mi solución para esto es para obtener la hoja de estilo URI completo:Hacer manipulaciones de rutas de archivos en XSLT

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

Ahora sólo tiene que cortar el nombre del fichero de $stylesheetURI. Esto me ha inspirado para escribir XSLT 2.0 clones de las funciones de PHP basename y 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> 

Ahora puedo hacer algo como esto en mi plantilla:

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

Mi pregunta es: ¿Hay una mejor/formas más rápidas de lograr esto con XSLT 2.0 nativo?

+0

Disfruté trabajando en esta pregunta (+1). Vea mi respuesta por lo que parece ser un 25% más rápido. :) –

Respuesta

7

que probé (no demasiado extensivamente) estas funciones y parecen desempeñar un 25% más rápido que el proporcionado. Por supuesto, los resultados dependen de la longitud de la secuencia y el número de calificadores:

<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

¡Guau! ¿Podría ser esto porque la implementación de la secuencia (con tokenize y string-join) tiene más costos de producción que la manipulación de cadenas? Pero, ¿los string-to-codeponits también devuelven una secuencia? –

+0

@Alejandro: tokenize() hace mucho trabajo - escaneando char por char y colocando cada ficha en un artículo separado. Dondequiera substring-before() o substring-after() solo escanea hasta la primera ocurrencia. –

Cuestiones relacionadas