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

XSL/XSLT/XPATH XML Discussion :

Problème de contexte dans une boucle « for-each »


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Candidat au Club
    Problème de contexte dans une boucle « for-each »
    Bonjour,
    J’aimerais récupérer uniquement les balises contenant du texte d’un XML de ce type :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <html>
    	<keyword/>
    	<p>Ceci est le 1er bloc</p>
    	<keyword>Ceci est le 1er keyword</keyword>
    	<p>Ceci est le 2ème bloc</p>
    	<keyword/>
    	<p>Ceci est le 3ème bloc</p>
    	<p/>
    	<keyword>Ceci est le 3ème keyword</keyword>
    	<p>Ceci est le 4ème bloc</p>
    	<keyword/>
    </html>

    J’ai testé avec différentes méthodes et ce qui se rapproche le plus du résultat que je souhaite obtenir est :
    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
     
    <html>
    <xsl:if test="/html/p != ''">
    	<xsl:for-each select="/html/p != ''">
    		<p>
    			<xsl:apply-templates/>
    		</p>
    		<xsl:if test="./following::keyword[1]">
    			< keyword >
    				<xsl:value-of select="./following::keyword[1]" />
    			</ keyword >
    		</xsl:if>
    	</xsl:for-each>
    </xsl:if>
    </html>


    Résultat
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <html>
    <p>Ceci est le 1er bloc</p>
    <keyword>Ceci est le 1er keyword</keyword>
    <p>Ceci est le 2ème bloc</p>
    <keyword>Ceci est le 3ème keyword</keyword>
    <p>Ceci est le 3ème bloc</p>
    <keyword>Ceci est le 3ème keyword</keyword>
    <p>Ceci est le 4ème bloc</p>
    </html>

    En fait, je n’arrive pas vraiment à placer au bon endroit les valeurs que je recherche, ce problème de contexte est lié à la fonction « for-each ». Ça paraît simple, mais je n'y arrive pas. J’ai essayé d’utiliser des templates sans parvenir à mes fins, l’un de vous pourrait m’aiguiller sur une solution ?

  2. #2
    Candidat au Club
    Merci Caballo pour ta réponse.

    En modifiant ta proposition, j'obtiens un résultat qui s'approche de ce que j'attends.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:template match="html">		
       <xsl:for-each select="//*">
    	     <xsl:copy-of select="node()[.!='']"/>
       </xsl:for-each>
    </xsl:template>


    je conserve bien les balises <p> et <keyword> contenant du texte. Mais, chose que j'avais oublié dans le sujet initial, j'aimerais également renommer la balise <keyword> en <motclef> par exemple.

    En bref : conservation des balises non vides (<p> et <keyword>) et remplacement de la balise <keyword> par <motclef>.

  3. #3
    Membre actif
    on peut tourner ca autrement (si tu connais les balises attendues)

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <xsl:for-each select="child::*">
    	<xsl:if test="local-name()='p' and . != '' ">
    		<p>
    		<xsl:copy-of select="text()"/>
    		</p>
    	</xsl:if>					
    	<xsl:if test="local-name()='keyword' and . != '' ">
    		<motclef>
    		<xsl:copy-of select="text()"/>
    		</motclef>
    	</xsl:if>				
    </xsl:for-each>
    "Chuck Norris a déjà compté jusqu'à l'infini. Deux fois."

  4. #4
    Candidat au Club
    Ça fonctionne !
    C'est exactement ce que j'avais besoin. J'ai essayé à peu près la même chose mais en utilisant current() au lieu de local-name() (ou name() qui fonctionne également) mais ça ne ramenait pas le résultat escompté. Je pensais que current() et name() était la même chose... Ça doit être la différence entre le noeud courant et le noeud du contexte ?!
    Merci Caballo !

  5. #5
    Modérateur

    current() est le nœud en cours, name() est le nom du nœud en cours.

    La différence ?

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <root>
      <u>a</u>
      <u>b</u>
      <u>c</u>
    </root>


    Il y a trois éléments différents, contenant chacun a, b ou c, et ils ont tous le même nom "u".

    A noter que c'est souvent un peu dommage d'utiliser name() ou local-name().

    On pouvait aussi s'en sortir à coup de templates :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:template match="p[. != '']">
      <p>
        <xsl:apply-templates/>
      </p>
    </xsl:template>


    et

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:template match="keyword[. != '']">
      <motclef>
        <xsl:apply-templates/>
      </motclef>
    </xsl:template>
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Candidat au Club
    Merci Thelvin pour ces précisions supplémentaires, je prends note.