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 :

Regrouper par valeur d'attribut + compteur


Sujet :

XSL/XSLT/XPATH XML

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau candidat au Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 2
    Par défaut Regrouper par valeur d'attribut + compteur
    Bonjour à tous,

    Je sollicite votre aide car débutant avec XSL, je n'ai pas trouvé d'exemples se rapprochant de mon cas précis.
    J'ai essayé plusieurs choses, for-each-group, muench, key, récursivité, mais je n'arrive à rien, je ne sais pas vers quelle methode me tourner.

    J'ai en entrée un XML formé d'une succession d'éléments "contenu" possédant tous un attribut "class".
    Cet attribut correspond à un style appliqué au différentes parties du texte : les différentes valeurs de cet attribut apparaissent donc dans un ordre complètement aléatoire.

    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
     
    <document>
    	<contenu class="classeA">texte A...</contenu>
    	<contenu class="classeA">texte B...</contenu>
    	<contenu class="classeA">texte C...</contenu>
    	<contenu class="classeC">texte D...</contenu>
    	<contenu class="classeC">texte E...</contenu>
    	<contenu class="classeB">texte F...</contenu>
    	<contenu class="classeA">texte G...</contenu>
    	<contenu class="classeD">texte H...</contenu>
    	<contenu class="classeD">texte I...</contenu>
    	<contenu class="classeA">texte J...</contenu>
    	<contenu class="classeA">texte K...</contenu>
    	<contenu class="classeB">texte L...</contenu>
    	<contenu class="classeB">texte M...</contenu>
    ...
    </document>
    Voici ce que je dois obtenir :
    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
     
     
    <document>
    	<contenu class="classeA">
    		<contenu class="1">texte A...</span>
    		<contenu class="2">texte B...</span>
    		<contenu class="3">texte C...</span>
    	</contenu>
    	<contenu class="classeC">
    		<contenu class="1">texte D...</span>
    		<contenu class="2">texte E...</span>
    	</contenu>
    	<contenu class="classeB">texte F...</contenu>
    	<contenu class="classeA 1">texte G...</contenu>
    	<contenu class="classeD">
    		<contenu class="1">texte H...</span>
    		<contenu class="2">texte I...</span>
    	</contenu>
    	<contenu class="classeA 2">
    		<contenu class="1">texte J...</span>
    		<contenu class="2">texte K...</span>
    	</contenu>
    	<contenu class="classeB 1">
    		<contenu class="1">texte L...</span>
    		<contenu class="2">texte M...</span>
    	</contenu>
    </document>
    Si plusieurs éléments avec la même valeur d'attribut "class" se suivent, ils doivent être regroupés dans un élément possédant le même attribut.
    L'attribut class des éléments regroupés doit être numérotés (compteur).

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <contenu class="classeA">texte A...</contenu>
    <contenu class="classeA">texte B...</contenu>
    <contenu class="classeA">texte C...</contenu>
    devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <contenu class="classeA">
    	<contenu class="1">texte A...</span>
    	<contenu class="2">texte B...</span>
    	<contenu class="3">texte C...</span>
    </contenu>

    Une fois ces regroupements effectués, les différentes occurences d'une même classe doivent être numérotées également :
    Par exemple
    <contenu class="classeA 1">texte G...</contenu>

    Car on a déjà <contenu class="classeA"> au dessus.

    La dernière contrainte que j'ai, c'est que l'ordre des éléments texte ne doit pas être modifié.

    D'avance, un immense 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
    Ok, je suis arrivé à le faire, mais je confirme, c'était pas évident du tout.
    Première précision : je ne connais que XSLT 1.0 et xPath 1.0. Pas de XSLT 2.0 et je ne connais pas bien EXSLT non plus. Tout ce petit monde pourrait peut-être simplifier un peu les choses.

    Je confirme que le problème ressemble à un regroupement Muench, mais l'ennui, c'est, on regroupe sur quoi ?
    On veut regrouper, d'une part sur la @class, d'autre part sur quelle "séquence" de cette @class se trouve le nœud.
    Or, ça si on comprend grosso-modo ce que ça veut dire, l'exprimer en xPath 1.0 n'a même pas l'air possible.

    Comment j'ai fait : sans clé.

    Pour commencer j'ai fait un template nommé qui calcule, pour le nœud en cours, dans quelle séquence de sa @class il se trouve (première séquence, deuxième séquence, etc.)
    Ça donne ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <xsl:template name="seqNum">
      <xsl:value-of select="count(
        (preceding-sibling::*|self::*)[
          @class = current()/@class
          and
          not(preceding-sibling::*[1][@class = current()/@class])
        ]
      )"/>
    </xsl:template>
    En appelant ce template, on obtient le numéro de la séquence dans laquelle est le nœud en cours.

    Reste à s'en servir.
    #1 Sur quoi boucler ? J'ai fait un for-each sur tous les <contenu>.
    À l'intérieur de ce for-each, je ne fais quelque chose que si le <contenu> en cours répond à des conditions.
    Ce qu'il y aurait à faire, c'est créer le <class name="{@class}"> ... </class> en mettant ce qu'il faut à l'intérieur.
    Dans quel cas on a besoin de faire ça ? Quand on commence une nouvelle séquence, donc quand le nœud en cours n'a pas de voisin précédent de la même classe que lui :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:if test="not(preceding-sibling::*[1][@class = current()/@class])">

    #2 comment sélectionner ce qu'on va mettre dans ce <class> ?
    - D'abord le nœud pour qui on l'a ouvert.
    - Ensuite les nœuds de même @class et qui sont dans la même séquence.
    => On calcule, avec le template, le numéro de séquence du nœud qui a ouvert ce <class>
    => On fait un for-each sur tous les nœuds suivant de même @class que lui.
    => Pour chacun, on calcule aussi son numéro de séquence.
    => Si c'est le même, on ajoute le nœud.

    Conclusion : regroupement effectué. Reste à calculer tes class="1", pas trop difficile normalement.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Rédacteur

    Avatar de Erwy
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2003
    Messages
    4 967
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Par défaut
    Citation Envoyé par thelvin Voir le message

    Comment j'ai fait : sans clé.
    Je n'avais pas le temps de regarder ceci ce week end pour la solution.

    Les clés ici n'apportent pas grand chose au niveau consommation ressource, et c'est encore moins évident à comprendre

    Si ça t'intéresse le principe est de creer une clé ou contenu est indexé via le generate-id de son premier following-sibling possédant le même attribut class mais dont le premier following-sibling n'a pas le même attribut class.

    Ensuite tu sélectionne tous les tous contenu dont le premier following-sibling n'a pas le même attribut class et tu utilise son generate-id pour récupérer tes groupes avec key

    Simple non

  4. #4
    Nouveau candidat au Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 2
    Par défaut
    Je vais étudier tout ca, j'ai encore un peu de mal à suivre dès qu'une XSLT se complique un peu, et je vous tiens au courant !

    Je me répète mais tant pis : immense merci !!!!

Discussions similaires

  1. [SimpleXML] Recherche par valeur d'attribut récupération valeur du noeud
    Par Cortexx dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 28/02/2015, 14h34
  2. XSLT synthèse regroupée par valeurs
    Par raphael75015 dans le forum XSL/XSLT/XPATH
    Réponses: 28
    Dernier message: 03/10/2013, 10h31
  3. [XSLT 1.0] Générer des index en regroupant par valeurs d'attributs
    Par hilyd dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 17/02/2011, 15h10
  4. Regroupement par valeurs
    Par laurentabj dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 28/09/2007, 12h13
  5. [XSLT]Regroupement par attribut.
    Par zserdtfg dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 08/12/2006, 11h35

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