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 :

Generation d'un index à partir de plusieurs noeuds [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 averti
    Homme Profil pro
    Débutant en XSLT
    Inscrit en
    Avril 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Débutant en XSLT

    Informations forums :
    Inscription : Avril 2011
    Messages : 54
    Par défaut Generation d'un index à partir de plusieurs noeuds
    Bonjour,

    Je planche sur un problème depuis quelques semaines, je viens sollicité votre aide pour me donner des pistes !

    J'aimerais générer un index d'auteurs pour un PDF qui fait une liste de livres.
    Je peux avoir plusieurs auteurs pour un même livre.

    J'ai pas mal de contraintes sur le XML en entrée (il est généré automatiquement à partir d'un fichier Excel) du coup, j'ai deux configurations de XML possibles :

    1- Soit mes auteurs se trouvent dans des noeuds séparés et de nom différents.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <Livre>
      <titre>Exemple de titre</titre>
      <auteur1>Robert Michel</auteur1>
      <auteur2>Roland Paul</auteur2>
      <auteur3></auteur3>
      <parution>1999</parution>
      <edition>Castor</edition>
    </livre>
    (Dans tous les cas les 3 noeuds auteurs existeront mais pourront être vide. Cette config me limite à 3 auteurs possibles.)

    2- Soit j'écris tous mes auteurs dans un seul noeud et je les sépare par des virgules
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <Livre>
      <titre>Exemple de titre</titre>
      <auteurs>Robert Michel,Roland Paul</auteurs>
      <parution>1999</parution>
      <edition>Castor</edition>
    </livre>
    (Dans cette config, j'ai un nombre illimité d'auteurs possibles, mais encore faut-il que je séparer les auteurs ensuite pour pouvoir les traiter dans mon index!)


    Je dois regrouper les auteurs par leur première lettre ex :
    A
    Albert Michel
    Alain Francois
    Alan Grant
    B
    Bernard Philippe
    Bertrand Jean
    C
    ....
    Je dois aussi dédoublonner mes auteurs qui sont listés plusieurs fois dans le PDF (ils ne doivent apparaître qu'une fois dans l'index).

    Aujourd'hui, j'y arrive pour un seul noeud et j'utilise un xsl:key de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:key name="PremLettreAuteur" match="auteur1" use="translate(substring(auteur1, 1, 1),'àâäáîïíôöóùûüéèêëçñÀÂÁÅÃÇÉÊÈËÑÓÔÒÕÖÚÛÙÜ','aaaaiiiooouuueeeecnAAAAACEEEENOOOOOUUUU')"/>
    Puis, pour générer mon index j'utilise :
    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="//livre[count(. | key('PremLettreAuteur', translate(substring(auteur1, 1, 1),$strFrom,$strTo))[1]) = 1]">
      <xsl:sort select="auteur1"/>
      <fo:block>
        <xsl:value-of select="translate(substring(auteur1, 1, 1),$strFrom,$strTo)"/>
      </fo:block>
      <xsl:for-each select="key('PremLettreAuteur', translate(substring(auteur1, 1, 1),$strFrom,$strTo))">
        <xsl:sort select="auteur1"/>
        <fo:block>
          <xsl:apply-templates select="current()[not(preceding::auteur1=auteur1)]" mode="INDEXAUTEURS"/> <!-- La template qui met en page -->
        </fo:block>
      </xsl:for-each>
    </xsl:for-each>

    Comment je dois m'y prendre pour inclure d'autres noeud dans mon traitement pour l'index ?
    Pour la solution de la liste d'auteurs séparés par des virgules, comment puis-je séparer mes auteurs et les traiter indépendamment ensuite ?

    Toute piste me sera très précieuse !

    Merci.

  2. #2
    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
    Etant donné que tu es en XSLT2.0, c'est relativement faisable :

    Pour dédoublonner les auteurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <xsl:template match="/">
      <xsl:variable name="all_authors">
        <authors>
          <xsl:apply-templates select="//auteurs" mode="list"/>
        </authors>
      </xsl:variable>
      <xsl:variable name="distinct_authors" select="distinct-values($all_authors/authors/author)"/>
    </xsl:template>
     
    <xsl:template match="auteurs" mode="list">
      <xsl:for-each select="tokenize(., ',')">
        <author>.</author>
      </xsl:for-each>
    </xsl:template>
    Après pour les regrouper par nom, il suffit d'utiliser un xsl:sort dans un for-each sur la variable $distinct_authors.

    Je n'ai pas testé mais ça devrait marcher.

  3. #3
    Membre averti
    Homme Profil pro
    Débutant en XSLT
    Inscrit en
    Avril 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Débutant en XSLT

    Informations forums :
    Inscription : Avril 2011
    Messages : 54
    Par défaut
    Super !

    Je teste ca demain matin et je reviens éventuellement si je rencontre des soucis.
    *Je repasserais mettre le sujet en résolu si c'est le cas*

    En tout cas merci beaucoup du tuyau !
    J'ai encore beaucoup à apprendre de xsl...

  4. #4
    Membre averti
    Homme Profil pro
    Débutant en XSLT
    Inscrit en
    Avril 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Débutant en XSLT

    Informations forums :
    Inscription : Avril 2011
    Messages : 54
    Par défaut
    Bon, comme mauvaise nouvelle, je viens de me rendre compte que le processeur (XEP) n'est qu'en version XSLT 1.0 ...

    J'ai tenté de faire un "tokenize" avec une template récursive (en adaptant un bout de code chopé du web) :
    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
     
    <xsl:template match="auteurs" name="tokenize-blocks" mode="list">
       <xsl:param name="text"/>
       <xsl:choose>
         <xsl:when test="contains($text,',')">
           <author>
             <xsl:value-of select="substring-before($text,',')"/>
           </author>
           <xsl:call-template name="tokenize-blocks">
             <xsl:with-param name="text" select="substring-after($text,',')"/>
           </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
           <author>
             <xsl:value-of select="$text"/>
           </author>
         </xsl:otherwise>
       </xsl:choose>
       </xsl:template>
    Que je stock comme ceci dans une variable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    		<xsl:variable name="all_authors">
    			<authors>
    			  <xsl:apply-templates select="//auteurs" mode="list">
    				  <xsl:with-param name="text" select="."/>
    			  </xsl:apply-templates>
    			</authors>
    		</xsl:variable>
    Et que j'affiche comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    		<xsl:for-each select="$all_authors/authors/author">
    			<xsl:sort select="author"/>
    			<xsl:value-of select="author"/>
    		</xsl:for-each>
    Là je lui demande de m'afficher une liste de tous mes auteurs, c'est pour voir si ca fonctionne.
    Or, ca ne fonctionne pas !

    Quel est mon erreur de raisonnement ?

    Merci encore.

  5. #5
    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
    Citation Envoyé par PouetteMan Voir le message
    Bon, comme mauvaise nouvelle, je viens de me rendre compte que le processeur (XEP) n'est qu'en version XSLT 1.0 ...
    Arf. Ca c'est une très mauvaise nouvelle.

    Déjà ça ne peut pas marcher parce qu'en XSLT 1.0 il n'est pas possible de "créer" du DOM dans une variable et d'utiliser ensuite cette variable dans un for-each.

    Ensuite, le template "tokenize-blocks" doit être déclaré comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <xsl:template name="tokenize-blocks" mode="list">
      <!-- ... -->
    </xsl:template>
    Et appellé comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <xsl:call-template name="tokenize-blocks" mode="list">
      <xsl:with-param name="text" select="auteurs/text()"/>
    </xsl:call-template>
    Mais pour le coup, en XSLT 1.0, je crois que cette approche serait trop complexe.

    Il vaudrait mieux passer par ta solution alternative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <Livre>
      <titre>Exemple de titre</titre>
      <auteur1>Robert Michel</auteur1>
      <auteur2>Roland Paul</auteur2>
      <auteur3></auteur3>
      <parution>1999</parution>
      <edition>Castor</edition>
    </livre>
    Je suppose que dans Excel tu peux mettre autant d'auteurs que tu veux non ? Il suffit de rajouter des colonnes auteur1... auteurN.

    Après, il est possible de les matcher comme ça : *[starts-with(local-name(), 'auteur')].

    Là il faut que j'y aille mais je peux déjà te dire qu'avec la méthode de Muench ça devrait être faisable (il y'a pas mal d'exemples sur le forum).

  6. #6
    Membre averti
    Homme Profil pro
    Débutant en XSLT
    Inscrit en
    Avril 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Débutant en XSLT

    Informations forums :
    Inscription : Avril 2011
    Messages : 54
    Par défaut
    Oui, je pense revenir sur mon autre alternative.

    Non, mes cases Excels pour les auteurs ne sont pas infinies, je n'en aurais que 4. (Ca ne pose pas de problèmes dans la pratique) Et en réalité elle n'auront pas toutes la même syntaxe de nom. (J'aurais "Auteur" et "Divers1", "Divers2" et "Divers3". Mon exemple était pour simplifier.)


    Pour utiliser la méthode Muench, je dois passer par une clé qui est aujourd'hui du type (Car je me dois de regrouper mes auteurs par leur première lettre):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <xsl:key name="PremLettreAuteur" match="livre" use="substring(Auteur, 1, 1)"/>
    Mais j'ai du mal à concevoir comment, dans ma key, je pourrais ajouter le contenu présent dans "Divers1", "Divers2"...
    Afin de pouvoir traiter la liste des éléments (Auteur, Divers1, Divers2, Divers3) confondu dans une même liste me permettant de les trier par ordre alphabétique et les regrouper par lettre.

    Merci bcp pour ton aide précieuse Loceka !

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

Discussions similaires

  1. [XL-2010] Fonction Index et équiv à partir de plusieurs colonnes
    Par qingwill dans le forum Excel
    Réponses: 2
    Dernier message: 16/11/2014, 09h36
  2. Crée image à partir de plusieurs Timage
    Par spikto dans le forum Composants VCL
    Réponses: 2
    Dernier message: 09/08/2005, 14h38
  3. [Treeview VBA] Liste des fils à partir d'un noeud donné
    Par NoCoZ dans le forum Général VBA
    Réponses: 3
    Dernier message: 26/04/2005, 09h15
  4. [ImageMagick] Générer une image à partir de plusieurs images ?
    Par fichtre! dans le forum Bibliothèques et frameworks
    Réponses: 8
    Dernier message: 16/02/2005, 15h32
  5. [SUM] récuperer une quantite a partir de plusieurs table
    Par Snowballz dans le forum PostgreSQL
    Réponses: 9
    Dernier message: 14/09/2004, 18h48

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