Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XML/XSL et SOAP Discussion :

XSLT 1.0 plusieurs appels d'un template


Sujet :

XML/XSL et SOAP

  1. #1
    Membre à l'essai
    XSLT 1.0 plusieurs appels d'un template
    Hello,
    J'essaie de transformer certaines chaînes de caractères qui font planter une appli dans un fichier XML à l'aide de XSLT 1.0.
    Pour cela j'utilise un template que j'essaie d'appeler plusieurs fois. Hors, seul le dernier appel au template fonctionne, et ne me change donc que le dernier string d'une série.

    Pour illustrer :
    Le XML que je veux modifier :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?xml version="1.0" encoding="UTF-8"?>
    <RAPPORT>
        <reason>debut test_test_145 &#145; et test 151 &#151; fin test</reason>
    </RAPPORT>


    Le template XSLT :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
        <xsl:template name="globalReplace">
            <xsl:param name="outputString"/>
            <xsl:param name="target"/>
            <xsl:param name="replacement"/>
            <xsl:choose>
                <xsl:when test="contains($outputString,$target)">
                    <xsl:value-of select="concat(substring-before($outputString,$target),$replacement)"/>
                    <xsl:call-template name="globalReplace">
                        <xsl:with-param name="outputString" select="substring-after($outputString,$target)"/>
                        <xsl:with-param name="target" select="$target"/>
                        <xsl:with-param name="replacement" select="$replacement"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$outputString"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>


    Les appels au template :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
        <xsl:template match="text()">
            <xsl:call-template name="globalReplace">
                <xsl:with-param name="outputString" select="."/>
                <xsl:with-param name="target" select="'&#145;'"/>
                <xsl:with-param name="replacement" select="' '"/>
            </xsl:call-template>
        </xsl:template>
     
        <xsl:template match="text()">
            <xsl:call-template name="globalReplace">
                <xsl:with-param name="outputString" select="."/>
                <xsl:with-param name="target" select="'&#151;'"/>
                <xsl:with-param name="replacement" select="' '"/>
            </xsl:call-template>
        </xsl:template>


    Le résultat attendu :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?xml version="1.0" encoding="UTF-8"?>
    <RAPPORT>
        <reason>debut test_test_145 et test 151 _fin test</reason>
    </RAPPORT>


    Le résultat effectif :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <?xml version="1.0" encoding="UTF-8"?>
    <RAPPORT>
        <reason>debut test_test_145PUI et test 151 _fin test</reason>
    </RAPPORT>

    où PUI représente un caractère non désiré, qui fait planter l'appli utilisatrice du XML...

    Auriez-vous une idée ou piste pour m'aider

  2. #2
    Modérateur

    Quand un template doit s'appliquer sur un noeud, XSLT en choisit un et un seul, et l'applique.

    Si tu as plusieurs templates qui ont le même match() (et pas de name et pas de mode et patati et patata) ceux après le premier ne servent absolument à rien.

    La solution est donc d'appeler globalReplace plusieurs fois de suite, dans le même template.

    Une idée serait ça :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        <xsl:template match="text()">
          <xsl:variable name="aposLess">
            <xsl:call-template name="globalReplace">
                <xsl:with-param name="outputString" select="."/>
                <xsl:with-param name="target" select="'‘'"/>
                <xsl:with-param name="replacement" select="' '"/>
            </xsl:call-template>
          </xsl:variable>
     
          <xsl:call-template name="globalReplace">
              <xsl:with-param name="outputString" select="$aposLess"/>
              <xsl:with-param name="target" select="''—''"/>
              <xsl:with-param name="replacement" select="' '"/>
          </xsl:call-template>
        </xsl:template>
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre à l'essai
    J'avais déjà essayé ça :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        <xsl:template match="text()">
            <xsl:call-template name="globalReplace">
                <xsl:with-param name="outputString" select="."/>
                <xsl:with-param name="target" select="'&#145;'"/>
                <xsl:with-param name="replacement" select="' '"/>
            </xsl:call-template>
            <xsl:call-template name="globalReplace">
                <xsl:with-param name="outputString" select="."/>
                <xsl:with-param name="target" select="'&#151;'"/>
                <xsl:with-param name="replacement" select="' '"/>
            </xsl:call-template>
        </xsl:template>


    Mais le résultat n'est pas bon : la données est présente 2 fois, une fois avec un caracère remplacé et l'autre fois avec l'autre caractère remplacé
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <?xml version="1.0" encoding="UTF-8"?>
    <RAPPORT>
     
    	<reason>debut test_test_145  et test 151&#151;_fin testdebut test_test_145&#145; et test 151 _fin test</reason>
     
     
    </RAPPORT>

  4. #4
    Modérateur

    Je sais.

    C'est pour ça que moi, je mets les choses dans une variable d'abord. D'une part, ça n'écrit pas les résultats intermédiaires mais seulement le dernier, d'autre part on ne perd pas les résultats d'un appel à l'autre.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre à l'essai
    Ah oui c'est tip top !
    Je n'avais pas vu que tu utilisais ta variable $aposLess dans le second appel au template
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    <xsl:with-param name="outputString" select="$aposLess"/>

    Et de proche en proche, en utilisant d'autres variables j'arrive à traiter X caractères comme ça !
    Un grand grand merci !

  6. #6
    Membre à l'essai
    Un petit complément d'info...
    Voici une solution qui m'a été suggérée sur le stackoverflow pour résoudre ces problématiques :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <xsl:template match="text()">
     <xsl:value-of select="translate(., '&#145;=&#151;','  ')"/>
    </xsl:template>


    Et l'adaptation que j'en ai faite à mon besoin avec ta solution de passage par une variable :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    <xsl:template match="text()">
     <xsl:variable name="premierePasse">
      <xsl:value-of select="translate(., '&#145;&#151;&#146;','   ')"/>
     </xsl:variable>
     <xsl:value-of select="translate($premierePasse, '&#156;', 'œ')"/>
    </xsl:template>

  7. #7
    Modérateur

    Effectivement, j'oublie toujours que translate() existe.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre à l'essai
    Et en fait, ça fonctionne sans faire d'appels multiples, juste en positionnant correctement les éléments à remplacer dans la fonction :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <xsl:template match="text()">
     <xsl:value-of select="translate(., '&#145;&#146;&#151;&#156;','  -œ')"/>
    </xsl:template>