2010-06-20 3 views
6

Je veux juste savoir s'il est possible d'utiliser des expressions régulières dans l'attribut match de l'élément xsl:template. Par exemple, supposons que je le document XML de suivi:Expressions régulières dans l'attribut de correspondance xsl: template

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

Maintenant, le XSLT pour transformer le document ci-dessus:

<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> 

Lorsque je tente d'utiliser la syntaxe matches(node-name(*),'line$') dans l'attribut match du xsl:template élément, il récupère un message d'erreur. Puis-je utiliser des expressions régulières dans l'attribut match?

Merci beaucoup

+2

La prochaine fois, s'il vous plaît il suffit de lire la case à côté de la zone de texte, où il est dit * » Comment formater: indentation du code de 4 espaces "*. Ensuite, vous ne devez pas utiliser '<' etc ... –

+0

Bonne question (+1). Voir ma réponse, qui à ce moment contient la seule solution complètement correcte à vos deux questions connexes. :) –

Répondre

14

Voici la façon XSLT 1.0 correcte de l'appariement (en XSLT 2.0 utilisent les résultats() fonction avec un vrai RegEx comme argument pattern):

correspondants d'un élément dont le nom contient 'line':

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

correspondants d'un élément dont le nom se termine 'line':

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

@Tomalak fourni une autre manière XSLT 1.0 de trouver des noms se terminant par une chaîne donnée. Sa solution utilise un caractère spécial garanti pour ne jamais être présent dans aucun nom. Ma solution peut être appliquée pour trouver si n'importe quelle chaîne (pas seulement le nom d'un élément) se termine avec une autre chaîne donnée.

Dans XSLT 2.x:

Utilisez: matches(name(), '.*line$') pour faire correspondre les noms qui se terminent par la chaîne "line"

Cette transformation:

lorsqu'il est appliqué sur le document XML Theis:

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

copies à la sortie que l'élément dont le nom se termine par la chaîne "line":

<dddline>Line</dddline> 

Bien que cette transformation (utilise 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> 

copies à la sortie de tous les éléments, dont les noms contiennent la chaîne "line":

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

Tout d'abord, merci beaucoup par vos efforts, c'était la première fois que je poste un doute dans ce forum je suis vraiment surpris de vous avoir répondu.Je rate la version de la xslt que je fais semblant de travailler, il va Etre 2.0 et oui je veux trouver la chaine 'line' au bout d'une chaine. Encore une fois, merci beaucoup pour votre soutien – tt0686

+0

@pedromarquescosta: De rien. J'ai mis à jour ma réponse avec la solution XSLT 2.0 demandée qui utilise RegEx. –

5

Dans XSLT 1.0 (et 2.0, aussi), pour votre exemple (ce n'est pas une expression régulière, cependant):

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

et pour obtenir une correspondance de fin de chaîne :

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

dans XSLT 2.0, vous pouvez bien sûr utiliser la fonction matches() en place de .

+0

@Dimitre: Comme vous l'avez dit, LF ne peut pas faire partie de 'name()'. Donc, si vous ne pouvez pas utiliser XPath 2.0 (et regex), ce serait un moyen de faire correspondre un nom qui contient la chaîne '' line'' à sa fin, et non ailleurs. L'OP semble vouloir cela, car il mentionne l'expression rationnelle «ligne $», et il n'a pas indiqué la version de XSLT qu'il utilise. J'aurais pu utiliser de l'espace, ou n'importe quel autre personnage qui est illégal dans les noms. Donc ce n'est pas du tout dénué de sens ou incorrect. ;-) – Tomalak

+0

OK, je vois maintenant. Pour les noms cela fonctionne. –