IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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 :

Construire un glossaire en XSLT [XSLT 1.0]


Sujet :

XSL/XSLT/XPATH XML

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 99
    Par défaut Construire un glossaire en XSLT
    Bonjour,

    Je souhaite construire un "glossaire" en XSL (1.0, je n'ai pas la possibilité de monter en 2.0)

    Mon fichier ressemble à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    <Uri>
        <Title>Mon premier élément</Title>
    </Uri>
    <Uri>
        <Title>Mon deuxième élément</Title>
    </Uri>
    <Uri>
        <Title>AZERTY</Title>
    </Uri>
    ...
    La sortie contient deux "parties" :

    - Dans la premier partie, j'ai un alphabet,

    S'il existe au moins un élément "Title" dont la première lettre est "A", je dois mettre "enabled" dans les classes du span.
    Sinon je dois mettre "disabled".

    S'il existe au moins un élément "Title" dont la première lettre est "B", je dois mettre "enabled" dans les classes du span correspondant.
    Sinon je dois mettre "disabled".

    Etc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    <div class=alphabet>
    <span class="letterA enabled">A</span>
    <span class="letterB disabled">B</span>
    <span class="letterC disabled">C</span>
    <span class="letterD disabled">D</span>
    <span class="letterE disabled">E</span>
    ...
    <span class="letterM enabled">M</span>
    ...
    <span class="letterZ disabled">Z</span>
    </div>
    Mon deuxième besoin consiste afficher l'ensemble des éléments Title en les classant par ordre alphabétique et dans les plaçant dans le bon "ul".

    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
    20
     
    <div class=letterA>
        <strong>A</strong>
        <ul>
             <li>AZERTY</li>
        </ul>
    </div>
    <div class=letterB>
        <strong>B</strong>
        <ul>
        </ul>
    </div>
    ...
    <div class=letterM>
        <strong>M</strong>
        <ul>
             <li>Mon deuxième élément</li>
             <li>Mon premier élément</li>
        </ul>
    </div>
    Dans mon premier besoin, je n'arrive pas à faire un test du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
          <xsl:if test="count(substring(//Uri/Title,0,1) = 'A')>0">
            A EST PRESENT
          </xsl:if>
    ==> L'argument 1 de la fonction 'count()' ne peut pas être converti en collection de noeuds. -->count(substring(...itle,0,1) = 'A')<-- > 0

    Dans mon second besoin, je n'arrive pas à faire grand chose non plus : //.

    La finalité est d'introduire le résultat dans une page web MAIS je ne peux pas traiter ces problèmes en javascript. J'ai d'autres contraintes qui m'imposent de trouver une solution 'full xsl'.

    Merci pour votre aide

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par Laur3nT Voir le message
    Dans mon premier besoin, je n'arrive pas à faire un test du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
          <xsl:if test="count(substring(//Uri/Title,0,1) = 'A')>0">
            A EST PRESENT
          </xsl:if>
    ==> L'argument 1 de la fonction 'count()' ne peut pas être converti en collection de noeuds. -->count(substring(...itle,0,1) = 'A')<-- > 0
    C'est un prédicat qu'il te faut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test="//Uri/Title[starts-with(., 'A')]"
    Et qu'il faudra assez vite remplacer par quelque chose de bouclable pour éviter de l'écrire 26 fois :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test="//Uri/Title[starts-with(., $letter)]"
    Citation Envoyé par Laur3nT Voir le message
    Dans mon second besoin, je n'arrive pas à faire grand chose non plus : //.
    C'est la même chose que le premier besoin, au départ. Au lieu de tester s'il existe une <Uri> qui commence par telle lettre, on veut sélectionner toutes les <Uri> qui commencent par telle lettre. Et faire ça pour toutes les lettres de A à Z.

    Du coup, comme pour le premier problème on voudrait pouvoir faire une boucle sur les lettres de A*à Z, mais en XSLT 1.0 c'est un peu compliqué.

    Pour commencer, déclarer une <xsl:variable> globales qui contient les lettres de l'alphabet dans l'ordre.

    Ensuite, pour boucler dessus, il va falloir faire des templates récursifs qui prennent en paramètre la position dans l'alphabet de la lettre qu'ils doivent traiter, et qui traitent cette lettre, puis se rappellent eux-même sur la position suivante.

    Exemple :

    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
    <xsl:template name="faire-quelque-chose-sur-tout-l-alphabet">
      <xsl:call-template name="faire-quelque-chose-sur-une-lettre">
        <xsl:with-param name="index" select="0"/>
      </xsl:call-template>
    </xsl:template>
     
    <xsl:template name="faire-quelque-chose-sur-une-lettre">
      <xsl:param name="index"/>
      <!-- Faire quelque chose avec la lettre -->
      <xsl:value-of select="substring($alphabet, $index, 1)"/>
      <!-- Appeler les lettres suivantes -->
      <xsl:if test="string-length($alphabet) > $index">
        <xsl:call-template name="faire-quelque-chose-sur-une-lettre">
          <xsl:with-param name="index" select="$index + 1"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:template>
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre Expert
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Par défaut
    Une autre solution serait de faire un for-each trié dans une variable et de prendre la première lettre :
    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
    <!-- concaténation de tous les titres triés par ordre alphabétique -->
    <xsl:variable name="sorted_titles">
    	<xsl:for-each select="//Uri/Title">
    		<xsl:sort select="."/>
    		<xsl:value-of select="."/>
    	</xsl:for-each>
    </xsl:variable>
    <!-- récupération de la première lettre en forçant le fait qu'elle soit en majuscule -->
    <xsl:variable name="first_letter" select="upper-case(substring($sorted_titles, 1, 1))"/>
     
    <!-- détermination du statut enabled ou disabled, en supposant que tu as ta lettre dans une variable -->
    <xsl:choose>
    	<xsl:when test="$first_letter = $current_letter">
    		<xsl:text>enabled</xsl:text>
    	</xsl:when>
    	<xsl:otherwise>
    		<xsl:text>disabled</xsl:text>
    	</xsl:otherwise>
    </xsl:choose>
    Bon, faut avouer que c'est moche mais ça a le mérite de ne pas répéter 36 fois le même test.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Une autre solution par rapport à quoi ?

    Plutôt que de concaténer tous les titres, tu pourrais te contenter de ne garder que la première lettre de celui dont la position() est 1
    Bon sinon upper-case() n'existe pas en XSLT 1.0. Le plus simple est un translate() de toutes les minuscules vers toutes les majuscules, en espérant qu'il n'y a pas de trucs trop compliqués avec les accents.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 99
    Par défaut
    Génial ! Merci beaucoup

    Je fais du XSL de manière occasionnelle et la syntaxe (correcte) des prédicats me manquait !

    J'ai légérement modifié le DOM par rapport à mon message mais le résultat est conforme, dans le principe, à ce que je souhaitais.

    Je c/c si cela peut servir à quelqu'un par la suite.

    En tous cas : MERCI !

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    <xsl:template name="glossary">
        <xsl:variable name="alphabet">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
        <xsl:call-template name="loadGlossaryIndex">
          <xsl:with-param name="alphabet" select="$alphabet"/>
        </xsl:call-template>
        <xsl:call-template name="loadGlossary">
          <xsl:with-param name="alphabet" select="$alphabet"/>
        </xsl:call-template>
      </xsl:template>
     
      <xsl:template name="loadGlossary">
        <xsl:param name="alphabet"/>
        <ul class="glossary">
          <xsl:call-template name="loadGlossaryItems">
            <xsl:with-param name="alphabet" select="$alphabet"/>
            <xsl:with-param name="index">1</xsl:with-param>
          </xsl:call-template>
        </ul>
      </xsl:template>
     
      <xsl:template name="loadGlossaryItems">
        <xsl:param name="alphabet"/>
        <xsl:param name="index"/>
        <xsl:if test="string-length($alphabet) >= $index">
          <xsl:variable name="currentLetter" select="substring($alphabet, $index, 1)"/>
          <li class="glossaryLetter">
            <a>
              <xsl:attribute name="name">
                <xsl:value-of select="$currentLetter"/>
              </xsl:attribute>
              <strong>
                <xsl:value-of select="$currentLetter"/>
              </strong>
            </a>
            <ul>
              <xsl:for-each select="//Uri[@type='glossaire']/Title[starts-with(., $currentLetter)]">
                <xsl:sort data-type="text" order="ascending" select="."/>
                <li>
                  <xsl:value-of select="."/>
                </li>
              </xsl:for-each>
            </ul>
          </li>
          <xsl:call-template name="loadGlossaryItems">
            <xsl:with-param name="alphabet" select="$alphabet"/>
            <xsl:with-param name="index" select="$index+1"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:template>
     
      <xsl:template name="loadGlossaryIndex">
        <xsl:param name="alphabet"/>
        <ul class="alphabet">
          <xsl:call-template name="loadGlossaryLetters">
            <xsl:with-param name="alphabet" select="$alphabet"/>
            <xsl:with-param name="index">1</xsl:with-param>
          </xsl:call-template>
        </ul>
      </xsl:template>
     
      <xsl:template name="loadGlossaryLetters">
        <xsl:param name="alphabet"/>
        <xsl:param name="index"/>
        <xsl:if test="string-length($alphabet) >= $index">
          <xsl:variable name="currentLetter" select="substring($alphabet, $index, 1)"/>
          <li>
            <a>
              <xsl:attribute name="href">
                <xsl:value-of select="concat('#',$currentLetter)"/>
              </xsl:attribute>
              <xsl:if test="not(//Uri[@type='glossaire']/Title[starts-with(., $currentLetter)])">
                <xsl:attribute name="class">disabled</xsl:attribute>
              </xsl:if>
              <xsl:value-of select="$currentLetter"/>
            </a>
          </li>
          <xsl:call-template name="loadGlossaryLetters">
            <xsl:with-param name="alphabet" select="$alphabet"/>
            <xsl:with-param name="index" select="$index+1"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:template>

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XSLT] construire un tableau JavaScript
    Par Mike35 dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 16/10/2006, 14h21
  2. [Documentation][XSLT][XSLFO]Les balises xslfo
    Par Lydiane dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 14/08/2002, 11h31
  3. [XSLT] les variables???
    Par Lydiane dans le forum XSL/XSLT/XPATH
    Réponses: 11
    Dernier message: 09/08/2002, 16h17
  4. [XSLT] inclure du XSL dans une balise html
    Par iaa dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 05/08/2002, 15h57
  5. [XSLT]position d'un element de valeur specifique
    Par squat dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 25/07/2002, 16h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo