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 :

"select distinct" dynamique [XSLT 1.0]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 107
    Points : 63
    Points
    63
    Par défaut "select distinct" dynamique
    M'sieurs dames, bonjour

    Je vous explique mon souci.
    J'ai une source de données de ce genre :

    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
    <?xml version="1.0" encoding="UTF-8"?>
    <racine>
    <ligne>
    	<item1>gronk</item1>
    </ligne>
    <ligne>
    	<item1>gronk</item1>
    </ligne>
    <ligne>
    	<item2>gronk</item2>
    </ligne>
    <ligne>
    	<item2>gronk</item2>
    </ligne>
    <ligne>
    	<item1>greuh</item1>
    </ligne>
     
    <param>
    	<valeur>item1</valeur>
    </param>
    <param>
    	<valeur>item2</valeur>
    </param>
    </racine>
    ('tention, la suite est velue)

    et mon but est de trouver, pour chaque paramètre (nœud "param") le nombre de nœuds parmi les nœuds "ligne" qui ont un enfant s'appelant comme le paramètre sans compter les doublons.

    Un bon exemple, parce que sinon, c'est pas évident.

    Ici, pour le premier paramètre (item1), il y a 3 nœuds "ligne" qui ont un fils avec ce nom, mais seulement 2 qui ont des valeurs différentes (gronk et greuh).
    Pour le second paramètre (item2), il y a 2 nœuds "ligne" qui ont un fils avec ce nom, mais seulement 1 qui a une valeur différente (gronk)
    La "fonction" renvoie donc :
    item1 > 2
    item2 > 1

    Mes premiers pas :

    Me renvoie les noeuds ayant un fils avec le nom du paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <xsl:template match="racine">
      <xsl:variable name="parametre" select="param/valeur"/>
      <xsl:copy-of select="/racine/ligne/*[name() =$parametre]"></xsl:copy-of>
    </xsl:template>
    Un test de filtre pour éliminer les doublons (marche pas)
    (en dur, pas en dynamique)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <xsl:template match="racine">
      <xsl:variable name="parametre" select="param/valeur"/>
      <xsl:copy-of select="/racine/ligne/*[name() =$parametre][not(preceding-sibling::*='gronk')]"></xsl:copy-of>
    </xsl:template>
    Mais là, je tourne en rond, j'arrive à rien...

    Est-ce seulement possible ?

    Un grand merci pour toute aide possible (si je n'ai pas été clair, ne pas hésiter à me demander des éclaircissements)

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 630
    Points
    21 630
    Par défaut
    Aïe.

    On ne peut pas exprimer cette contrainte d'unicité avec du xPath, justement parce que xPath n'est pas dynamique.
    On ne peut pas non plus se servir des clés, puisque leur use serait sur quelque chose qui sera indiqué dans le document source.
    Du coup, pas moyen de faire un count().

    Et quand on ne peut pas faire de count, la solution restante est un template récursif.
    Il passerait sur toutes les ligne[*[name() = $param]], et ajouterait 1 au calcul du résultat si on ne trouve pas de précédente avec le même contenu, et renverrait le résultat inchangé sinon.

  3. #3
    Expert confirmé
    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
    Points : 4 843
    Points
    4 843
    Par défaut
    Personnellement, après avoir galéré avec des méthodes récursives qui alourdissaient mon code et que je devais constamment réécrire, j'ai fini par adopter une librairie externe qui fait ça très bien : http://www.exslt.org/set/functions/distinct/index.html.

    Après, n'étant pas un pro en XSL (je me fais juste des fichiers XSL pour des projets perso que je lance avec Firefox - il possède un parser plutôt bien fait), je ne sais pas ce que ça vaut vraiment ni même comment ça marche.

    (D'ailleurs si quelqu'un ici peut me dire pourquoi quand on va à l'URL donnée par leur namespace (http://exslt.org/sets) ça renvoie un 404 mais que si on change ce namespace dans la déclaration, le XSL ne fonctionne plus ?)

    Soit dit en passant ils fournissent aussi d'autres librairies super pratiques, comme les expressions régulières !

    En espérant que ça puisse aider,
    Loceka.

  4. #4
    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
    Points : 10 927
    Points
    10 927
    Par défaut
    Citation Envoyé par thelvin Voir le message
    On ne peut pas non plus se servir des clés, puisque leur use serait sur quelque chose qui sera indiqué dans le document source.
    Il faut juste adapter la clé, même principe qu'un regroupement


    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
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    	<xsl:key use="concat(name(),'//',.)" match="ligne/*" name="item"/>
    	<xsl:template match="/">
    		<test>
    			<xsl:for-each select="racine/param">
    				<i>
    					<xsl:value-of select="."/> : <xsl:value-of select="count(/racine/ligne/*[generate-id(.)=generate-id(key('item',concat(current(),'//',.))[1])])"/>
     
    				</i>
    			</xsl:for-each>
    		</test>
    	</xsl:template>
    </xsl:stylesheet>
    J'ai pris comme séparateur // au niveau de la clé, ce n'est pas nécessairement le plus adapté.

  5. #5
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 630
    Points
    21 630
    Par défaut
    Ah, oui, mince. Je me doutais que j'avais loupé un truc mais je voyais pas quoi.

    Citation Envoyé par Loceka Voir le message
    Personnellement, après avoir galéré avec des méthodes récursives qui alourdissaient mon code et que je devais constamment réécrire, j'ai fini par adopter une librairie externe qui fait ça très bien : http://www.exslt.org/set/functions/distinct/index.html.
    Hum. Je ne vois pas comment cette fonction résoudrait le problème. D'un autre côté, je ne voyais pas non plus comment utiliser les clés pour ça.
    'Faudrait que j'essaie de prouver les choses mathématiquement.

    Citation Envoyé par Loceka Voir le message
    (D'ailleurs si quelqu'un ici peut me dire pourquoi quand on va à l'URL donnée par leur namespace (http://exslt.org/sets) ça renvoie un 404 mais que si on change ce namespace dans la déclaration, le XSL ne fonctionne plus ?)
    Parce que les namespaces ne sont pas des URL mais des URI. Ils ne servent pas à dire "où on peut trouver" des ressources, ils servent à les identifier de façon unique. Ce sont des noms, quoi. Si on me dit Loceka, je vais pas taper ça dans mon GPS en pensant que ça me dira où tu es. Je me dirai que c'est ton nom. Les URI, c'est pareil, mais c'est étudié pour pouvoir être unique.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 107
    Points : 63
    Points
    63
    Par défaut
    Un grand MERCI à vous pour votre contribution à ma problématique (spéciale dédicace à Erwy ).

    J'avais effectivement commencé à étudier le principe des clefs pour résoudre mon souci, mais sans succès. En voyant la solution, je comprend pourquoi : c'était loin d'être évident...

    Vais être obligé de continuer à bosser, maintenant, moi, c'est malin

    Bonne journée à vous.

  7. #7
    Expert confirmé
    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
    Points : 4 843
    Points
    4 843
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Hum. Je ne vois pas comment cette fonction résoudrait le problème.
    Comme ç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:stylesheet
    		id="stylesheet"
    		version="1.0"
    		xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    		xmlns:set="http://exslt.org/sets">
     
    	<xsl:template match="/">
    		<xsl:apply-templates select="/racine/param/valeur"/>
    	</xsl:template>
     
    	<xsl:template match="valeur">
    		<xsl:value-of select="."/><xsl:text> : </xsl:text>
    		<xsl:copy-of select="count(set:distinct(/racine/ligne/*[name() = current()]))"/><xsl:text> ; </xsl:text>
    	</xsl:template>
    </xsl:stylesheet>

  8. #8
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 630
    Points
    21 630
    Par défaut
    De fait. 'Y a pas, j'ai un problème pour modéliser ce besoin. La prochaine fois, je ferai un schéma papier.

    Je viens de comprendre ce qui me gêne, toutefois : je suis parti du principe qu'une <ligne> peut avoir plusieurs enfants, éventuellement de noms différents. Or, ce qu'on compte, c'est les lignes, pas les enfants de lignes.

    Mais on devrait pouvoir s'en sortir quand même, en comptant "les enfants de ligne qui répondent aux conditions et n'ont pas de preceding-sibling qui y réponde."

    Edit : Ouais non. Ma gêne venait du fait que "ne pas compter les doublons" est assez confus si une <ligne> peut avoir plusieurs enfants de même nom. C'est donc sûrement pas le cas.

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

Discussions similaires

  1. Passage d'un paramètre avec quote pour une procédure dynamique
    Par dcarroz dans le forum Développement
    Réponses: 7
    Dernier message: 26/01/2010, 11h06
  2. Select distinct et order by
    Par arsgunner dans le forum Langage SQL
    Réponses: 2
    Dernier message: 17/06/2004, 11h17
  3. equivalent SELECT DISTINCT pour MyBase?
    Par chrisou31 dans le forum Bases de données
    Réponses: 2
    Dernier message: 08/03/2004, 19h33

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