web-dev-qa-db-fra.com

Sous-chaîne XSL et indexOf

Je suis nouveau sur XSLT. Je me demande s'il est possible de sélectionner une sous-chaîne d'un élément. J'essaie d'analyser un flux RSS. La valeur de description contient plus de texte que ce que je veux afficher. Je voudrais en obtenir une sous-chaîne basée sur l'index d'une sous-chaîne. Fondamentalement, je veux montrer le résultat d'un appel de sous-chaîne passant indxOf ('some_substring') et une longueur comme paramètres. Est-ce possible?

D'après les commentaires:

Je veux sélectionner le texte d'une chaîne qui se trouve après l'occurrence de la sous-chaîne

22
Carlos Blanco

On ne sait pas exactement ce que vous voulez faire avec l'index d'une sous-chaîne [mise à jour: c'est plus clair maintenant - merci] mais vous pouvez peut-être utiliser la fonction substring-after Ou substring-before:

substring-before('My name is Fred', 'Fred')

renvoie 'My name is '.

Si vous avez besoin d'un contrôle plus détaillé, la fonction substring() peut prendre deux ou trois arguments: chaîne, index de départ, longueur. Omettez la longueur pour obtenir le reste de la chaîne.

Il n'y a pas de fonction index-of() pour les chaînes dans XPath (uniquement pour les séquences, dans XPath 2.0). Vous pouvez utiliser string-length(substring-before($string, $substring))+1 si vous avez spécifiquement besoin de la position.

Il y a aussi contains($string, $substring). Ce sont tous documentés ici . Dans XPath 2.0, vous pouvez utiliser la correspondance d'expressions régulières.

(XSLT utilise principalement XPath pour sélectionner les nœuds et traiter les valeurs, donc c'est en fait plus une question XPath. Je l'ai tagué ainsi.)

46
LarsH

Voici quelques expressions lignées xpath 1.0 pour IndexOf ($ text, $ searchString):

Si vous avez besoin de la position du caractère PREMIER de la chaîne recherchée, ou 0 s'il n'est pas présent:

contains($text,$searchString)*(1 + string-length(substring-before($text,$searchString)))

Si vous avez besoin de la position du premier caractère APRÈS la chaîne trouvée, ou si elle n'est pas présente:

contains($text,$searchString)*(1 + string-length(substring-before($text,$searchString)) + string-length($searchString))

Alternativement, si vous avez besoin de la position du premier caractère APRÈS la chaîne trouvée, ou longueur + 1 si elle n'est pas présente:

1 + string-length($right) - string-length(substring-after($right,$searchString))

Cela devrait couvrir la plupart des cas dont vous avez besoin.

Remarque: La multiplication par contient (...) entraîne la conversion du résultat vrai ou faux de la fonction contient (...) en 1 ou 0, ce qui fournit élégamment la partie "0 lorsqu'il n'est pas trouvé" de la logique.

9
MrWatson

Je veux sélectionner le texte d'une chaîne qui se trouve après l'occurrence de la sous-chaîne

Vous pouvez utiliser:

substring-after($string,$match)

Si vous voulez une sous-chaîne de ce qui précède avec une certaine longueur, utilisez:

substring(substring-after($string,$match),1,$length)

Mais les problèmes commencent s'il n'y a pas d'occurrence de la sous-chaîne correspondante ... Donc, si vous voulez une sous-chaîne de longueur spécifique située après l'occurrence d'une sous-chaîne, ou de la chaîne entière s'il n'y a pas de correspondance, vous pouvez utiliser:

substring(substring-after($string,substring-before($string,$match)),
          string-length($match) * contains($string,$match) + 1,
          $length) 
7
user357812

Voici un exemple complet contenant à la fois XML et XSLT où la sous-chaîne avant et la sous-chaîne après sont utilisées

<?xml version="1.0" encoding="UTF-8"?>
<persons name="Group_SOEM">
    <person>
        <first>Joe Smith</first>
        <last>Joe Smith</last>
        <address>123 Main St, Anycity</address>
    </person>
</persons>    

Ce qui suit est XSLT qui modifie la valeur du prénom/nom en séparant la valeur par l'espace de sorte qu'après avoir appliqué ce XSL, l'élément du prénom aura la valeur "Joe" et le dernier "Smith".

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="first">
    <first>
        <xsl:value-of select="substring-before(.,' ')" />
    </first>
</xsl:template> 
<xsl:template match="last">
    <last>
        <xsl:value-of select="substring-after(.,' ')" />
    </last>
</xsl:template> 
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>   
5
Hemant

Il existe une fonction de sous-chaîne dans XSLT. Exemple ici .

2
Jon