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 :

Supprimer les doublons en tenant compte des descendants [XSLT 2.0]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Avril 2014
    Messages : 3
    Points : 4
    Points
    4
    Par défaut Supprimer les doublons en tenant compte des descendants
    Bonjour,

    J'ai un fichier 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
    <node>
    <var @name="toto" /> 
    <var @name="tata">  <var @name="toto" />  </var>
    <var @name="tata">  <var @name="toto" >  <var @name="titi" />  </var> </var>
    <var @name="tata">  <var @name="toto" />  </var>
    <var @name="tata">  <var @name="toto" >  <var @name="titi" />  </var> </var>
    <var @name="toto" /> 
    <var @name="tata">  <var @name="toto" />  </var>
    <var @name="tata">  <var @name="toto" >  <var @name="tutu" />  </var> </var>
    <var @name="tata">  <var @name="tyty" >  <var @name="tutu" />  </var> </var>
    <var @name="tata">  <var @name="toto" >  <var @name="tutu" />  </var> </var>
    <var @name="toto">  <var @name="toto" >  <var @name="tutu" />  </var> </var>
    </node>
    Et j'aimerais généré le fichier text suivant, tel que chaque élément unique n'apparaisse qu'une fois:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Mes éléments:
    - toto
    - tata-toto
    - tata-toto-titi
    - tata-toto-tutu
    - tata-tyty-tutu
    - toto-toto-tutu
    Je précise qu'il peut y avoir n <var> en cascade (et pas seulement 3 comme dans l'exemple).

    J'utilise actuellement generate-id() en bouclant for each node/var:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <xsl:variable name="allVar" select="./node/var" />
    <xsl:for-each select="./node/var]">
        <xsl:variable name="name" select="@name" />
          <xsl:if test="generate-id() = generate-id($allVar[@name = $name][1])">  
          </xsl:if>
    </xsl:for-each>
    Mais cela ne convient pas car les descendants ne sont pas pris en compte.

    Comment feriez-vous cela ?

    Merci par avance.

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Citation Envoyé par Myrkiriad Voir le message
    Comment feriez-vous cela ?
    En Java .

    C'est pas facile du tout ton truc.
    Mais tu pourrais faire un genre de template récursif qui, pour un <var> donné et un ensemble d'autres <var> donnés, écrit le premier <var> si aucun des autres <var> de l'ensemble n'écrirait la même chose. À chaque étape il suffirait d'enlever tous les <var> de l'ensemble dont le nom n'est pas le même que celui de l'étape en cours. Et quand on a déroulé tous les descendants, s'il n'y a plus rien dans l'ensemble des autres <var>, c'est que son écriture est unique.
    Puis il n'y a plus qu'à appeler ce template sur tous les <var> enfants de node, avec comme ensemble, tous ses frères <var> précédents.

  3. #3
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Avril 2014
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    J'ai effectivement réussi avec un template récursif !

    Merci pour cette bonne piste Thelvin !

  4. #4
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Je vois dans l'un des deux lieux, le titre est marqué XSLT 2.0. Si on travaille sur XSLT 2.0, la définition de xsl:key est bien plus flexible et elle peut admettre un nombre variable de déscendants.

    On peut faire comme ça.
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
    <xsl:key name="name-chain" match="var" use="string-join((@name, (descendant::var/@name)),'-')" />
    <xsl:template match="/">
        <result>
            <xsl:apply-templates select="node" />
        </result>
    </xsl:template>
    <xsl:template match="node">
        <xsl:for-each select="var[count(.|key('name-chain', string-join((@name, (descendant::var/@name)), '-'))[1])=1]">
            <kv><xsl:value-of select="string-join((@name, (descendant::var/@name)), '-')" /></kv>
        </xsl:for-each>
    </xsl:template>
    </xsl:stylesheet>
    En XSLT 1.0, on peut faire avec une clé opérative seulement avec une assumption sur la maximum du nombre de possibles déscendants : ce qui rend le script peu agréable à l'oeil - mais c'est tout de même possible.

  5. #5
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Oooh, effectivement, bien vu le string-join() sur descendant. Je manque d'habitude du XPath 2.0.

    Du coup, en XSLT 2.0 il y a nettement plus simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:template match="node">
        <xsl:for-each select="distinct-values(for $var in var return string-join($var/descendant-or-self::var/@name, '-'))">
            <kv><xsl:value-of select="."/></kv>
        </xsl:for-each>
    </xsl:template>
    le for $var in var étant nécessaire pour dire que pour chaque var fils de node, on veut calculer une valeur.

    Et si le but était de faire un traitement sur les cas uniques, on peut remplacer le for-each distinct-values par un for-each-group.

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 17/02/2011, 17h14
  2. Comparer des colonnes dans 2 feuilles différentes et supprimer les doublons
    Par eudeline91 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 21/04/2008, 09h24
  3. Renommer des fichiers en supprimant les doublons
    Par Serge63 dans le forum VBScript
    Réponses: 5
    Dernier message: 07/03/2008, 10h36
  4. Supprimer les doublons sans tri préalable des données
    Par ouskel'n'or dans le forum Macros et VBA Excel
    Réponses: 17
    Dernier message: 20/12/2007, 08h16
  5. Réponses: 9
    Dernier message: 06/06/2007, 23h03

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