2010-06-20 31 views
6

Solo quiero saber si es posible usar expresiones regulares en el atributo match del elemento xsl:template. Por ejemplo, supongamos que tengo el documento de seguimiento XML:Expresiones regulares en xsl: atributo de coincidencia de plantilla

<greeting> 
    <aaa>Hello</aaa> 
    <bbb>Good</bbb> 
    <ccc>Excellent</ccc> 
    <dddline>Line</dddline> 
</greeting> 

Ahora el XSLT para transformar el documento anterior:

<xsl:stylesheet> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="*"/> 
    </xsl:template> 

    <xsl:template match="matches(node-name(*),'line')"> 
     <xsl:value-of select="."/> 
    </xsl:template> 

</xsl:stylesheet> 

Cuando trato de utilizar la sintaxis matches(node-name(*),'line$') en el atributo match del xsl:template elemento, recupera un mensaje de error. ¿Puedo usar expresiones regulares en el atributo match?

Muchas gracias

+2

La próxima vez, por favor, acabo de leer la caja al lado del cuadro de texto, donde dice *" Cómo formatear: sangrar el código por 4 espacios "*. Entonces no tiene que usar '<' etc ... –

+0

Buena pregunta (+1). Vea mi respuesta, que en este momento contiene la única solución completamente correcta para sus dos preguntas relacionadas. :) –

Respuesta

14

Aquí es la correcta XSLT 1.0 manera de hacer coincidir (en XSLT 2.0 utilizan los partidos() con una expresión regular real como el argumento pattern):

Coincidencia de un elemento cuyo nombre contiene 'line':

<xsl:template match="*[contains(name(), 'line')]"> 
    <!-- Whatever processing is necessary --> 
</xsl:template> 

Coincidencia de un elemento cuyo nombre termina en 'line':

<xsl:template match="*[substring(name(), string-length() -3) = 'line']"> 
    <!-- Whatever processing is necessary --> 
</xsl:template> 

@Tomalak proporcionó otra forma XSLT 1.0 de buscar nombres que terminan con una cadena dada. Su solución utiliza un carácter especial que garantiza que nunca estará presente en ningún nombre. Mi solución se puede aplicar para encontrar si cualquier cadena (no solo el nombre de un elemento) termina con otra cadena dada.

En XSLT 2.x:

Uso: matches(name(), '.*line$') para que coincida con los nombres que terminan con la cadena "line"

Esta transformación:

cuando se aplica en el documento Theis XML:

<greeting> 
    <aaa>Hello</aaa> 
    <bblineb>Good</bblineb> 
    <ccc>Excellent</ccc> 
    <dddline>Line</dddline> 
</greeting> 

copias a la salida sólo el elemento, cuyo nombre termina con la cadena "line":

<dddline>Line</dddline> 

Mientras esta transformación (usa matches(name(), '.*line')):

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="*[matches(name(), '.*line')]"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="*[not(matches(name(), '.*line'))]"> 
    <xsl:apply-templates select="node()[not(self::text())]"/> 
</xsl:template> 
</xsl:stylesheet> 

copias a la salida de todos los elementos, cuyos nombres contienen la cadena "line":

<bblineb>Good</bblineb> 
<dddline>Line</dddline> 
+0

En primer lugar, muchas gracias por su esfuerzo, fue la primera vez que publico una duda en este foro, estoy realmente sorprendido de que haya respondido rápidamente. Extraño la versión del xslt con la que pretendo trabajar, lo hará ser 2.0 y sí quiero encontrar la cadena 'línea' en el de una cadena. Una vez más, gracias a su apoyo – tt0686

+0

@pedromarquescosta: De nada. He actualizado mi respuesta con la solución XSLT 2.0 solicitada que usa RegEx. –

5

En XSLT 1.0 (y 2.0, también), por su ejemplo (no es una expresión regular, sin embargo):

<xsl:template match="*[contains(name(), 'line')]"> 
    <xsl:value-of select="."/> 
</xsl:template> 

y para lograr una coincidencia de fin de cadena :

<xsl:template match="*[contains(concat(name(), '&#xA;'), 'line&#xA;')]"> 
    <xsl:value-of select="."/> 
</xsl:template> 

en XSLT 2.0 se puede, por supuesto, utilizar la función de matches() en lugar de .

+0

@Dimitre: Como dijiste, LF no puede ser parte del 'nombre()'. Entonces, si no puede usar XPath 2.0 (y regex), esta sería una forma de emparejar un nombre que contiene la cadena ''línea'' en su extremo, en lugar de en cualquier lugar. El OP parece querer eso, porque menciona la expresión regular ''línea $ '', y no indicó la versión XSLT que usa. Podría haber usado espacio, o cualquier otro personaje que sea ilegal en los nombres. Entonces no tiene ningún sentido o es incorrecto. ;-) – Tomalak

+0

OK, ya veo. Para los nombres, esto funciona. –

Cuestiones relacionadas