2010-06-05 14 views
7

Usando solo las funciones de cadena de XSLT 1.0, ¿cómo podría cortar el final de una url?¿Es posible cortar el final de una URL con XSLT 1.0?

Así que desde

http://stackoverflow.com/questions/2981175/is-it-possible-to-slice-the-end-of-a-url-with-xslt-1- 0

me gustaría extraer

es-es-posible-a-slice-el-fin-de-un-url-con-XSLT-1-0

¿Es esto posible?

+0

Buena pregunta (+1). Vea mi respuesta para dos soluciones completas diferentes. –

Respuesta

7

Desafortunadamente, no hay una función subscring-after-last en XSLT/XPath 1.0. Así que para obtener la última parte de una dirección URL que tendría que escribir una plantilla recursiva como explained by Jeni Tenisson:

<xsl:template name="substring-after-last"> 
    <xsl:param name="string" /> 
    <xsl:param name="delimiter" /> 
    <xsl:choose> 
    <xsl:when test="contains($string, $delimiter)"> 
     <xsl:call-template name="substring-after-last"> 
     <xsl:with-param name="string" 
      select="substring-after($string, $delimiter)" /> 
     <xsl:with-param name="delimiter" select="$delimiter" /> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise><xsl:value-of select="$string" /></xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

Esta plantilla se llama, por ejemplo, de esta manera:

<xsl:call-template name="substring-after-last"> 
    <xsl:with-param name="string" select="$url" /> 
    <xsl:with-param name="delimiter" select="'/'" /> 
</xsl:call-template> 
2

I. Utilizando una llamada recursiva plantilla llamada:

Esta transformación:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:template match="/"> 
    <xsl:call-template name="eatAllSlashes"> 
    <xsl:with-param name="pText" select="."/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="eatAllSlashes"> 
    <xsl:param name="pText"/> 

    <xsl:choose> 
    <xsl:when test="not(contains($pText,'/'))"> 
     <xsl:value-of select="$pText"/> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:call-template name="eatAllSlashes"> 
     <xsl:with-param name="pText" 
     select="substring-after($pText, '/')"/> 
    </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica en este documento XML:

<t>http://stackoverflow.com/questions/2981175/is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0</t> 

produce el deseado, salida correcta:

is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0 

II. Utilizando el FXSL biblioteca:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my" exclude-result-prefixes="xsl my"> 
<xsl:import href="iter.xsl"/> 

<xsl:output method="text"/> 

    <my:condition/> 
    <my:skipSlash/> 

    <xsl:variable name="vfunCondition" 
    select="document('')/*/my:condition"/> 

    <xsl:variable name="vfunSkipSlash" 
    select="document('')/*/my:skipSlash"/> 

    <xsl:template match="/"> 
    <xsl:call-template name="iterUntil"> 
     <xsl:with-param name="pCond" select="$vfunCondition"/> 
     <xsl:with-param name="pFun" select="$vfunSkipSlash"/> 
     <xsl:with-param name="arg1" select="string(/)"/> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template match="my:condition"> 
    <xsl:param name="arg1"/> 

    <xsl:value-of select="number(not(contains($arg1, '/')))"/> 
    </xsl:template> 

    <xsl:template match="my:skipSlash"> 
    <xsl:param name="arg1"/> 

    <xsl:value-of select="substring-after($arg1, '/')"/> 
    </xsl:template> 
</xsl:stylesheet> 

Cuando se aplica esta transformación en este documento XML:

<t>http://stackoverflow.com/questions/2981175/is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0</t> 

el resultado deseado se produce:

is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0 

hacer la nota :

  1. La plantilla iterUntil tiene tres parámetros:

    - pCond - una función (de referencia plantilla) que comprueba una condición sobre el resultado actual y potencialmente emite una "señal de parada" (1).

    - pFun - una función (referencia de plantilla) que se utiliza para producir el siguiente resultado actual del resultado actual (o inicialmente del argumento de entrada $ arg1).

    - arg1 - el argumento de entrada en el que se aplica inicialmente la función pFun.

  2. Nuestra función pCond es la plantilla que coincide con my:condition. Emite la "señal de parada" (salidas 1) solo si la cadena pasada como $arg1 no contiene ningún '/' caracteres.

  3. Nuestra función pFun es la plantilla que coincide con my:skipSlash. Descarta todos los caracteres hasta e incluyendo el primer '/' en la cadena $arg1

  4. El argumento de entrada inicial se define en $arg1 y es el valor de la cadena de la que sólo el texto después de la última '/' debe ser producido.

  5. La principal ventaja de usar FXSL es que esto evita la necesidad de codificar la recursión explícita y las posibilidades de errores al hacerlo. Además, la plantilla/funciones son muy genéricas y potentes y pueden reutilizarse para resolver grandes clases de problemas similares.

+0

¿Qué hace el espacio de nombres 'my:'? – Eric

+0

@Eric: utilizar un elemento de espacio de nombres que es un elemento secundario de '' es una técnica bien conocida que permite al desarrollador definir constantes globales a las que se puede acceder (utilizando un 'document ('')/*/prefijo: nombre' expresión XPath) por el código XSLT. –

Cuestiones relacionadas