web-dev-qa-db-fra.com

Chaîne XSLT remplacer

Je ne connais pas vraiment XSL mais je dois corriger ce code, je l'ai réduit pour le rendre plus simple.
Je reçois cette erreur

Fonction XSLT/XPath non valide

sur cette ligne

<xsl:variable name="text" select="replace($text,'a','b')"/>

C'est le XSL

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:inm="http://www.inmagic.com/webpublisher/query" version="1.0">
    <xsl:output method="text" encoding="UTF-8" />

    <xsl:preserve-space elements="*" />
    <xsl:template match="text()" />

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

        <xsl:for-each select="mosObj">
          'Notes or subject' 
           <xsl:call-template
                name="rem-html">
                <xsl:with-param name="text" select="SBS_ABSTRACT" />
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="rem-html">
        <xsl:param name="text" />
        <xsl:variable name="text" select="replace($text, 'a', 'b')" />
    </xsl:template>
</xsl:stylesheet>

Quelqu'un peut-il me dire ce qui ne va pas?

82
Aximili

replace n'est pas disponible pour XSLT 1.0.

Codesling a un modèle pour string-replace que vous pouvez utiliser comme substitut de la fonction:

<xsl:template name="string-replace-all">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
        <xsl:when test="$text = '' or $replace = ''or not($replace)" >
            <!-- Prevent this routine from hanging -->
            <xsl:value-of select="$text" />
        </xsl:when>
        <xsl:when test="contains($text, $replace)">
            <xsl:value-of select="substring-before($text,$replace)" />
            <xsl:value-of select="$by" />
            <xsl:call-template name="string-replace-all">
                <xsl:with-param name="text" select="substring-after($text,$replace)" />
                <xsl:with-param name="replace" select="$replace" />
                <xsl:with-param name="by" select="$by" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

invoqué comme:

<xsl:variable name="newtext">
    <xsl:call-template name="string-replace-all">
        <xsl:with-param name="text" select="$text" />
        <xsl:with-param name="replace" select="a" />
        <xsl:with-param name="by" select="b" />
    </xsl:call-template>
</xsl:variable>

D'autre part, si vous ne devez littéralement remplacer qu'un caractère par un autre, vous pouvez appeler translate qui possède une signature similaire. Quelque chose comme ça devrait bien fonctionner:

<xsl:variable name="newtext" select="translate($text,'a','b')"/>

Notez également que dans cet exemple, j'ai changé le nom de la variable en "newtext", les variables XSLT étant immuables, vous ne pouvez donc pas utiliser l'équivalent de $foo = $foo comme dans votre code d'origine.

133
Mark Elliot

Voici la fonction XSLT qui fonctionnera de manière similaire à la fonction String.Replace () de C #.

Ce modèle a les 3 paramètres ci-dessous

text : - votre chaîne principale

remplace : - la chaîne que vous souhaitez remplacer

by : - la chaîne qui répondra par une nouvelle chaîne

Ci-dessous, le modèle

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

L'exemple ci-dessous montre comment l'appeler

<xsl:variable name="myVariable ">
  <xsl:call-template name="string-replace-all">
    <xsl:with-param name="text" select="'This is a {old} text'" />
    <xsl:with-param name="replace" select="'{old}'" />
    <xsl:with-param name="by" select="'New'" />
  </xsl:call-template>
</xsl:variable>

Vous pouvez également vous référer au RL ci-dessous pour plus de détails.

36
Optimus

Note: Si vous souhaitez utiliser l’algorithme déjà mentionné pour les cas où vous devez remplacer un grand nombre d’occurrences dans la chaîne source (par exemple, de nouvelles lignes dans un texte long), il existe forte probabilité que vous vous retrouviez avec StackOverflowException à cause de l'appel récursif.

J'ai résolu ce problème grâce à Xalan (n'a pas regardé comment le faire dans Saxon) intégré Java type incorporant:

<xsl:stylesheet version="1.0" exclude-result-prefixes="xalan str"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xalan="http://xml.Apache.org/xalan"
                xmlns:str="xalan://Java.lang.String"
        >
...
<xsl:value-of select="str:replaceAll(
    str:new(text()),
    $search_string,
    $replace_string)"/>
...
</xsl:stylesheet>
12
Milan Aleksić

Vous pouvez utiliser le code suivant lorsque votre processeur s'exécute sur .NET ou utilise MSXML (par opposition aux processeurs basés sur Java ou autres). Il utilise msxsl:script .

Veillez à ajouter l'espace de nom _xmlns:msxsl="urn:schemas-Microsoft-com:xslt"_ à votre élément racine _xsl:stylesheet_ ou _xsl:transform_.

De plus, liez outlet à tout espace de nom de votre choix, par exemple _xmlns:outlet = "http://my.functions"_.

_<msxsl:script implements-prefix="outlet" language="javascript">
function replace_str(str_text,str_replace,str_by)
{
     return str_text.replace(str_replace,str_by);
}
</msxsl:script>


<xsl:variable name="newtext" select="outlet:replace_str(string(@oldstring),'me','you')" />
_
6
John Jin

La rouine est plutôt bonne, mais mon application est bloquée, je devais donc ajouter le cas:

  <xsl:when test="$text = '' or $replace = ''or not($replace)" >
    <xsl:value-of select="$text" />
    <!-- Prevent thsi routine from hanging -->
  </xsl:when>

avant que la fonction soit appelée récursivement.

J'ai eu la réponse d'ici: Lorsque le test est suspendu dans une boucle infinie

Je vous remercie!

0
Chesare